@guava-ai/guava-sdk 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/examples/example.test.d.ts +5 -0
- package/dist/examples/example.test.js +46 -0
- package/dist/examples/example.test.js.map +1 -0
- package/dist/examples/help-desk.d.ts +3 -1
- package/dist/examples/help-desk.js +25 -9
- package/dist/examples/help-desk.js.map +1 -1
- package/dist/examples/property-insurance.js +4 -1
- package/dist/examples/property-insurance.js.map +1 -1
- package/dist/examples/restaurant-waitlist.js +4 -1
- package/dist/examples/restaurant-waitlist.js.map +1 -1
- package/dist/examples/scheduling-outbound.js +6 -0
- package/dist/examples/scheduling-outbound.js.map +1 -1
- package/dist/src/action-item.d.ts +4 -4
- package/dist/src/agent.d.ts +81 -16
- package/dist/src/agent.js +394 -127
- package/dist/src/agent.js.map +1 -1
- package/dist/src/auth.d.ts +27 -0
- package/dist/src/auth.js +127 -0
- package/dist/src/auth.js.map +1 -0
- package/dist/src/call.d.ts +1 -1
- package/dist/src/call.js +2 -2
- package/dist/src/call.js.map +1 -1
- package/dist/src/client.d.ts +4 -11
- package/dist/src/client.js +22 -14
- package/dist/src/client.js.map +1 -1
- package/dist/src/commands.d.ts +3 -3
- package/dist/src/events.d.ts +22 -0
- package/dist/src/events.js +19 -5
- package/dist/src/events.js.map +1 -1
- package/dist/src/helpers/llm.d.ts +2 -0
- package/dist/src/helpers/llm.js +17 -0
- package/dist/src/helpers/llm.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +5 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/logging.js +16 -11
- package/dist/src/logging.js.map +1 -1
- package/dist/src/socket/call-info.d.ts +35 -0
- package/dist/src/socket/call-info.js +59 -0
- package/dist/src/socket/call-info.js.map +1 -0
- package/dist/src/socket/client.d.ts +51 -0
- package/dist/src/socket/client.js +455 -0
- package/dist/src/socket/client.js.map +1 -0
- package/dist/src/socket/listen-inbound.d.ts +83 -0
- package/dist/src/socket/listen-inbound.js +82 -0
- package/dist/src/socket/listen-inbound.js.map +1 -0
- package/dist/src/socket/protocol.d.ts +127 -0
- package/dist/src/socket/protocol.js +69 -0
- package/dist/src/socket/protocol.js.map +1 -0
- package/dist/src/socket/utils.d.ts +8 -0
- package/dist/src/socket/utils.js +26 -0
- package/dist/src/socket/utils.js.map +1 -0
- package/dist/src/telemetry.d.ts +3 -3
- package/dist/src/telemetry.js +9 -7
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/testing/chat.d.ts +2 -0
- package/dist/src/testing/chat.js +181 -0
- package/dist/src/testing/chat.js.map +1 -0
- package/dist/src/testing/mocks.d.ts +6 -0
- package/dist/src/testing/mocks.js +14 -0
- package/dist/src/testing/mocks.js.map +1 -0
- package/dist/src/testing/protocol.d.ts +46 -0
- package/dist/src/testing/protocol.js +61 -0
- package/dist/src/testing/protocol.js.map +1 -0
- package/dist/src/testing/session.d.ts +26 -0
- package/dist/src/testing/session.js +219 -0
- package/dist/src/testing/session.js.map +1 -0
- package/dist/src/utils.d.ts +1 -0
- package/dist/src/utils.js +15 -1
- package/dist/src/utils.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/examples/example.test.ts +58 -0
- package/examples/help-desk.ts +14 -3
- package/examples/property-insurance.ts +3 -1
- package/examples/restaurant-waitlist.ts +3 -1
- package/examples/scheduling-outbound.ts +7 -0
- package/package.json +9 -1
- package/src/agent.ts +372 -162
- package/src/auth.ts +109 -0
- package/src/call.ts +3 -3
- package/src/client.ts +32 -15
- package/src/events.ts +24 -10
- package/src/helpers/llm.ts +20 -0
- package/src/index.ts +2 -0
- package/src/logging.ts +21 -13
- package/src/socket/call-info.ts +30 -0
- package/src/socket/client.ts +433 -0
- package/src/socket/listen-inbound.ts +62 -0
- package/src/socket/protocol.ts +89 -0
- package/src/socket/utils.ts +25 -0
- package/src/telemetry.ts +11 -8
- package/src/testing/chat.ts +196 -0
- package/src/testing/mocks.ts +12 -0
- package/src/testing/protocol.ts +40 -0
- package/src/testing/session.ts +218 -0
- package/src/utils.ts +15 -1
- package/src/version.ts +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent testing example — demonstrates agent.test(), agent.testRoleplay(),
|
|
4
|
+
* agent.patch(), and session.evaluate().
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const guava_sdk_1 = require("@guava-ai/guava-sdk");
|
|
8
|
+
const help_desk_1 = require("@guava-ai/guava-sdk/examples/help-desk");
|
|
9
|
+
describe("HelpDeskAgent", () => {
|
|
10
|
+
test("handler unit test - new purchase routes to sales", async () => {
|
|
11
|
+
const suggestion = await help_desk_1.agent.handlers.onActionRequest(new guava_sdk_1.MockCall(), "make a new purchase");
|
|
12
|
+
expect(suggestion).toHaveProperty("key", "sales");
|
|
13
|
+
});
|
|
14
|
+
test("new purchase routes to sales", async () => {
|
|
15
|
+
const session = await help_desk_1.agent.test(async (session) => {
|
|
16
|
+
// Wait for the agent to finish its opening turn, then inject a caller utterance.
|
|
17
|
+
await session.waitForTurn();
|
|
18
|
+
session.say("Hi, I'm looking to make a new purchase.");
|
|
19
|
+
// Wait for the bot to complete its transfer.
|
|
20
|
+
await session.waitForEnd();
|
|
21
|
+
});
|
|
22
|
+
// You can inspect the full transcript with session.getTranscript()
|
|
23
|
+
expect(session.executedActions).toContain("sales");
|
|
24
|
+
expect(session.terminationReason).toBe("bot-transfer");
|
|
25
|
+
});
|
|
26
|
+
test("roleplay - caller buys a table", async () => {
|
|
27
|
+
// testRoleplay() drives the conversation automatically using an LLM as the caller.
|
|
28
|
+
const session = await help_desk_1.agent.testRoleplay("You are a caller trying to buy a new table.");
|
|
29
|
+
expect(session.executedActions).toContain("sales");
|
|
30
|
+
expect(session.terminationReason).toBe("bot-transfer");
|
|
31
|
+
});
|
|
32
|
+
test("patched agent - sales department closed", async () => {
|
|
33
|
+
// patch() returns a shallow clone with independently overridable callbacks.
|
|
34
|
+
const patched = help_desk_1.agent.patch();
|
|
35
|
+
patched.onAction("sales", async (call) => {
|
|
36
|
+
call.hangup("Tell the caller that the sales department is closed and that they should call back tomorrow from 9am to 5pm.");
|
|
37
|
+
});
|
|
38
|
+
const session = await patched.testRoleplay("You are a caller trying to buy a new table.");
|
|
39
|
+
// evaluate() uses an LLM to check natural-language pass/fail criteria against the transcript.
|
|
40
|
+
await session.evaluate({
|
|
41
|
+
passCriteria: ["The agent informed the caller of the business hours from 9am to 5pm."],
|
|
42
|
+
failCriteria: ["The agent transferred the caller to the sales department."],
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=example.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.test.js","sourceRoot":"","sources":["../../examples/example.test.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAGH,mDAA+C;AAC/C,sEAA+D;AAE/D,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,UAAU,GAAG,MAAM,iBAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,oBAAQ,EAAE,EAAE,qBAAqB,CAAC,CAAC;QAC/F,MAAM,CAAC,UAAU,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,OAAO,GAAG,MAAM,iBAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YACjD,iFAAiF;YACjF,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;YAEvD,6CAA6C;YAC7C,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,mEAAmE;QAEnE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAChD,mFAAmF;QACnF,MAAM,OAAO,GAAG,MAAM,iBAAK,CAAC,YAAY,CAAC,6CAA6C,CAAC,CAAC;QAExF,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACzD,4EAA4E;QAC5E,MAAM,OAAO,GAAG,iBAAK,CAAC,KAAK,EAAE,CAAC;QAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,IAAU,EAAE,EAAE;YAC7C,IAAI,CAAC,MAAM,CACT,8GAA8G,CAC/G,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,6CAA6C,CAAC,CAAC;QAE1F,8FAA8F;QAC9F,MAAM,OAAO,CAAC,QAAQ,CAAC;YACrB,YAAY,EAAE,CAAC,sEAAsE,CAAC;YACtF,YAAY,EAAE,CAAC,2DAA2D,CAAC;SAC5E,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -33,12 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.agent = void 0;
|
|
36
37
|
exports.run = run;
|
|
37
38
|
const guava = __importStar(require("@guava-ai/guava-sdk"));
|
|
38
39
|
const openai_1 = require("@guava-ai/guava-sdk/helpers/openai");
|
|
39
40
|
const example_data_1 = require("@guava-ai/guava-sdk/example-data");
|
|
40
41
|
const guava_sdk_1 = require("@guava-ai/guava-sdk");
|
|
41
|
-
|
|
42
|
+
exports.agent = new guava.Agent({
|
|
42
43
|
name: "Nova",
|
|
43
44
|
organization: "Clearfield Home & Living",
|
|
44
45
|
purpose: "Answer questions and route callers to the appropriate department.",
|
|
@@ -46,26 +47,41 @@ const agent = new guava.Agent({
|
|
|
46
47
|
const logger = (0, guava_sdk_1.getDefaultLogger)();
|
|
47
48
|
const documentQA = new openai_1.DocumentQA("clearfield-home-living-qa", example_data_1.FURNITURE_RETAILER_QA);
|
|
48
49
|
const intentRecognizer = new openai_1.IntentRecognizer(["sales", "delivery-and-returns", "account-management", "other"], logger);
|
|
49
|
-
agent.onQuestion(async (_call, question) => {
|
|
50
|
+
exports.agent.onQuestion(async (_call, question) => {
|
|
50
51
|
return await documentQA.ask(question);
|
|
51
52
|
});
|
|
52
|
-
agent.onActionRequest(async (_call, request) => {
|
|
53
|
+
exports.agent.onActionRequest(async (_call, request) => {
|
|
53
54
|
const key = await intentRecognizer.classify(request);
|
|
54
55
|
return { key };
|
|
55
56
|
});
|
|
56
|
-
agent.onAction("sales", async (call) => {
|
|
57
|
+
exports.agent.onAction("sales", async (call) => {
|
|
57
58
|
call.transfer("+15555555555", "Notify the caller that you will be transferring them to the Sales department.");
|
|
58
59
|
});
|
|
59
|
-
agent.onAction("delivery-and-returns", async (call) => {
|
|
60
|
+
exports.agent.onAction("delivery-and-returns", async (call) => {
|
|
60
61
|
call.transfer("+15555555555", "Notify the caller that you will be transferring them to the Delivery and Returns department.");
|
|
61
62
|
});
|
|
62
|
-
agent.onAction("account-management", async (call) => {
|
|
63
|
+
exports.agent.onAction("account-management", async (call) => {
|
|
63
64
|
call.transfer("+15555555555", "Notify the caller that you will be transferring them to the Account Management department.");
|
|
64
65
|
});
|
|
65
|
-
agent.onAction("other", async (call) => {
|
|
66
|
+
exports.agent.onAction("other", async (call) => {
|
|
66
67
|
call.transfer("+15555555555", "Notify the caller that you will be connecting them with a service representative.");
|
|
67
68
|
});
|
|
68
|
-
async function run(
|
|
69
|
-
|
|
69
|
+
async function run(args) {
|
|
70
|
+
if (args.includes("--webrtc")) {
|
|
71
|
+
await exports.agent.listenWebrtc();
|
|
72
|
+
}
|
|
73
|
+
else if (args.includes("--phone")) {
|
|
74
|
+
exports.agent.listenPhone(process.env.GUAVA_AGENT_NUMBER);
|
|
75
|
+
}
|
|
76
|
+
else if (args.includes("--local")) {
|
|
77
|
+
await exports.agent.callLocal();
|
|
78
|
+
}
|
|
79
|
+
else if (args.includes("--chat")) {
|
|
80
|
+
await exports.agent.chat();
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.error("Usage: guava-example help-desk --phone | --webrtc | --local | --chat");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
70
86
|
}
|
|
71
87
|
//# sourceMappingURL=help-desk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-desk.js","sourceRoot":"","sources":["../../examples/help-desk.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"help-desk.js","sourceRoot":"","sources":["../../examples/help-desk.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,kBAaC;AAtED,2DAA6C;AAC7C,+DAAkF;AAClF,mEAAyE;AACzE,mDAAuD;AAE1C,QAAA,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC;IACnC,IAAI,EAAE,MAAM;IACZ,YAAY,EAAE,0BAA0B;IACxC,OAAO,EAAE,mEAAmE;CAC7E,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAA,4BAAgB,GAAE,CAAC;AAElC,MAAM,UAAU,GAAG,IAAI,mBAAU,CAAC,2BAA2B,EAAE,oCAAqB,CAAC,CAAC;AAEtF,MAAM,gBAAgB,GAAG,IAAI,yBAAgB,CAC3C,CAAC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,OAAO,CAAU,EACzE,MAAM,CACP,CAAC;AAEF,aAAK,CAAC,UAAU,CAAC,KAAK,EAAE,KAAiB,EAAE,QAAgB,EAAE,EAAE;IAC7D,OAAO,MAAM,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC;AAEH,aAAK,CAAC,eAAe,CAAC,KAAK,EAAE,KAAiB,EAAE,OAAe,EAAE,EAAE;IACjE,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,EAAE,GAAG,EAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AAEH,aAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,IAAgB,EAAE,EAAE;IACjD,IAAI,CAAC,QAAQ,CACX,cAAc,EACd,+EAA+E,CAChF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,aAAK,CAAC,QAAQ,CAAC,sBAAsB,EAAE,KAAK,EAAE,IAAgB,EAAE,EAAE;IAChE,IAAI,CAAC,QAAQ,CACX,cAAc,EACd,8FAA8F,CAC/F,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,aAAK,CAAC,QAAQ,CAAC,oBAAoB,EAAE,KAAK,EAAE,IAAgB,EAAE,EAAE;IAC9D,IAAI,CAAC,QAAQ,CACX,cAAc,EACd,4FAA4F,CAC7F,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,aAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,IAAgB,EAAE,EAAE;IACjD,IAAI,CAAC,QAAQ,CACX,cAAc,EACd,mFAAmF,CACpF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEI,KAAK,UAAU,GAAG,CAAC,IAAc;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,aAAK,CAAC,YAAY,EAAE,CAAC;IAC7B,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,aAAK,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAmB,CAAC,CAAC;IACrD,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,MAAM,aAAK,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,aAAK,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -60,8 +60,11 @@ async function run(args) {
|
|
|
60
60
|
else if (args.includes("--local")) {
|
|
61
61
|
await agent.callLocal();
|
|
62
62
|
}
|
|
63
|
+
else if (args.includes("--chat")) {
|
|
64
|
+
await agent.chat();
|
|
65
|
+
}
|
|
63
66
|
else {
|
|
64
|
-
console.error("Usage: guava-example property-insurance --phone | --webrtc | --local");
|
|
67
|
+
console.error("Usage: guava-example property-insurance --phone | --webrtc | --local | --chat");
|
|
65
68
|
process.exit(1);
|
|
66
69
|
}
|
|
67
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"property-insurance.js","sourceRoot":"","sources":["../../examples/property-insurance.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,
|
|
1
|
+
{"version":3,"file":"property-insurance.js","sourceRoot":"","sources":["../../examples/property-insurance.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,kBAaC;AAjCD,2DAA6C;AAC7C,+DAAgE;AAChE,mEAA6E;AAE7E,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC;IAC5B,YAAY,EAAE,kCAAkC;IAChD,OAAO,EAAE,wFAAwF;CAClG,CAAC,CAAC;AAEH,8EAA8E;AAC9E,yCAAyC;AACzC,MAAM,UAAU,GAAG,IAAI,mBAAU,CAAC,kCAAkC,EAAE,wCAAyB,CAAC,CAAC;AAEjG,qGAAqG;AACrG,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,IAAgB,EAAE,QAAgB,EAAE,EAAE;IAC5D,4EAA4E;IAC5E,2DAA2D;IAC3D,OAAO,MAAM,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC;AAEI,KAAK,UAAU,GAAG,CAAC,IAAc;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC;IAC7B,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAmB,CAAC,CAAC;IACrD,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,+EAA+E,CAAC,CAAC;QAC/F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -78,8 +78,11 @@ async function run(args) {
|
|
|
78
78
|
else if (args.includes("--local")) {
|
|
79
79
|
await agent.callLocal();
|
|
80
80
|
}
|
|
81
|
+
else if (args.includes("--chat")) {
|
|
82
|
+
await agent.chat();
|
|
83
|
+
}
|
|
81
84
|
else {
|
|
82
|
-
console.error("Usage: guava-example restaurant-waitlist --phone | --webrtc | --local");
|
|
85
|
+
console.error("Usage: guava-example restaurant-waitlist --phone | --webrtc | --local | --chat");
|
|
83
86
|
process.exit(1);
|
|
84
87
|
}
|
|
85
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restaurant-waitlist.js","sourceRoot":"","sources":["../../examples/restaurant-waitlist.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,
|
|
1
|
+
{"version":3,"file":"restaurant-waitlist.js","sourceRoot":"","sources":["../../examples/restaurant-waitlist.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,kBAaC;AAzDD,2DAA6C;AAC7C,mDAAuD;AAEvD,MAAM,MAAM,GAAG,IAAA,4BAAgB,GAAE,CAAC;AAElC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC;IAC5B,IAAI,EAAE,KAAK;IACX,YAAY,EAAE,aAAa;IAC3B,OAAO,EAAE,8CAA8C;CACxD,CAAC,CAAC;AAEH,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,SAAyB,EAAE,EAAE;IACvD,6FAA6F;IAC7F,8FAA8F;IAC9F,uBAAuB;IACvB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,IAAgB,EAAE,EAAE;IAC3C,MAAM,IAAI,CAAC,OAAO,CAAC;QACjB,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,2EAA2E;QACtF,SAAS,EAAE;YACT,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;YAC5F,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;YACzF,KAAK,CAAC,KAAK,CAAC;gBACV,GAAG,EAAE,cAAc;gBACnB,SAAS,EAAE,MAAM;gBACjB,WAAW,EAAE,8CAA8C;aAC5D,CAAC;YACF,sDAAsD;SACvD;KACF,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,IAAgB,EAAE,EAAE;IAC1D,MAAM,CAAC,IAAI,CACT,qCAAqC,EACrC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAClC,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAClC,CAAC;IACF,MAAM,IAAI,CAAC,MAAM,CAAC,0EAA0E,CAAC,CAAC;AAChG,CAAC,CAAC,CAAC;AAEI,KAAK,UAAU,GAAG,CAAC,IAAc;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC;IAC7B,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAmB,CAAC,CAAC;IACrD,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;QAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -74,9 +74,15 @@ agent.onTaskComplete("schedule_appointment", async (call) => {
|
|
|
74
74
|
await call.hangup("Thank them for their time and hang up the call.");
|
|
75
75
|
});
|
|
76
76
|
async function run(args) {
|
|
77
|
+
if (args.includes("--chat")) {
|
|
78
|
+
const patientName = args[args.indexOf("--chat") + 1] ?? "Benjamin Buttons";
|
|
79
|
+
await agent.chat({ patientName });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
77
82
|
const [toNumber, patientName = "Benjamin Buttons"] = args;
|
|
78
83
|
if (!toNumber) {
|
|
79
84
|
console.error("Usage: guava-example scheduling-outbound <phone> [name]");
|
|
85
|
+
console.error(" guava-example scheduling-outbound --chat [name]");
|
|
80
86
|
process.exit(1);
|
|
81
87
|
}
|
|
82
88
|
agent.callPhone(process.env.GUAVA_AGENT_NUMBER, toNumber, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduling-outbound.js","sourceRoot":"","sources":["../../examples/scheduling-outbound.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,
|
|
1
|
+
{"version":3,"file":"scheduling-outbound.js","sourceRoot":"","sources":["../../examples/scheduling-outbound.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,kBAkBC;AA/DD,2DAA6C;AAC7C,+DAAoE;AACpE,mEAA6E;AAE7E,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC;IAC5B,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,qEAAqE;CAC/E,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,IAAI,uBAAc,CAAC;IACxC,UAAU,EAAE,IAAA,wCAAyB,GAAE;CACxC,CAAC,CAAC;AAEH,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,IAAgB,EAAE,EAAE;IAC3C,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,aAAa,CAAC,kBAAkB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IAC7D,OAAO,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,IAAgB,EAAE,OAAe,EAAE,EAAE;IAC9D,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,MAAM,IAAI,CAAC,OAAO,CAAC;YACjB,MAAM,EAAE,sBAAsB;YAC9B,SAAS,EAAE;gBACT,+EAA+E;gBAC/E,KAAK,CAAC,KAAK,CAAC;oBACV,GAAG,EAAE,kBAAkB;oBACvB,SAAS,EAAE,eAAe;oBAC1B,WAAW,EAAE,uCAAuC;oBACpD,UAAU,EAAE,IAAI;iBACjB,CAAC;gBACF,iGAAiG;aAClG;SACF,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,CAAC,MAAM,CAAC,kDAAkD,CAAC,CAAC;IACxE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,cAAc,CAAC,sBAAsB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAC1D,MAAM,IAAI,CAAC,MAAM,CAAC,iDAAiD,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEI,KAAK,UAAU,GAAG,CAAC,IAAc;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,kBAAkB,CAAC;QAC3E,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IAED,MAAM,CAAC,QAAQ,EAAE,WAAW,GAAG,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAE1D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACzE,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,EAAE;QACxD,WAAW,EAAE,WAAW;KACzB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
export declare const FieldItemType: z.ZodUnion<z.ZodLiteral<"text" | "
|
|
2
|
+
export declare const FieldItemType: z.ZodUnion<z.ZodLiteral<"text" | "date" | "datetime" | "integer" | "multiple_choice" | "calendar_slot">[]>;
|
|
3
3
|
export type FieldItemType = z.input<typeof FieldItemType>;
|
|
4
4
|
export type ChoiceGenerator = (query: string) => Promise<[string[], string[]]>;
|
|
5
5
|
export declare const FieldItem: z.ZodObject<{
|
|
6
6
|
item_type: z.ZodLiteral<"field">;
|
|
7
7
|
key: z.ZodString;
|
|
8
8
|
description: z.ZodString;
|
|
9
|
-
field_type: z.ZodUnion<z.ZodLiteral<"text" | "
|
|
9
|
+
field_type: z.ZodUnion<z.ZodLiteral<"text" | "date" | "datetime" | "integer" | "multiple_choice" | "calendar_slot">[]>;
|
|
10
10
|
required: z.ZodDefault<z.ZodBoolean>;
|
|
11
11
|
choices: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
12
12
|
choiceGenerator: z.ZodOptional<z.ZodCustom<ChoiceGenerator, ChoiceGenerator>>;
|
|
@@ -17,7 +17,7 @@ export declare const SerializableFieldItem: z.ZodObject<{
|
|
|
17
17
|
item_type: z.ZodLiteral<"field">;
|
|
18
18
|
key: z.ZodString;
|
|
19
19
|
description: z.ZodString;
|
|
20
|
-
field_type: z.ZodUnion<z.ZodLiteral<"text" | "
|
|
20
|
+
field_type: z.ZodUnion<z.ZodLiteral<"text" | "date" | "datetime" | "integer" | "multiple_choice" | "calendar_slot">[]>;
|
|
21
21
|
required: z.ZodDefault<z.ZodBoolean>;
|
|
22
22
|
choices: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
23
23
|
is_search_field: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -39,7 +39,7 @@ export declare const ActionItem: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
39
39
|
item_type: z.ZodLiteral<"field">;
|
|
40
40
|
key: z.ZodString;
|
|
41
41
|
description: z.ZodString;
|
|
42
|
-
field_type: z.ZodUnion<z.ZodLiteral<"text" | "
|
|
42
|
+
field_type: z.ZodUnion<z.ZodLiteral<"text" | "date" | "datetime" | "integer" | "multiple_choice" | "calendar_slot">[]>;
|
|
43
43
|
required: z.ZodDefault<z.ZodBoolean>;
|
|
44
44
|
choices: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
45
45
|
is_search_field: z.ZodDefault<z.ZodBoolean>;
|
package/dist/src/agent.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import WebSocket from "ws";
|
|
2
1
|
import { Call } from "./index.ts";
|
|
3
2
|
import { type CallerSpeechEvent, type AgentSpeechEvent } from "./events.ts";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
3
|
+
import type { CallInfo } from "./socket/call-info.ts";
|
|
4
|
+
import { TestSession } from "./testing/session.ts";
|
|
5
|
+
export type { CallInfo } from "./socket/call-info.ts";
|
|
8
6
|
export type IncomingCallAction = {
|
|
9
7
|
action: "accept";
|
|
10
8
|
} | {
|
|
@@ -54,25 +52,92 @@ export declare class Agent {
|
|
|
54
52
|
onAction(callback: (call: Call, actionKey: string) => Promise<void>): void;
|
|
55
53
|
onAction(actionKey: string, callback: (call: Call) => Promise<void>): void;
|
|
56
54
|
onSessionEnd(callback: (call: Call) => Promise<void>): void;
|
|
55
|
+
get handlers(): {
|
|
56
|
+
onCallReceived: (callInfo: CallInfo) => Promise<IncomingCallAction>;
|
|
57
|
+
onCallStart: (call: Call) => Promise<void>;
|
|
58
|
+
onCallerSpeech: (call: Call, event: CallerSpeechEvent) => Promise<void>;
|
|
59
|
+
onAgentSpeech: (call: Call, event: AgentSpeechEvent) => Promise<void>;
|
|
60
|
+
onQuestion: (call: Call, question: string) => Promise<string>;
|
|
61
|
+
onTaskComplete: (taskId: string, call: Call) => Promise<void>;
|
|
62
|
+
onSearchQuery: (fieldKey: string, call: Call, query: string) => Promise<[string[], string[]]>;
|
|
63
|
+
onActionRequest: (call: Call, intentSummary: string) => Promise<SuggestedAction | undefined>;
|
|
64
|
+
onAction: (actionKey: string, call: Call) => Promise<void>;
|
|
65
|
+
onSessionEnd: (call: Call) => Promise<void>;
|
|
66
|
+
};
|
|
57
67
|
onReachPerson(callback: (call: Call, availability: string) => Promise<void>): void;
|
|
58
|
-
listenPhone(phoneNumber: string):
|
|
59
|
-
listenWebrtc(webrtcCode?: string): Promise<
|
|
68
|
+
listenPhone(phoneNumber: string): Promise<void>;
|
|
69
|
+
listenWebrtc(webrtcCode?: string): Promise<void>;
|
|
60
70
|
callLocal(): Promise<void>;
|
|
61
71
|
private _dispatchEvent;
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
_initCall(variables?: Record<string, any>): Promise<Call>;
|
|
73
|
+
_attachToCall(callId: string, initialVariables?: Record<string, any>, testSession?: TestSession): Promise<void>;
|
|
74
|
+
_listenInbound(conn: InboundConnection): Promise<void>;
|
|
75
|
+
private _handleAssignedCall;
|
|
64
76
|
/**
|
|
65
77
|
* @description use the Guava API to call out to a number
|
|
66
78
|
*/
|
|
67
79
|
callPhone(fromNumber: string | undefined, toNumber: string, variables?: Record<string, any>): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Run the agent against a live test session.
|
|
82
|
+
*
|
|
83
|
+
* Connects to the Guava test endpoint, starts the agent's call handling, and
|
|
84
|
+
* calls `callback` with a TestSession for driving the conversation
|
|
85
|
+
* programmatically. Returns the completed TestSession after the callback and
|
|
86
|
+
* call handler both finish.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* const session = await agent.test(async (session) => {
|
|
90
|
+
* await session.waitForTurn();
|
|
91
|
+
* session.say("Hi, I'd like to make a purchase.");
|
|
92
|
+
* await session.waitForEnd();
|
|
93
|
+
* });
|
|
94
|
+
* assert(session.executedActions.includes("sales"));
|
|
95
|
+
*/
|
|
96
|
+
test(callback: (session: TestSession) => Promise<void>, variables?: Record<string, any>): Promise<TestSession>;
|
|
97
|
+
/**
|
|
98
|
+
* Run an automated test conversation where an LLM plays the caller.
|
|
99
|
+
*
|
|
100
|
+
* Connects to the Guava test endpoint, starts the agent, then drives a
|
|
101
|
+
* back-and-forth conversation by repeatedly asking the Guava LLM to decide
|
|
102
|
+
* whether to speak or hang up based on the transcript so far.
|
|
103
|
+
*
|
|
104
|
+
* @param roleplayPrompt - Instructions for the simulated caller, e.g.
|
|
105
|
+
* `"You are a frustrated customer trying to cancel your subscription."`
|
|
106
|
+
* @param variables - Optional initial call variables.
|
|
107
|
+
* @returns The completed TestSession. Call `session.evaluate()` to assert
|
|
108
|
+
* pass/fail criteria, or `session.getTranscript()` to inspect the conversation.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* const session = await agent.testRoleplay(
|
|
112
|
+
* "You are a caller trying to buy a new table.",
|
|
113
|
+
* );
|
|
114
|
+
* assert(session.executedActions.includes("sales"));
|
|
115
|
+
*/
|
|
116
|
+
testRoleplay(roleplayPrompt: string, variables?: Record<string, any>): Promise<TestSession>;
|
|
117
|
+
/**
|
|
118
|
+
* Start an interactive terminal chat session with the agent.
|
|
119
|
+
*
|
|
120
|
+
* Opens a TUI with a scrolling conversation panel and an input line.
|
|
121
|
+
* Agent responses appear in real time. Press Ctrl+C or let the agent
|
|
122
|
+
* end the session to exit.
|
|
123
|
+
*
|
|
124
|
+
* @param variables - Optional initial call variables.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* await agent.chat();
|
|
128
|
+
* // or: await agent.chat({ patient_name: "Benjamin Buttons" });
|
|
129
|
+
*/
|
|
130
|
+
chat(variables?: Record<string, any>): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Return a shallow copy of this agent with independently overridable
|
|
133
|
+
* callbacks.
|
|
134
|
+
*
|
|
135
|
+
* Use in tests to register alternative handlers on the clone without
|
|
136
|
+
* affecting the original agent.
|
|
137
|
+
*/
|
|
138
|
+
patch(): Agent;
|
|
68
139
|
/** @deprecated Use {@link listenPhone} instead. */
|
|
69
|
-
inboundPhone(phoneNumber: string):
|
|
140
|
+
inboundPhone(phoneNumber: string): Promise<void>;
|
|
70
141
|
/** @deprecated Use {@link callPhone} instead. */
|
|
71
142
|
outboundPhone(fromNumber: string | undefined, toNumber: string, variables?: Record<string, any>): Promise<void>;
|
|
72
143
|
}
|
|
73
|
-
declare class InboundListener {
|
|
74
|
-
private ws;
|
|
75
|
-
constructor(ws: WebSocket);
|
|
76
|
-
close(): void;
|
|
77
|
-
}
|
|
78
|
-
export {};
|