{"id":20331211,"url":"https://github.com/comcast/jovo-plugin-resume","last_synced_at":"2025-04-11T21:07:42.591Z","repository":{"id":40841598,"uuid":"229765274","full_name":"Comcast/jovo-plugin-resume","owner":"Comcast","description":"🔈 A plugin for resuming conversations in the Open Source Voice Layer, Jovo (https://www.jovo.tech)","archived":false,"fork":false,"pushed_at":"2023-01-06T02:46:33.000Z","size":1466,"stargazers_count":7,"open_issues_count":33,"forks_count":4,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-11T21:07:36.644Z","etag":null,"topics":["conversational-continuity","jovo","jovo-framework","jovo-plugin","resume","voice-app","voice-applications"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Comcast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-23T14:12:19.000Z","updated_at":"2020-04-20T09:20:09.000Z","dependencies_parsed_at":"2023-02-05T03:46:12.256Z","dependency_job_id":null,"html_url":"https://github.com/Comcast/jovo-plugin-resume","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fjovo-plugin-resume","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fjovo-plugin-resume/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fjovo-plugin-resume/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fjovo-plugin-resume/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Comcast","download_url":"https://codeload.github.com/Comcast/jovo-plugin-resume/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248480435,"owners_count":21110937,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conversational-continuity","jovo","jovo-framework","jovo-plugin","resume","voice-app","voice-applications"],"created_at":"2024-11-14T20:19:15.766Z","updated_at":"2025-04-11T21:07:42.563Z","avatar_url":"https://github.com/Comcast.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Jovo Resumer Plugin\n[![Build Status](https://travis-ci.org/Comcast/jovo-plugin-resume.svg?branch=master)](https://travis-ci.org/Comcast/jovo-plugin-resume)\n\n\u003eNB: this project is a WIP. We are actively working towards rolling up, testing, and providing examples!\n\nThis plugin makes it simple to integrate conversational memory into a Jovo app. It provides an easy to use API\nthat manages the data required to pause, resume, and switch between multi-step linear or non-linear conversations.\n\n\n## Install\n\n\u003e`npm i jovo-plugin-resume --save`\n\n## API\n\nThe plugin adds a new object to the Jovo object, Resumer.\nIt can be accessed in your handler function with\n`this.$resumer`\nThis object is automatically serialized and deserialized into the jovo user data object with each request, and has the following exposed methods:\n\n### switchTo(conversationName: string, startIntent: string)\n\nswitchTo acts like an intelligent toStateIntent.\nFor example:\n\n```\nstartFooHandler() {\n    if (someConditionThatStartsFoo) {\n        this.$resumer.switchTo(\"FooConversation\", \"FooIntent\");\n    }\n},\nFooConversation: {\n    FooIntent() {\n        this.followUpState(\"YesNoState\").ask(\"Welcome to the Foo conversation! Say Yes or No!\");\n    },\n\n    YesNoState: {\n        YesIntent() {\n            ...\n        },\n        NoIntent() {\n            ...\n        }\n    },\n    ...\n}\n```\nWhen FooConversation is first started, the switchTo is functionally identical to\n`toStateIntent(\"FooConversation\", \"FooIntent\")`\nIf the user starts FooConversation, then answers yes to the intial question, they are in the YesNoState, part of\nFooConversation. Now if the user closes out of the app, and hits the startFooHandler again, switchTo will not bring them\nto the FooIntent handler, but will bring them to the YesIntent handler that they left off in. All requests\n(accross any session) are now automatically saved as a marker for the current conversation.\nThis can be controlled with the following methods:\n\n### endCurrent()\nSignals that the conversation currently in progress has reached its end.\n\n### pauseCurrent()\nCall this to preserve the progress of the current conversation, but stop interacting with.\n\n### ignore()\nTells the resumer to not update the conversation with the current request. Use this for intents that do not\nprogress the conversation, such as Fallback, Unhandled, Help, etc...\n\n\n### Handling a Resume\nThe way to determine if handler code is running under the context of a normal request, or from a resume,\nthe field actionData will either be set or not set. So when a resume happens $resumer.actionData will be an object\nwith the following fields:\n\n```\ncomingFrom: ConversationStatus,\nresumingInto: ConversationStatus\n```\n\nwhere ConversationStatus is an object with the following fields:\n\n```\nname: string, // the conversation name, empty string if not in a conversation\n// Important information about the last request in this conversation\nintent: string,\nstate: string,\ntimestamp: string,\nslots: Object\n```\n\nSo to write a handler function that can gracefully be resumed into:\n```\nhandler() {\n    let resumeData = this.$resumer.actionData;\n    if (resumeData) {\n        // Handle this intent in the context of a resume\n        console.log(`This conversation is being resumed from ${resumeData.comingFrom.name}`);\n        console.log(`This conversation was left at this point at ${resumeData.resumingInto.timestamp}`);\n    } else {\n        // Handle this intent like normal\n    }\n}\n```\n\n\n### Code Examples\n```\napp.setHandler({\n\n    ConversationStarter() {\n        let slots = this.$inputs;\n        // Resumer maintains input history, so one intent handler\n        // is able to start multiple conversations\n        if (slots.foo.value) {\n            this.$resumer.switchTo(\"foo\", \"fooStart\");\n        } else if (slots.bar.value) {\n            this.$resumer.switchTo(\"bar\", \"barStart\");\n        }\n    },\n\n    foo: {\n        fooStart() {\n            this.followUpState(\"Foo.Question\").ask(\"Say yes or no\");\n        },\n        Question: {\n            YesIntent() {\n                this.followUpState(\"Question2\").ask(\"Say your name\");\n            },\n\n            NoIntent() {\n                this.$resumer.endCurrent(); // This intent means that the foo conversation is done\n                this.removeState().ask(\"Start a new Conversation!\");\n            }\n        }\n    },\n    Question2: {\n        MyNameIsIntent() {\n            // States don't have to be within the foo state to be part of the conversation\n            this.$resumer.ignore(); // However we don't want this intent to be saved to foo\n            this.removeState().ask();\n        },\n\n        NoIntent() {\n            let resumeData = this.$resumer.actionData;\n            if (resumeData) {\n                // The user got to this point in foo previously\n                // They have restarted it, and we want to ask them again in maybe a gentler, different way\n                this.ask(\n                \"Hey, last time we talked I asked you for your name, but you didnt' want to tell me it.\" +\n                \" Do you want to tell me it now?\")\n            } else {\n                // The user declined entering their name for the first time\n                // We want to remember that they are at the point in foo where their name is asked\n                // but we want to move on to something else for now\n                this.$resumer.pauseCurrent();\n                this.removeState().ask(\"That's ok, we can try again later!\");\n            }\n\n        }\n    }\n\n    bar: {\n        barStart() {\n            this.followUpState(\"bar.StartFoo\").ask(\"Do you want to start the foo conversation?\");\n        },\n\n        startFoo: {\n            YesIntent() {\n                // saves that we have started the bar conversation\n                // but switching the focus over to foo\n                this.$resumer.switchTo(\"foo\", \"startFoo\");\n            }\n        }\n    }\n})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomcast%2Fjovo-plugin-resume","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomcast%2Fjovo-plugin-resume","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomcast%2Fjovo-plugin-resume/lists"}