@adonis-agora/agent 0.93.0 → 0.95.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/CHANGELOG.md +20 -0
- package/dist/assets/spa/assets/{index-DUq09Q_k.js → index-DBu17cDY.js} +1 -1
- package/dist/assets/spa/index.html +1 -1
- package/dist/providers/agent_provider.d.ts.map +1 -1
- package/dist/providers/agent_provider.js +20 -2
- package/dist/providers/agent_provider.js.map +1 -1
- package/dist/providers/poppy_connections_provider.d.ts +1 -1
- package/dist/providers/poppy_connections_provider.js +1 -1
- package/dist/providers/poppy_provider.d.ts +1 -1
- package/dist/providers/poppy_provider.d.ts.map +1 -1
- package/dist/providers/poppy_provider.js +6 -6
- package/dist/providers/poppy_provider.js.map +1 -1
- package/dist/src/agent-service.d.ts +11 -1
- package/dist/src/agent-service.d.ts.map +1 -1
- package/dist/src/agent-service.js +13 -4
- package/dist/src/agent-service.js.map +1 -1
- package/dist/src/diagnostics.d.ts +2 -0
- package/dist/src/diagnostics.d.ts.map +1 -1
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/auth.d.ts +3 -3
- package/dist/src/mcp/auth.d.ts.map +1 -1
- package/dist/src/mcp/auth.js +2 -29
- package/dist/src/mcp/auth.js.map +1 -1
- package/dist/src/mcp/discovery.d.ts +3 -3
- package/dist/src/mcp/discovery.d.ts.map +1 -1
- package/dist/src/mcp/discovery.js +2 -2
- package/dist/src/poppy/auth.d.ts +20 -16
- package/dist/src/poppy/auth.d.ts.map +1 -1
- package/dist/src/poppy/auth.js.map +1 -1
- package/dist/src/poppy/conversations.d.ts +25 -25
- package/dist/src/poppy/conversations.d.ts.map +1 -1
- package/dist/src/poppy/conversations.js +37 -37
- package/dist/src/poppy/conversations.js.map +1 -1
- package/dist/src/poppy/define_config.d.ts +7 -7
- package/dist/src/poppy/define_config.d.ts.map +1 -1
- package/dist/src/poppy/define_config.js +1 -1
- package/dist/src/poppy/endpoints.d.ts +2 -2
- package/dist/src/poppy/endpoints.js +1 -1
- package/dist/src/poppy/handler.d.ts +5 -5
- package/dist/src/poppy/handler.d.ts.map +1 -1
- package/dist/src/poppy/handler.js +23 -21
- package/dist/src/poppy/handler.js.map +1 -1
- package/dist/src/poppy/index.d.ts +2 -2
- package/dist/src/poppy/index.d.ts.map +1 -1
- package/dist/src/poppy/index.js +1 -1
- package/dist/src/poppy/index.js.map +1 -1
- package/dist/src/poppy/protocol.d.ts +30 -23
- package/dist/src/poppy/protocol.d.ts.map +1 -1
- package/dist/src/poppy/protocol.js +16 -17
- package/dist/src/poppy/protocol.js.map +1 -1
- package/dist/src/poppy/redis-store.d.ts +1 -1
- package/dist/src/poppy/redis-store.js +1 -1
- package/dist/src/poppy/store.d.ts +7 -7
- package/dist/src/poppy/store.js +1 -1
- package/dist/src/poppy-client/api.d.ts +5 -4
- package/dist/src/poppy-client/api.d.ts.map +1 -1
- package/dist/src/poppy-client/api.js +14 -9
- package/dist/src/poppy-client/api.js.map +1 -1
- package/dist/src/poppy-client/browser.d.ts +12 -18
- package/dist/src/poppy-client/browser.d.ts.map +1 -1
- package/dist/src/poppy-client/browser.js +33 -73
- package/dist/src/poppy-client/browser.js.map +1 -1
- package/dist/src/poppy-client/cli/main.d.ts.map +1 -1
- package/dist/src/poppy-client/cli/main.js +48 -56
- package/dist/src/poppy-client/cli/main.js.map +1 -1
- package/dist/src/poppy-client/company.d.ts +43 -28
- package/dist/src/poppy-client/company.d.ts.map +1 -1
- package/dist/src/poppy-client/company.js +216 -160
- package/dist/src/poppy-client/company.js.map +1 -1
- package/dist/src/poppy-client/conversations.d.ts +12 -13
- package/dist/src/poppy-client/conversations.d.ts.map +1 -1
- package/dist/src/poppy-client/conversations.js +24 -22
- package/dist/src/poppy-client/conversations.js.map +1 -1
- package/dist/src/poppy-client/discovery.d.ts +32 -10
- package/dist/src/poppy-client/discovery.d.ts.map +1 -1
- package/dist/src/poppy-client/discovery.js +134 -68
- package/dist/src/poppy-client/discovery.js.map +1 -1
- package/dist/src/poppy-client/dpop.d.ts +2 -1
- package/dist/src/poppy-client/dpop.d.ts.map +1 -1
- package/dist/src/poppy-client/dpop.js +2 -1
- package/dist/src/poppy-client/dpop.js.map +1 -1
- package/dist/src/poppy-client/errors.d.ts +5 -4
- package/dist/src/poppy-client/errors.d.ts.map +1 -1
- package/dist/src/poppy-client/errors.js +5 -4
- package/dist/src/poppy-client/errors.js.map +1 -1
- package/dist/src/poppy-client/http.d.ts +4 -2
- package/dist/src/poppy-client/http.d.ts.map +1 -1
- package/dist/src/poppy-client/http.js +9 -5
- package/dist/src/poppy-client/http.js.map +1 -1
- package/dist/src/poppy-client/identity.d.ts +15 -15
- package/dist/src/poppy-client/identity.d.ts.map +1 -1
- package/dist/src/poppy-client/identity.js +17 -33
- package/dist/src/poppy-client/identity.js.map +1 -1
- package/dist/src/poppy-client/index.d.ts +6 -3
- package/dist/src/poppy-client/index.d.ts.map +1 -1
- package/dist/src/poppy-client/index.js +6 -3
- package/dist/src/poppy-client/index.js.map +1 -1
- package/dist/src/poppy-client/llm.js +4 -4
- package/dist/src/poppy-client/llm.js.map +1 -1
- package/dist/src/poppy-client/mcp.d.ts +3 -4
- package/dist/src/poppy-client/mcp.d.ts.map +1 -1
- package/dist/src/poppy-client/mcp.js +26 -38
- package/dist/src/poppy-client/mcp.js.map +1 -1
- package/dist/src/poppy-client/safe_fetch.d.ts +30 -0
- package/dist/src/poppy-client/safe_fetch.d.ts.map +1 -0
- package/dist/src/poppy-client/safe_fetch.js +210 -0
- package/dist/src/poppy-client/safe_fetch.js.map +1 -0
- package/dist/src/poppy-client/session_jwt.d.ts +20 -0
- package/dist/src/poppy-client/session_jwt.d.ts.map +1 -0
- package/dist/src/poppy-client/session_jwt.js +37 -0
- package/dist/src/poppy-client/session_jwt.js.map +1 -0
- package/dist/src/poppy-client/signin.d.ts +34 -11
- package/dist/src/poppy-client/signin.d.ts.map +1 -1
- package/dist/src/poppy-client/signin.js +134 -80
- package/dist/src/poppy-client/signin.js.map +1 -1
- package/dist/src/poppy-client/store.d.ts +23 -11
- package/dist/src/poppy-client/store.d.ts.map +1 -1
- package/dist/src/poppy-client/store.js +1 -1
- package/dist/src/poppy-client/store.js.map +1 -1
- package/dist/src/poppy-client/task_coverage.d.ts +13 -0
- package/dist/src/poppy-client/task_coverage.d.ts.map +1 -0
- package/dist/src/poppy-client/task_coverage.js +66 -0
- package/dist/src/poppy-client/task_coverage.js.map +1 -0
- package/dist/src/poppy-client/token_client.d.ts +36 -33
- package/dist/src/poppy-client/token_client.d.ts.map +1 -1
- package/dist/src/poppy-client/token_client.js +47 -47
- package/dist/src/poppy-client/token_client.js.map +1 -1
- package/dist/src/poppy-client/types.d.ts +81 -42
- package/dist/src/poppy-client/types.d.ts.map +1 -1
- package/dist/src/poppy-client/types.js +1 -1
- package/dist/src/poppy-client/util.d.ts +12 -3
- package/dist/src/poppy-client/util.d.ts.map +1 -1
- package/dist/src/poppy-client/util.js +29 -9
- package/dist/src/poppy-client/util.js.map +1 -1
- package/dist/src/poppy-connections/config.d.ts +2 -2
- package/dist/src/poppy-connections/config.js +1 -1
- package/dist/src/poppy-connections/config.js.map +1 -1
- package/dist/src/poppy-connections/crypto.d.ts +2 -2
- package/dist/src/poppy-connections/crypto.js +2 -2
- package/dist/src/poppy-connections/index.d.ts +1 -1
- package/dist/src/poppy-connections/index.js +1 -1
- package/dist/src/poppy-connections/service.d.ts +11 -10
- package/dist/src/poppy-connections/service.d.ts.map +1 -1
- package/dist/src/poppy-connections/service.js +33 -21
- package/dist/src/poppy-connections/service.js.map +1 -1
- package/dist/src/poppy-connections/store.d.ts +2 -2
- package/dist/src/poppy-connections/tools.d.ts.map +1 -1
- package/dist/src/poppy-connections/tools.js +5 -4
- package/dist/src/poppy-connections/tools.js.map +1 -1
- package/dist/src/spi/agent-store.d.ts +6 -0
- package/dist/src/spi/agent-store.d.ts.map +1 -1
- package/dist/src/spi/agent-store.js.map +1 -1
- package/dist/src/spi/governance-queries.d.ts +23 -1
- package/dist/src/spi/governance-queries.d.ts.map +1 -1
- package/dist/src/spi/governance-queries.js +16 -1
- package/dist/src/spi/governance-queries.js.map +1 -1
- package/dist/src/stores/lucid-governance-queries.d.ts +2 -2
- package/dist/src/stores/lucid-governance-queries.d.ts.map +1 -1
- package/dist/src/stores/lucid-governance-queries.js +11 -7
- package/dist/src/stores/lucid-governance-queries.js.map +1 -1
- package/dist/src/stores/lucid-schema.d.ts +2 -0
- package/dist/src/stores/lucid-schema.d.ts.map +1 -1
- package/dist/src/stores/lucid-schema.js +12 -0
- package/dist/src/stores/lucid-schema.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +7 -0
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +21 -3
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/testing/in-memory-governance-queries.d.ts +2 -2
- package/dist/src/testing/in-memory-governance-queries.d.ts.map +1 -1
- package/dist/src/testing/in-memory-governance-queries.js +11 -2
- package/dist/src/testing/in-memory-governance-queries.js.map +1 -1
- package/dist/src/testing/in-memory-store.d.ts +2 -0
- package/dist/src/testing/in-memory-store.d.ts.map +1 -1
- package/dist/src/testing/in-memory-store.js +7 -2
- package/dist/src/testing/in-memory-store.js.map +1 -1
- package/dist/src/usage-ledger.d.ts.map +1 -1
- package/dist/src/usage-ledger.js +1 -0
- package/dist/src/usage-ledger.js.map +1 -1
- package/package.json +6 -6
- package/skills/agent-governance/SKILL.md +3 -3
- package/skills/agent-tools/SKILL.md +3 -3
package/dist/src/poppy/auth.d.ts
CHANGED
|
@@ -2,32 +2,35 @@ import type { Actor } from '../types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Who a Poppy request comes from: a Personal Agent (`clientId`) acting for one of its Users
|
|
4
4
|
* (`userId`, the pairwise User ID — not an account) in one Session. `signedIn`, with the app
|
|
5
|
-
* account (`accountId`) and `scopes`,
|
|
6
|
-
* neither. The shape `@adonis-agora/authkit-server` answers.
|
|
5
|
+
* account (`accountId`) and `scopes`, on a request that carries an access token (§5.4); a signed-out
|
|
6
|
+
* request has neither. The shape `@adonis-agora/authkit-server` answers.
|
|
7
7
|
*/
|
|
8
8
|
export interface PoppyPrincipal {
|
|
9
9
|
/** The opaque, stable id the Personal Agent gave this User here. */
|
|
10
10
|
userId: string;
|
|
11
|
-
/**
|
|
11
|
+
/** Which of the User's agents this Session is for (§5.1), if the Personal Agent says. */
|
|
12
|
+
agentId?: string | null;
|
|
13
|
+
/** The app account, when the request carries an access token; `null` signed out. */
|
|
12
14
|
accountId: string | null;
|
|
13
15
|
/** The Personal Agent's `client_id` (its metadata document URL). */
|
|
14
16
|
clientId: string;
|
|
15
|
-
/** The token's
|
|
17
|
+
/** The access token's scopes. Empty signed out. */
|
|
16
18
|
scopes: string[];
|
|
17
19
|
sessionId: string;
|
|
18
20
|
signedIn: boolean;
|
|
19
21
|
/** The `resource` the token was issued for (RFC 8707), or `null`. */
|
|
20
22
|
resource?: string | null;
|
|
21
|
-
|
|
23
|
+
/** The access token's scheme; `null` signed out. */
|
|
24
|
+
tokenType?: 'DPoP' | 'Bearer' | null;
|
|
22
25
|
/** What the app's `personalAgents.poppy.toActor` answered, when it has one. */
|
|
23
26
|
actor?: Actor;
|
|
24
27
|
}
|
|
25
|
-
/** The request a resolver verifies — the Session
|
|
28
|
+
/** The request a resolver verifies — the `Poppy-Session` JWT and any access token are in `headers`. */
|
|
26
29
|
export interface PoppyAuthRequest {
|
|
27
30
|
method: string;
|
|
28
|
-
/** The full PUBLIC request URL (the
|
|
31
|
+
/** The full PUBLIC request URL (the Session JWT's `htu` is checked against it; the query is ignored). */
|
|
29
32
|
url: string;
|
|
30
|
-
/** The request's headers as received (lower-cased names) — `authorization` and `dpop` included. */
|
|
33
|
+
/** The request's headers as received (lower-cased names) — `poppy-session`, `authorization` and `dpop` included. */
|
|
31
34
|
headers: Record<string, string | string[] | undefined>;
|
|
32
35
|
}
|
|
33
36
|
/**
|
|
@@ -42,14 +45,15 @@ export interface PoppyAuthOptions {
|
|
|
42
45
|
}
|
|
43
46
|
export type PoppyAuthFailure = {
|
|
44
47
|
ok: false;
|
|
45
|
-
status: 400 | 401 | 403;
|
|
46
|
-
|
|
48
|
+
status: 400 | 401 | 403 | 429;
|
|
49
|
+
/** `null`: a challenge without a code (§8, the request needs the account) or a rate limit (§5.6). */
|
|
50
|
+
error: 'invalid_session' | 'invalid_token' | 'insufficient_scope' | 'invalid_dpop_proof' | 'use_dpop_nonce' | (string & {}) | null;
|
|
47
51
|
scope?: string;
|
|
48
|
-
/** The challenge to answer with, verbatim. */
|
|
49
|
-
wwwAuthenticate: string;
|
|
50
|
-
/** For logs and
|
|
52
|
+
/** The challenge to answer with, verbatim; `null` for `invalid_session` and rate limits. */
|
|
53
|
+
wwwAuthenticate: string | null;
|
|
54
|
+
/** For logs and `invalid_session`'s `error_description` — never a token. */
|
|
51
55
|
description?: string;
|
|
52
|
-
/** Extra headers to answer with (`DPoP-Nonce`). */
|
|
56
|
+
/** Extra headers to answer with (`DPoP-Nonce`, `Retry-After`). */
|
|
53
57
|
headers?: Record<string, string>;
|
|
54
58
|
};
|
|
55
59
|
export type PoppyAuthResult = {
|
|
@@ -57,10 +61,10 @@ export type PoppyAuthResult = {
|
|
|
57
61
|
principal: PoppyPrincipal;
|
|
58
62
|
} | PoppyAuthFailure;
|
|
59
63
|
/**
|
|
60
|
-
* Verifies a request's Session
|
|
64
|
+
* Verifies a request's Session header and any access token. `@adonis-agora/authkit-server` installs one in the global
|
|
61
65
|
* slot {@link POPPY_AUTHENTICATE_SLOT}; an app can pass its own (`definePoppyConfig({ authenticate })`).
|
|
62
66
|
*
|
|
63
|
-
* @experimental Tracks Personal Agent Protocol Draft 0.
|
|
67
|
+
* @experimental Tracks Personal Agent Protocol Draft 0.3 (https://personalagentprotocol.org/docs/spec),
|
|
64
68
|
* a spec still in development: this API WILL change as the spec evolves — possibly in breaking
|
|
65
69
|
* ways, outside semver majors while it is a draft.
|
|
66
70
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/poppy/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/poppy/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,oFAAoF;IACpF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IACrC,+EAA+E;IAC/E,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,uGAAuG;AACvG,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,yGAAyG;IACzG,GAAG,EAAE,MAAM,CAAC;IACZ,oHAAoH;IACpH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC9B,qGAAqG;IACrG,KAAK,EACD,iBAAiB,GACjB,eAAe,GACf,oBAAoB,GACpB,oBAAoB,GACpB,gBAAgB,GAChB,CAAC,MAAM,GAAG,EAAE,CAAC,GACb,IAAI,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GAAG,gBAAgB,CAAC;AAEzF;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,OAAO,EAAE,gBAAgB,EACzB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,eAAe,CAAC,CAAC;AAE9B;;;GAGG;AACH,eAAO,MAAM,uBAAuB,eAAiD,CAAC;AAEtF,sGAAsG;AACtG,wBAAgB,uBAAuB,IAAI,iBAAiB,GAAG,SAAS,CAGvE;AAED,+FAA+F;AAC/F,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAGtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/poppy/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/poppy/auth.ts"],"names":[],"mappings":"AAqFA;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAEtF,sGAAsG;AACtG,MAAM,UAAU,uBAAuB;IACrC,MAAM,KAAK,GAAI,UAAsC,CAAC,uBAAuB,CAAC,CAAC;IAC/E,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAE,KAA2B,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAI,UAAsC,CAAC,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;IAChG,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type A2aActionPolicy, type A2aTurnOutcome, type A2aTurnService } from '../a2a/turn.js';
|
|
2
2
|
import type { Actor } from '../types.js';
|
|
3
3
|
import type { PoppyPrincipal } from './auth.js';
|
|
4
|
-
import { type PoppyEvent, type PoppyEventMessage, type PoppyResponder, type PoppySendBody, type
|
|
4
|
+
import { type PoppyAuthor, type PoppyEvent, type PoppyEventMessage, type PoppyResponder, type PoppySendBody, type PoppyStatus } from './protocol.js';
|
|
5
5
|
import { type PoppyConversationRecord, type PoppyStore } from './store.js';
|
|
6
6
|
/** What the hooks are told about a conversation. */
|
|
7
7
|
export interface PoppyHookContext {
|
|
@@ -15,13 +15,13 @@ export interface PoppyHookContext {
|
|
|
15
15
|
* - `'queued'` — someone will join: call {@link PoppyConversations.humanJoined} when they do, or
|
|
16
16
|
* {@link PoppyConversations.handoffUnavailable} if nobody can.
|
|
17
17
|
* - `'joined'` — a person took it now.
|
|
18
|
-
* - `{ unavailable }` — nobody can; the text is what the Company Agent says (§
|
|
18
|
+
* - `{ unavailable }` — nobody can; the text is what the Company Agent says (§8.9).
|
|
19
19
|
*/
|
|
20
20
|
export type PoppyHandoffDecision = 'queued' | 'joined' | {
|
|
21
21
|
unavailable: string;
|
|
22
22
|
};
|
|
23
23
|
/**
|
|
24
|
-
* How the app brings a person in (§
|
|
24
|
+
* How the app brings a person in (§8.9). Without these, a handoff is answered by the Company Agent
|
|
25
25
|
* saying no one is available — the conversation stays with the agent.
|
|
26
26
|
*/
|
|
27
27
|
export interface PoppyHandoffHooks {
|
|
@@ -36,10 +36,10 @@ export interface PoppyHandoffHooks {
|
|
|
36
36
|
message?(ctx: PoppyHookContext & {
|
|
37
37
|
message: PoppyEventMessage;
|
|
38
38
|
}): void | Promise<void>;
|
|
39
|
-
/** The conversation closed while a person was handling it or being found (§
|
|
39
|
+
/** The conversation closed while a person was handling it or being found (§8.12). */
|
|
40
40
|
cancel?(ctx: PoppyHookContext): void | Promise<void>;
|
|
41
41
|
}
|
|
42
|
-
/** Notified when the Personal Agent opens or closes a Direct Conversation (§
|
|
42
|
+
/** Notified when the Personal Agent opens or closes a Direct Conversation (§8.10). */
|
|
43
43
|
export interface PoppyDirectHooks {
|
|
44
44
|
opened?(ctx: PoppyHookContext & {
|
|
45
45
|
parentId: string;
|
|
@@ -50,11 +50,11 @@ export interface PoppyDirectHooks {
|
|
|
50
50
|
}
|
|
51
51
|
/** What the Company Agent says on its own. */
|
|
52
52
|
export interface PoppyTexts {
|
|
53
|
-
/** A handoff with no one to take it (§
|
|
53
|
+
/** A handoff with no one to take it (§8.9). */
|
|
54
54
|
handoffUnavailable: string;
|
|
55
55
|
/** A turn that failed before saying anything. */
|
|
56
56
|
failed: string;
|
|
57
|
-
/** Asked in a Direct Conversation alongside an `authorization` event (§
|
|
57
|
+
/** Asked in a Direct Conversation alongside an `authorization` event (§8.11 SHOULD). */
|
|
58
58
|
signIn: string;
|
|
59
59
|
/** An action that ran — `{title}` is the app's confirmation title (default {@link formatPoppyAction}). */
|
|
60
60
|
actionSucceeded: string;
|
|
@@ -67,7 +67,7 @@ export declare const DEFAULT_POPPY_TEXTS: PoppyTexts;
|
|
|
67
67
|
/** An action of the turn, as the reply's `data.actions` carries it. */
|
|
68
68
|
export type PoppyActionOutcome = A2aTurnOutcome;
|
|
69
69
|
/**
|
|
70
|
-
* Words an action for the reply's text (§
|
|
70
|
+
* Words an action for the reply's text (§8: the message must make sense without `data`). Return
|
|
71
71
|
* `null` to leave it out. Default {@link formatPoppyAction}.
|
|
72
72
|
*/
|
|
73
73
|
export type PoppyActionFormatter = (action: PoppyActionOutcome, texts: PoppyTexts) => string | null | undefined;
|
|
@@ -106,7 +106,7 @@ export interface PoppyConversationsOptions {
|
|
|
106
106
|
/** Logs what fails outside a request (a turn, a hook). */
|
|
107
107
|
onError?: (error: unknown, context: string) => void;
|
|
108
108
|
}
|
|
109
|
-
/** What a read answers (§
|
|
109
|
+
/** What a read answers (§8.5). */
|
|
110
110
|
export interface PoppyReadResult {
|
|
111
111
|
conversation_id: string;
|
|
112
112
|
events: PoppyEvent[];
|
|
@@ -115,7 +115,7 @@ export interface PoppyReadResult {
|
|
|
115
115
|
status: PoppyStatus;
|
|
116
116
|
responder: PoppyResponder;
|
|
117
117
|
}
|
|
118
|
-
/** What a stream yields: a stored event, or a provisional piece of text (§
|
|
118
|
+
/** What a stream yields: a stored event, or a provisional piece of text (§8.6). */
|
|
119
119
|
export type PoppyStreamItem = {
|
|
120
120
|
kind: 'event';
|
|
121
121
|
event: PoppyEvent;
|
|
@@ -130,7 +130,7 @@ export type PoppyStreamItem = {
|
|
|
130
130
|
/** The actor of a principal the resolver gave none: stable per (Personal Agent, its User). */
|
|
131
131
|
export declare function poppyActorId(clientId: string, userId: string): string;
|
|
132
132
|
/**
|
|
133
|
-
* Poppy conversations (§
|
|
133
|
+
* Poppy conversations (§8) over the agent runtime: the state machine, the event log and the turns.
|
|
134
134
|
* HTTP-free — `createPoppyHandler` puts the protocol's requests on it, and the app drives the
|
|
135
135
|
* Company side through it (a person joining, their messages, `user_requested`).
|
|
136
136
|
*
|
|
@@ -140,7 +140,7 @@ export declare function poppyActorId(clientId: string, userId: string): string;
|
|
|
140
140
|
* then appends the reply as a `message` event. A replica that finds a conversation `working` with
|
|
141
141
|
* no pump picks it up, so a reply survives the process that started it.
|
|
142
142
|
*
|
|
143
|
-
* @experimental Tracks Personal Agent Protocol Draft 0.
|
|
143
|
+
* @experimental Tracks Personal Agent Protocol Draft 0.3 (https://personalagentprotocol.org/docs/spec),
|
|
144
144
|
* a spec still in development: this API WILL change as the spec evolves — possibly in breaking
|
|
145
145
|
* ways, outside semver majors while it is a draft.
|
|
146
146
|
*/
|
|
@@ -163,17 +163,17 @@ export declare class PoppyConversations {
|
|
|
163
163
|
body: Record<string, unknown>;
|
|
164
164
|
conversationId: string;
|
|
165
165
|
}>;
|
|
166
|
-
/** `POST {endpoint}/{id}/messages` — another message (§
|
|
166
|
+
/** `POST {endpoint}/{id}/messages` — another message (§8.3). */
|
|
167
167
|
send(principal: PoppyPrincipal, conversationId: string, body: PoppySendBody): Promise<{
|
|
168
168
|
status: number;
|
|
169
169
|
body: Record<string, unknown>;
|
|
170
170
|
}>;
|
|
171
|
-
/** `GET {endpoint}/{id}/events` without streaming — read (and wait for) events (§
|
|
171
|
+
/** `GET {endpoint}/{id}/events` without streaming — read (and wait for) events (§8.5). */
|
|
172
172
|
read(principal: PoppyPrincipal, conversationId: string, options: {
|
|
173
173
|
cursor?: string;
|
|
174
174
|
waitMs?: number;
|
|
175
175
|
}): Promise<PoppyReadResult>;
|
|
176
|
-
/** A read of a conversation already checked — also what a POST with `wait` answers (§
|
|
176
|
+
/** A read of a conversation already checked — also what a POST with `wait` answers (§8.3). */
|
|
177
177
|
readOwned(conversation: PoppyConversationRecord, options: {
|
|
178
178
|
cursor?: string;
|
|
179
179
|
waitMs?: number;
|
|
@@ -181,17 +181,17 @@ export declare class PoppyConversations {
|
|
|
181
181
|
/** Check a conversation is the principal's, for a caller that reads it afterwards. */
|
|
182
182
|
owned(principal: PoppyPrincipal, conversationId: string): Promise<PoppyConversationRecord>;
|
|
183
183
|
/**
|
|
184
|
-
* `GET {endpoint}/{id}/events` as SSE (§
|
|
184
|
+
* `GET {endpoint}/{id}/events` as SSE (§8.6): the events after `cursor`, then new ones as they
|
|
185
185
|
* come, with `text-delta` pieces of a reply being written in this process. Ends when `signal`
|
|
186
186
|
* aborts, or once the conversation is closed and every event was sent.
|
|
187
187
|
*/
|
|
188
188
|
stream(conversation: PoppyConversationRecord, cursor: string | undefined, signal: AbortSignal): AsyncGenerator<PoppyStreamItem>;
|
|
189
|
-
/** `POST {endpoint}/{id}/handoff` — ask for a person at the Company (§
|
|
189
|
+
/** `POST {endpoint}/{id}/handoff` — ask for a person at the Company (§8.9). */
|
|
190
190
|
requestHandoff(principal: PoppyPrincipal, conversationId: string): Promise<{
|
|
191
191
|
status: PoppyStatus;
|
|
192
192
|
responder: PoppyResponder;
|
|
193
193
|
}>;
|
|
194
|
-
/** `POST {endpoint}/{id}/close` — close the conversation (§
|
|
194
|
+
/** `POST {endpoint}/{id}/close` — close the conversation (§8.12). */
|
|
195
195
|
closeByAgent(principal: PoppyPrincipal, conversationId: string): Promise<{
|
|
196
196
|
status: PoppyStatus;
|
|
197
197
|
responder: PoppyResponder;
|
|
@@ -199,19 +199,19 @@ export declare class PoppyConversations {
|
|
|
199
199
|
/** Look a conversation up — for the app's own routing (a support tool, an admin page). */
|
|
200
200
|
get(conversationId: string): Promise<PoppyConversationRecord | null>;
|
|
201
201
|
/**
|
|
202
|
-
* Close a conversation (§
|
|
202
|
+
* Close a conversation (§8.12): its open Direct Conversation first, a pending handoff is
|
|
203
203
|
* cancelled, and a `closed` state event added. Nothing it started is undone. Idempotent.
|
|
204
204
|
*/
|
|
205
205
|
close(conversationId: string): Promise<{
|
|
206
206
|
status: PoppyStatus;
|
|
207
207
|
responder: PoppyResponder;
|
|
208
208
|
}>;
|
|
209
|
-
/** The Company Agent hands off to a person on its own (§
|
|
209
|
+
/** The Company Agent hands off to a person on its own (§8.9) — e.g. from one of your tools. */
|
|
210
210
|
handoff(conversationId: string): Promise<{
|
|
211
211
|
status: PoppyStatus;
|
|
212
212
|
responder: PoppyResponder;
|
|
213
213
|
}>;
|
|
214
|
-
/** A person at the Company joined: `responder` becomes `human` (§
|
|
214
|
+
/** A person at the Company joined: `responder` becomes `human` (§8.7). */
|
|
215
215
|
humanJoined(conversationId: string): Promise<{
|
|
216
216
|
status: PoppyStatus;
|
|
217
217
|
responder: PoppyResponder;
|
|
@@ -223,23 +223,23 @@ export declare class PoppyConversations {
|
|
|
223
223
|
}>;
|
|
224
224
|
/**
|
|
225
225
|
* No one could take a queued handoff: the Company Agent says why, and the conversation goes back
|
|
226
|
-
* to `idle` with the agent (§
|
|
226
|
+
* to `idle` with the agent (§8.9).
|
|
227
227
|
*/
|
|
228
228
|
handoffUnavailable(conversationId: string, reason?: string): Promise<{
|
|
229
229
|
status: PoppyStatus;
|
|
230
230
|
responder: PoppyResponder;
|
|
231
231
|
}>;
|
|
232
232
|
/**
|
|
233
|
-
* Add a Company message — a person's (`
|
|
233
|
+
* Add a Company message — a person's (`author.type: 'human'`, while they handle the conversation) or
|
|
234
234
|
* an automated one. Answers the message's id.
|
|
235
235
|
*/
|
|
236
236
|
postMessage(conversationId: string, message: {
|
|
237
237
|
text?: string;
|
|
238
238
|
data?: Record<string, unknown>;
|
|
239
|
-
|
|
239
|
+
author: PoppyAuthor;
|
|
240
240
|
}): Promise<string>;
|
|
241
241
|
/**
|
|
242
|
-
* Ask to talk with the User directly (§
|
|
242
|
+
* Ask to talk with the User directly (§8.10): a `user_requested` event. Only the Personal Agent
|
|
243
243
|
* opens the Direct Conversation, once the User agrees.
|
|
244
244
|
*/
|
|
245
245
|
requestUser(conversationId: string, reason: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../src/poppy/conversations.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EAEpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../src/poppy/conversations.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,7 +36,7 @@ const PRUNE_EVERY_MS = 60_000;
|
|
|
36
36
|
export function poppyActorId(clientId, userId) {
|
|
37
37
|
return `poppy:${createHash('sha256').update(`${clientId}\n${userId}`).digest('hex').slice(0, 40)}`;
|
|
38
38
|
}
|
|
39
|
-
/** The idempotency owner of §
|
|
39
|
+
/** The idempotency owner of §8.3: message ids are unique per User of a Personal Agent. */
|
|
40
40
|
function ownerKey(principal) {
|
|
41
41
|
return createHash('sha256').update(`${principal.clientId}\n${principal.userId}`).digest('hex');
|
|
42
42
|
}
|
|
@@ -57,7 +57,7 @@ function turnText(messages) {
|
|
|
57
57
|
}
|
|
58
58
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
59
59
|
/**
|
|
60
|
-
* Poppy conversations (§
|
|
60
|
+
* Poppy conversations (§8) over the agent runtime: the state machine, the event log and the turns.
|
|
61
61
|
* HTTP-free — `createPoppyHandler` puts the protocol's requests on it, and the app drives the
|
|
62
62
|
* Company side through it (a person joining, their messages, `user_requested`).
|
|
63
63
|
*
|
|
@@ -67,7 +67,7 @@ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
67
67
|
* then appends the reply as a `message` event. A replica that finds a conversation `working` with
|
|
68
68
|
* no pump picks it up, so a reply survives the process that started it.
|
|
69
69
|
*
|
|
70
|
-
* @experimental Tracks Personal Agent Protocol Draft 0.
|
|
70
|
+
* @experimental Tracks Personal Agent Protocol Draft 0.3 (https://personalagentprotocol.org/docs/spec),
|
|
71
71
|
* a spec still in development: this API WILL change as the spec evolves — possibly in breaking
|
|
72
72
|
* ways, outside semver majors while it is a draft.
|
|
73
73
|
*/
|
|
@@ -110,7 +110,7 @@ export class PoppyConversations {
|
|
|
110
110
|
roles: [...new Set([...(actor.roles ?? []), PERSONAL_AGENT_ROLE, ...scopes.map(scopeRole)])],
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
|
-
/** The account a signed-in principal is — what a conversation binds to once used (§
|
|
113
|
+
/** The account a signed-in principal is — what a conversation binds to once used (§8.2). */
|
|
114
114
|
async #accountOf(principal) {
|
|
115
115
|
if (!principal.signedIn)
|
|
116
116
|
return null;
|
|
@@ -124,9 +124,9 @@ export class PoppyConversations {
|
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
|
-
* The conversation, when `principal` may use it (§
|
|
127
|
+
* The conversation, when `principal` may use it (§8.2): the same Personal Agent and User — and
|
|
128
128
|
* once it used an account, a token signed in to that account. Anything else is indistinguishable
|
|
129
|
-
* from no conversation, except a signed-out
|
|
129
|
+
* from no conversation, except a signed-out request of its own User: a challenge (§8.11).
|
|
130
130
|
*/
|
|
131
131
|
async #owned(principal, id) {
|
|
132
132
|
const conversation = await this.options.store.getConversation(id);
|
|
@@ -141,7 +141,7 @@ export class PoppyConversations {
|
|
|
141
141
|
return conversation;
|
|
142
142
|
}
|
|
143
143
|
if (conversation.userId === principal.userId) {
|
|
144
|
-
throw new PoppyError('
|
|
144
|
+
throw new PoppyError('account_required', 'This conversation used your account: sign in');
|
|
145
145
|
}
|
|
146
146
|
throw new PoppyError('conversation_not_found');
|
|
147
147
|
}
|
|
@@ -169,7 +169,7 @@ export class PoppyConversations {
|
|
|
169
169
|
this.#bus.emit(`event:${conversationId}`, event);
|
|
170
170
|
return event;
|
|
171
171
|
}
|
|
172
|
-
/** Change status and/or responder; every change is a `state` event (§
|
|
172
|
+
/** Change status and/or responder; every change is a `state` event (§8.7). */
|
|
173
173
|
async #setState(conversation, next, extra = {}) {
|
|
174
174
|
const status = next.status ?? conversation.status;
|
|
175
175
|
const responder = next.responder ?? conversation.responder;
|
|
@@ -180,11 +180,11 @@ export class PoppyConversations {
|
|
|
180
180
|
await this.#append(conversation.id, { type: 'state', status, responder });
|
|
181
181
|
return updated;
|
|
182
182
|
}
|
|
183
|
-
#companyMessage(text, data,
|
|
183
|
+
#companyMessage(text, data, author, id = newPoppyId('msg')) {
|
|
184
184
|
return {
|
|
185
185
|
id,
|
|
186
186
|
role: 'company',
|
|
187
|
-
|
|
187
|
+
author,
|
|
188
188
|
...(text !== undefined && text !== '' ? { text } : {}),
|
|
189
189
|
...(data !== undefined ? { data } : {}),
|
|
190
190
|
};
|
|
@@ -198,7 +198,7 @@ export class PoppyConversations {
|
|
|
198
198
|
let parent = null;
|
|
199
199
|
if (body.parentConversationId !== undefined) {
|
|
200
200
|
parent = await this.#owned(principal, body.parentConversationId);
|
|
201
|
-
// A Direct Conversation is not a parent (§
|
|
201
|
+
// A Direct Conversation is not a parent (§8.10): as a parent, it does not exist.
|
|
202
202
|
if (parent.parentId !== null)
|
|
203
203
|
throw new PoppyError('conversation_not_found');
|
|
204
204
|
}
|
|
@@ -223,7 +223,7 @@ export class PoppyConversations {
|
|
|
223
223
|
throw new PoppyError('message_id_conflict');
|
|
224
224
|
const existing = await this.options.store.getConversation(claim.conversationId);
|
|
225
225
|
if (existing) {
|
|
226
|
-
// A retried first message: the conversation it already started (§
|
|
226
|
+
// A retried first message: the conversation it already started (§8.3).
|
|
227
227
|
return { ...claim.response, conversationId: claim.conversationId };
|
|
228
228
|
}
|
|
229
229
|
// Claimed by a delivery that died before creating it: take it over.
|
|
@@ -299,13 +299,13 @@ export class PoppyConversations {
|
|
|
299
299
|
// A Direct Conversation that closed without telling its parent: the parent is free.
|
|
300
300
|
await this.options.store.updateConversation(conversation.id, { openDirectId: null });
|
|
301
301
|
}
|
|
302
|
-
/** `POST {endpoint}/{id}/messages` — another message (§
|
|
302
|
+
/** `POST {endpoint}/{id}/messages` — another message (§8.3). */
|
|
303
303
|
async send(principal, conversationId, body) {
|
|
304
304
|
const owned = await this.#owned(principal, conversationId);
|
|
305
305
|
const actor = await this.actorOf(principal);
|
|
306
306
|
const owner = ownerKey(principal);
|
|
307
307
|
const fingerprint = messageFingerprint(conversationId, body);
|
|
308
|
-
// A retry is answered as before, whatever happened since (§
|
|
308
|
+
// A retry is answered as before, whatever happened since (§8.3).
|
|
309
309
|
return this.#locked(conversationId, async () => {
|
|
310
310
|
const conversation = (await this.options.store.getConversation(owned.id)) ?? owned;
|
|
311
311
|
const content = hasContent(body.message);
|
|
@@ -335,7 +335,7 @@ export class PoppyConversations {
|
|
|
335
335
|
throw error;
|
|
336
336
|
}
|
|
337
337
|
const patch = { grant: this.#grant(principal, actor) };
|
|
338
|
-
// Once it is used signed in, the conversation belongs to that account (§
|
|
338
|
+
// Once it is used signed in, the conversation belongs to that account (§8.2).
|
|
339
339
|
if (principal.signedIn && conversation.accountRef === null) {
|
|
340
340
|
patch.accountRef = await this.#accountOf(principal);
|
|
341
341
|
}
|
|
@@ -371,12 +371,12 @@ export class PoppyConversations {
|
|
|
371
371
|
if (hasContent(message))
|
|
372
372
|
this.#kick(conversation.id);
|
|
373
373
|
}
|
|
374
|
-
/** `GET {endpoint}/{id}/events` without streaming — read (and wait for) events (§
|
|
374
|
+
/** `GET {endpoint}/{id}/events` without streaming — read (and wait for) events (§8.5). */
|
|
375
375
|
async read(principal, conversationId, options) {
|
|
376
376
|
const conversation = await this.#owned(principal, conversationId);
|
|
377
377
|
return this.readOwned(conversation, options);
|
|
378
378
|
}
|
|
379
|
-
/** A read of a conversation already checked — also what a POST with `wait` answers (§
|
|
379
|
+
/** A read of a conversation already checked — also what a POST with `wait` answers (§8.3). */
|
|
380
380
|
async readOwned(conversation, options) {
|
|
381
381
|
await this.#maintain(conversation);
|
|
382
382
|
let afterSeq = await this.#cursorSeq(conversation, options.cursor);
|
|
@@ -404,7 +404,7 @@ export class PoppyConversations {
|
|
|
404
404
|
return this.#owned(principal, conversationId);
|
|
405
405
|
}
|
|
406
406
|
/**
|
|
407
|
-
* `GET {endpoint}/{id}/events` as SSE (§
|
|
407
|
+
* `GET {endpoint}/{id}/events` as SSE (§8.6): the events after `cursor`, then new ones as they
|
|
408
408
|
* come, with `text-delta` pieces of a reply being written in this process. Ends when `signal`
|
|
409
409
|
* aborts, or once the conversation is closed and every event was sent.
|
|
410
410
|
*/
|
|
@@ -488,7 +488,7 @@ export class PoppyConversations {
|
|
|
488
488
|
this.#bus.on(`event:${conversationId}`, done);
|
|
489
489
|
});
|
|
490
490
|
}
|
|
491
|
-
/** The position after which a read starts (§
|
|
491
|
+
/** The position after which a read starts (§8.5): unknown → `invalid_cursor`, pruned → expired. */
|
|
492
492
|
async #cursorSeq(conversation, cursor) {
|
|
493
493
|
if (cursor === undefined)
|
|
494
494
|
return 0;
|
|
@@ -515,7 +515,7 @@ export class PoppyConversations {
|
|
|
515
515
|
this.#kick(conversation.id);
|
|
516
516
|
}
|
|
517
517
|
}
|
|
518
|
-
/** `POST {endpoint}/{id}/handoff` — ask for a person at the Company (§
|
|
518
|
+
/** `POST {endpoint}/{id}/handoff` — ask for a person at the Company (§8.9). */
|
|
519
519
|
async requestHandoff(principal, conversationId) {
|
|
520
520
|
const owned = await this.#owned(principal, conversationId);
|
|
521
521
|
const conversation = await this.#locked(owned.id, async () => {
|
|
@@ -534,10 +534,10 @@ export class PoppyConversations {
|
|
|
534
534
|
}
|
|
535
535
|
const hooks = this.options.handoff;
|
|
536
536
|
if (!hooks) {
|
|
537
|
-
// No people to hand off to: the Company Agent says so, and keeps the conversation (§
|
|
537
|
+
// No people to hand off to: the Company Agent says so, and keeps the conversation (§8.9).
|
|
538
538
|
await this.#append(conversation.id, {
|
|
539
539
|
type: 'message',
|
|
540
|
-
message: this.#companyMessage(this.#texts.handoffUnavailable, undefined, 'agent'),
|
|
540
|
+
message: this.#companyMessage(this.#texts.handoffUnavailable, undefined, { type: 'agent' }),
|
|
541
541
|
});
|
|
542
542
|
return { status: conversation.status, responder: conversation.responder };
|
|
543
543
|
}
|
|
@@ -565,7 +565,7 @@ export class PoppyConversations {
|
|
|
565
565
|
}
|
|
566
566
|
return { status: queued.status, responder: queued.responder };
|
|
567
567
|
}
|
|
568
|
-
/** `POST {endpoint}/{id}/close` — close the conversation (§
|
|
568
|
+
/** `POST {endpoint}/{id}/close` — close the conversation (§8.12). */
|
|
569
569
|
async closeByAgent(principal, conversationId) {
|
|
570
570
|
const conversation = await this.#owned(principal, conversationId);
|
|
571
571
|
return this.close(conversation.id);
|
|
@@ -582,7 +582,7 @@ export class PoppyConversations {
|
|
|
582
582
|
return conversation;
|
|
583
583
|
}
|
|
584
584
|
/**
|
|
585
|
-
* Close a conversation (§
|
|
585
|
+
* Close a conversation (§8.12): its open Direct Conversation first, a pending handoff is
|
|
586
586
|
* cancelled, and a `closed` state event added. Nothing it started is undone. Idempotent.
|
|
587
587
|
*/
|
|
588
588
|
async close(conversationId) {
|
|
@@ -627,14 +627,14 @@ export class PoppyConversations {
|
|
|
627
627
|
}
|
|
628
628
|
return { status: 'closed', responder: closed.responder };
|
|
629
629
|
}
|
|
630
|
-
/** The Company Agent hands off to a person on its own (§
|
|
630
|
+
/** The Company Agent hands off to a person on its own (§8.9) — e.g. from one of your tools. */
|
|
631
631
|
async handoff(conversationId) {
|
|
632
632
|
const conversation = await this.#require(conversationId);
|
|
633
633
|
if (conversation.status === 'closed')
|
|
634
634
|
throw new PoppyError('conversation_closed');
|
|
635
635
|
return this.#handoff(conversation, 'company');
|
|
636
636
|
}
|
|
637
|
-
/** A person at the Company joined: `responder` becomes `human` (§
|
|
637
|
+
/** A person at the Company joined: `responder` becomes `human` (§8.7). */
|
|
638
638
|
async humanJoined(conversationId) {
|
|
639
639
|
return this.#locked(conversationId, async () => {
|
|
640
640
|
const conversation = await this.#require(conversationId);
|
|
@@ -659,7 +659,7 @@ export class PoppyConversations {
|
|
|
659
659
|
}
|
|
660
660
|
/**
|
|
661
661
|
* No one could take a queued handoff: the Company Agent says why, and the conversation goes back
|
|
662
|
-
* to `idle` with the agent (§
|
|
662
|
+
* to `idle` with the agent (§8.9).
|
|
663
663
|
*/
|
|
664
664
|
async handoffUnavailable(conversationId, reason = this.#texts.handoffUnavailable) {
|
|
665
665
|
return this.#locked(conversationId, async () => {
|
|
@@ -669,26 +669,26 @@ export class PoppyConversations {
|
|
|
669
669
|
}
|
|
670
670
|
await this.#append(conversationId, {
|
|
671
671
|
type: 'message',
|
|
672
|
-
message: this.#companyMessage(reason, undefined, 'agent'),
|
|
672
|
+
message: this.#companyMessage(reason, undefined, { type: 'agent' }),
|
|
673
673
|
});
|
|
674
674
|
const updated = await this.#setState(conversation, { status: 'idle', responder: 'agent' });
|
|
675
675
|
return { status: updated.status, responder: updated.responder };
|
|
676
676
|
});
|
|
677
677
|
}
|
|
678
678
|
/**
|
|
679
|
-
* Add a Company message — a person's (`
|
|
679
|
+
* Add a Company message — a person's (`author.type: 'human'`, while they handle the conversation) or
|
|
680
680
|
* an automated one. Answers the message's id.
|
|
681
681
|
*/
|
|
682
682
|
async postMessage(conversationId, message) {
|
|
683
683
|
const conversation = await this.#require(conversationId);
|
|
684
684
|
if (conversation.status === 'closed')
|
|
685
685
|
throw new PoppyError('conversation_closed');
|
|
686
|
-
const event = this.#companyMessage(message.text, message.data, message.
|
|
686
|
+
const event = this.#companyMessage(message.text, message.data, message.author);
|
|
687
687
|
await this.#append(conversationId, { type: 'message', message: event });
|
|
688
688
|
return event.id;
|
|
689
689
|
}
|
|
690
690
|
/**
|
|
691
|
-
* Ask to talk with the User directly (§
|
|
691
|
+
* Ask to talk with the User directly (§8.10): a `user_requested` event. Only the Personal Agent
|
|
692
692
|
* opens the Direct Conversation, once the User agrees.
|
|
693
693
|
*/
|
|
694
694
|
async requestUser(conversationId, reason) {
|
|
@@ -829,7 +829,7 @@ export class PoppyConversations {
|
|
|
829
829
|
poppy: {
|
|
830
830
|
conversationId: conversation.id,
|
|
831
831
|
direct: conversation.parentId !== null,
|
|
832
|
-
sender: last?.
|
|
832
|
+
sender: last?.author?.type ?? 'agent',
|
|
833
833
|
signedIn: grant.signedIn,
|
|
834
834
|
context: conversation.context,
|
|
835
835
|
},
|
|
@@ -941,13 +941,13 @@ export class PoppyConversations {
|
|
|
941
941
|
}
|
|
942
942
|
/**
|
|
943
943
|
* Write a turn's reply: a `message` event (text, and `data` for components and executed actions),
|
|
944
|
-
* then an `authorization` event when the turn needed a scope the token does not carry (§
|
|
944
|
+
* then an `authorization` event when the turn needed a scope the token does not carry (§8.11).
|
|
945
945
|
*/
|
|
946
946
|
async #reply(conversation, grant, runId, turn) {
|
|
947
947
|
const store = this.options.store;
|
|
948
948
|
const current = await store.getConversation(conversation.id);
|
|
949
949
|
await store.updateConversation(conversation.id, { activeRunId: null });
|
|
950
|
-
// A closed conversation takes no more events from its agent (§
|
|
950
|
+
// A closed conversation takes no more events from its agent (§8.12).
|
|
951
951
|
if (!current || current.status === 'closed')
|
|
952
952
|
return;
|
|
953
953
|
const components = turn.components.map((frame) => ({
|
|
@@ -986,21 +986,21 @@ export class PoppyConversations {
|
|
|
986
986
|
if (text !== '' || Object.keys(data).length > 0) {
|
|
987
987
|
await this.#append(conversation.id, {
|
|
988
988
|
type: 'message',
|
|
989
|
-
message: this.#companyMessage(text, Object.keys(data).length > 0 ? data : undefined, 'agent', derivedPoppyId('msg', `reply:${runId}`)),
|
|
989
|
+
message: this.#companyMessage(text, Object.keys(data).length > 0 ? data : undefined, { type: 'agent' }, derivedPoppyId('msg', `reply:${runId}`)),
|
|
990
990
|
}, `reply:${runId}`);
|
|
991
991
|
}
|
|
992
992
|
const missing = (turn.permission ?? []).filter((scope) => !grant.signedIn || !grant.scopes.includes(scope));
|
|
993
993
|
if (missing.length > 0) {
|
|
994
994
|
await this.#append(conversation.id, {
|
|
995
995
|
type: 'authorization',
|
|
996
|
-
error:
|
|
996
|
+
error: 'insufficient_scope',
|
|
997
997
|
scope: missing.join(' '),
|
|
998
998
|
}, `authorization:${runId}`);
|
|
999
999
|
// In a Direct Conversation the User reads the messages, not the events: ask there too.
|
|
1000
1000
|
if (conversation.parentId !== null) {
|
|
1001
1001
|
await this.#append(conversation.id, {
|
|
1002
1002
|
type: 'message',
|
|
1003
|
-
message: this.#companyMessage(this.#texts.signIn, undefined, 'agent', derivedPoppyId('msg', `sign-in:${runId}`)),
|
|
1003
|
+
message: this.#companyMessage(this.#texts.signIn, undefined, { type: 'agent' }, derivedPoppyId('msg', `sign-in:${runId}`)),
|
|
1004
1004
|
}, `sign-in:${runId}`);
|
|
1005
1005
|
}
|
|
1006
1006
|
}
|