@guuey/agent-client 0.14.1 → 0.15.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/error-codes.d.ts +11 -0
- package/dist/error-codes.d.ts.map +1 -1
- package/dist/error-codes.js +11 -0
- package/dist/history.js +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useAgentInvoke.d.ts.map +1 -1
- package/dist/useAgentInvoke.js +30 -2
- package/dist/web-adapters.d.ts +3 -1
- package/dist/web-adapters.d.ts.map +1 -1
- package/dist/web-adapters.js +6 -2
- package/package.json +2 -2
- package/src/error-codes.ts +11 -0
- package/src/history.ts +1 -1
- package/src/types.ts +8 -0
- package/src/useAgentInvoke.ts +34 -2
- package/src/web-adapters.ts +13 -3
package/dist/error-codes.d.ts
CHANGED
|
@@ -87,6 +87,17 @@ export declare const CLIENT_ERROR_CODES: {
|
|
|
87
87
|
* the reply if the backend completes later.
|
|
88
88
|
*/
|
|
89
89
|
readonly STREAM_STALLED: "STREAM_STALLED";
|
|
90
|
+
/**
|
|
91
|
+
* A RESUMED thread's history read was refused (401 after the one
|
|
92
|
+
* forceRefresh retry) — the persisted threadId exists but the CURRENT
|
|
93
|
+
* identity cannot read it (guuey#413: the identity-drift face; an
|
|
94
|
+
* expired-and-unrefreshable session is the benign sibling). Surfaced
|
|
95
|
+
* LOUDLY instead of the silent fresh-looking boot: the transcript the
|
|
96
|
+
* user expects exists and cannot be shown, which is an ERROR, not an
|
|
97
|
+
* empty chat. Sends still work (the pod may fork a fresh thread) — the
|
|
98
|
+
* error names why the history is missing.
|
|
99
|
+
*/
|
|
100
|
+
readonly THREAD_HISTORY_UNAVAILABLE: "THREAD_HISTORY_UNAVAILABLE";
|
|
90
101
|
};
|
|
91
102
|
/** One of this SDK's client-originated codes — see {@link CLIENT_ERROR_CODES}. */
|
|
92
103
|
export type ClientErrorCode = (typeof CLIENT_ERROR_CODES)[keyof typeof CLIENT_ERROR_CODES];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB;IAC5B,yDAAyD;;IAEzD,gDAAgD;;IAEhD,8DAA8D;;IAE9D;;;;;OAKG;;IAEH,6EAA6E;;IAE7E,qDAAqD;;IAErD;;;;OAIG;;IAEH;;;;;OAKG;;IAEH,oFAAoF;;IAEpF;;;;OAIG;;IAEH,qDAAqD;;IAErD,iEAAiE;;IAEjE,gCAAgC;;CAExB,CAAC;AAEX,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAExF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;;;;OAKG;;CAEK,CAAC;AAEX,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB;IAC5B,yDAAyD;;IAEzD,gDAAgD;;IAEhD,8DAA8D;;IAE9D;;;;;OAKG;;IAEH,6EAA6E;;IAE7E,qDAAqD;;IAErD;;;;OAIG;;IAEH;;;;;OAKG;;IAEH,oFAAoF;;IAEpF;;;;OAIG;;IAEH,qDAAqD;;IAErD,iEAAiE;;IAEjE,gCAAgC;;CAExB,CAAC;AAEX,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAExF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;;;;OAKG;;IAEH;;;;;;;;;OASG;;CAEK,CAAC;AAEX,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC"}
|
package/dist/error-codes.js
CHANGED
|
@@ -85,4 +85,15 @@ export const CLIENT_ERROR_CODES = {
|
|
|
85
85
|
* the reply if the backend completes later.
|
|
86
86
|
*/
|
|
87
87
|
STREAM_STALLED: "STREAM_STALLED",
|
|
88
|
+
/**
|
|
89
|
+
* A RESUMED thread's history read was refused (401 after the one
|
|
90
|
+
* forceRefresh retry) — the persisted threadId exists but the CURRENT
|
|
91
|
+
* identity cannot read it (guuey#413: the identity-drift face; an
|
|
92
|
+
* expired-and-unrefreshable session is the benign sibling). Surfaced
|
|
93
|
+
* LOUDLY instead of the silent fresh-looking boot: the transcript the
|
|
94
|
+
* user expects exists and cannot be shown, which is an ERROR, not an
|
|
95
|
+
* empty chat. Sends still work (the pod may fork a fresh thread) — the
|
|
96
|
+
* error names why the history is missing.
|
|
97
|
+
*/
|
|
98
|
+
THREAD_HISTORY_UNAVAILABLE: "THREAD_HISTORY_UNAVAILABLE",
|
|
88
99
|
};
|
package/dist/history.js
CHANGED
|
@@ -30,7 +30,7 @@ export function threadHistoryRowsToMessages(rows) {
|
|
|
30
30
|
for (const row of rows) {
|
|
31
31
|
if (row.kind !== "text" || row.text == null)
|
|
32
32
|
continue;
|
|
33
|
-
messages.push({ role: row.authorRole === "user" ? "user" : "assistant", text: row.text });
|
|
33
|
+
messages.push({ role: row.authorRole === "user" ? "user" : "assistant", text: row.text, seq: row.seq });
|
|
34
34
|
}
|
|
35
35
|
return messages;
|
|
36
36
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -24,6 +24,14 @@ export interface AgentMessage {
|
|
|
24
24
|
* join key (`UseAgentInvokeReturn.sendStates`).
|
|
25
25
|
*/
|
|
26
26
|
clientMessageId?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The read plane's transcript `seq` for history-rehydrated entries
|
|
29
|
+
* (guuey#423) — server-allocated, gap-free per thread. Present ONLY on
|
|
30
|
+
* rows the history loader mapped; live turns carry none. The transcript
|
|
31
|
+
* planner uses it to interleave persisted cards at their true positions
|
|
32
|
+
* instead of the R13 tail.
|
|
33
|
+
*/
|
|
34
|
+
seq?: number;
|
|
27
35
|
}
|
|
28
36
|
/**
|
|
29
37
|
* A cross-app profile LINK invite surfaced mid-stream by the pod's
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5F,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5F,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,SAAS,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;AAED,0EAA0E;AAC1E,MAAM,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC;AAEtC,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,mCAAmC;IACnC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,aAAa,CAAC,MAAM,CAAC,CAAC;AAE5E;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnB;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,sFAAsF;IACtF,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACpD;AAED,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,eAAe,CAAC;IAC3B,yGAAyG;IACzG,OAAO,CAAC,EAAE,yBAAyB,CAAC;CACrC;AAED,iGAAiG;AACjG,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,6FAA6F;IAC7F,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,KAAK,GAAG,oBAAoB,CAAC;IAC7C;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC;AAElG,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC;mFAC+E;IAC/E,MAAM,EAAE,iBAAiB,CAAC;IAC1B,8EAA8E;IAC9E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,EAAE,cAAc,GAAG,IAAI,CAAC;IACpC;;;;;;;;OAQG;IACH,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC9C,uEAAuE;IACvE,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC;CAC5D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAgentInvoke.d.ts","sourceRoot":"","sources":["../src/useAgentInvoke.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAW,KAAK,oBAAoB,EAAuB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"useAgentInvoke.d.ts","sourceRoot":"","sources":["../src/useAgentInvoke.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAW,KAAK,oBAAoB,EAAuB,MAAM,sBAAsB,CAAC;AAM/F,OAAO,KAAK,EAGV,YAAY,EAEZ,iBAAiB,EAGjB,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAMpB;;;;;GAKG;AACH,eAAO,MAAM,qCAAqC,EAAE,oBAEnD,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,eAAe,EAAE,YAAY,EAAE,GAC9B,kBAAkB,CAIpB;AAED,uFAAuF;AACvF,eAAO,MAAM,uBAAuB;;;IAGlC;;;;;;;OAOG;;CAEK,CAAC;AAcX;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EAAE,EACvB,cAAc,EAAE,MAAM,GACrB,OAAO,GAAG,WAAW,CAOvB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,oBAAoB,CAmgBhF"}
|
package/dist/useAgentInvoke.js
CHANGED
|
@@ -27,6 +27,7 @@ import { invokeTurn, toInvokeUrl } from "./invoke-turn.js";
|
|
|
27
27
|
import { AgentResponseError } from "./errors.js";
|
|
28
28
|
import { withActivityObserver } from "./transport.js";
|
|
29
29
|
import { CLIENT_ERROR_CODES } from "./error-codes.js";
|
|
30
|
+
import { HistoryUnauthorizedError } from "./history.js";
|
|
30
31
|
function threadStorageKey(appId) {
|
|
31
32
|
return `guuey:thread:${appId ?? "default"}`;
|
|
32
33
|
}
|
|
@@ -228,8 +229,27 @@ export function useAgentInvoke(opts) {
|
|
|
228
229
|
try {
|
|
229
230
|
result = await history.load(tid);
|
|
230
231
|
}
|
|
231
|
-
catch {
|
|
232
|
-
|
|
232
|
+
catch (err) {
|
|
233
|
+
// guuey#413 fail-LOUD carve-out from the best-effort rule: an
|
|
234
|
+
// UNAUTHORIZED read on a RESUMED threadId means a transcript the
|
|
235
|
+
// user expects exists and cannot be shown — silently booting a
|
|
236
|
+
// fresh-looking empty chat hid the identity-drift outage for
|
|
237
|
+
// exactly the accounts holding old threads. Auth refusal surfaces
|
|
238
|
+
// as an error item; every other failure (offline, transient)
|
|
239
|
+
// keeps the best-effort swallow — chat continues without history.
|
|
240
|
+
if (!cancelled && err instanceof HistoryUnauthorizedError) {
|
|
241
|
+
// Same guard as the `gone` arm below: clear + fresh (functional)
|
|
242
|
+
// + the notice (loud). Same concurrency guard — never clobber a
|
|
243
|
+
// threadId a mid-flight send just established.
|
|
244
|
+
if (threadIdRef.current === tid) {
|
|
245
|
+
threadIdRef.current = null;
|
|
246
|
+
setThreadId(null);
|
|
247
|
+
void adaptersRef.current.storage.save(threadStorageKey(appId), "");
|
|
248
|
+
}
|
|
249
|
+
setError("Couldn't restore your previous conversation — started a new one. (This session was not authorized to read the old thread.)");
|
|
250
|
+
setErrorCode(CLIENT_ERROR_CODES.THREAD_HISTORY_UNAVAILABLE);
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
233
253
|
}
|
|
234
254
|
if (cancelled)
|
|
235
255
|
return;
|
|
@@ -243,6 +263,14 @@ export function useAgentInvoke(opts) {
|
|
|
243
263
|
threadIdRef.current = null;
|
|
244
264
|
setThreadId(null);
|
|
245
265
|
void adaptersRef.current.storage.save(threadStorageKey(appId), "");
|
|
266
|
+
// guuey#413: the hydration guard's LOUD half. `gone` covers 403 as
|
|
267
|
+
// well as 404 (history.ts) — an owner-mismatch refusal on a drifted
|
|
268
|
+
// identity flowed through THIS arm as a silent fresh-looking boot,
|
|
269
|
+
// which is the exact outage face this guard exists to kill. The
|
|
270
|
+
// fresh mint stays (functional); the notice makes it honest. Loud
|
|
271
|
+
// AND functional, never one without the other.
|
|
272
|
+
setError("Couldn't restore your previous conversation — started a new one.");
|
|
273
|
+
setErrorCode(CLIENT_ERROR_CODES.THREAD_HISTORY_UNAVAILABLE);
|
|
246
274
|
return;
|
|
247
275
|
}
|
|
248
276
|
// Single decision authority: `applyHistoryResult` runs INSIDE the
|
package/dist/web-adapters.d.ts
CHANGED
|
@@ -163,7 +163,9 @@ export declare function __resetRelayEndpointWarning(): void;
|
|
|
163
163
|
* byte-identical to a miss, and a miss renders the host's placeholder,
|
|
164
164
|
* never an error surface.
|
|
165
165
|
*/
|
|
166
|
-
export declare function createUiResourceReader(options: CreateUiResourceReaderOptions): (resourceUri: string
|
|
166
|
+
export declare function createUiResourceReader(options: CreateUiResourceReaderOptions): (resourceUri: string, hints?: {
|
|
167
|
+
origin?: "live" | "history";
|
|
168
|
+
}) => Promise<ResolvedViewMount | undefined>;
|
|
167
169
|
/** Options for {@link createUiActionRelay} — same credential surface as the reader. */
|
|
168
170
|
export interface CreateUiActionRelayOptions {
|
|
169
171
|
/** The guuey public API base (`…/v1`). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-adapters.d.ts","sourceRoot":"","sources":["../src/web-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAIL,KAAK,iBAAiB,EAEtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAmB,aAAa,EAAE,MAAM,YAAY,CAAC;AAItF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAGpE,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,EAAE,aAiBrC,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAED,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAC9D;;;;;;;;;;;;;;;;;OAiBG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,GAAE,wBAA6B,GAClC,mBAAmB,CAkFrB;AAED,mGAAmG;AACnG,MAAM,WAAW,6BAA6B;IAC5C,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kFAAkF;IAClF,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAID,0FAA0F;AAC1F,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD;AAcD,0FAA0F;AAC1F,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,
|
|
1
|
+
{"version":3,"file":"web-adapters.d.ts","sourceRoot":"","sources":["../src/web-adapters.ts"],"names":[],"mappings":"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"}
|
package/dist/web-adapters.js
CHANGED
|
@@ -256,9 +256,13 @@ export function createUiResourceReader(options) {
|
|
|
256
256
|
};
|
|
257
257
|
};
|
|
258
258
|
const podUrl = options.endpointUrl ? toUiResourceUrl(options.endpointUrl) : null;
|
|
259
|
-
const readResource = async (resourceUri) => {
|
|
259
|
+
const readResource = async (resourceUri, hints) => {
|
|
260
260
|
const query = `?uri=${encodeURIComponent(resourceUri)}`;
|
|
261
|
-
|
|
261
|
+
// guuey#421: a PERSISTED card's locator skips the pod door — pods serve
|
|
262
|
+
// live turns only and 404 such reads by construction; the old
|
|
263
|
+
// pod-first-always order fired a 404 pair on every old-conversation
|
|
264
|
+
// load (noise that read as breakage in every capture).
|
|
265
|
+
if (podUrl !== null && hints?.origin !== "history") {
|
|
262
266
|
const live = await readDoor(`${podUrl}${query}`);
|
|
263
267
|
if (live !== undefined)
|
|
264
268
|
return live;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/agent-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Client SDK for Guuey's agent runtime: the `useAgentInvoke` React hook + pure SSE helpers that speak the /agent/invoke streaming contract, plus the paginated thread-history read plane. Host adapters (storage / id / transport) are injected, so it runs on web (Next) and React Native alike.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@silverprotocol/core": "0.5.1",
|
|
38
|
-
"@guuey/mcp-apps-host": "0.
|
|
38
|
+
"@guuey/mcp-apps-host": "0.15.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": ">=18"
|
package/src/error-codes.ts
CHANGED
|
@@ -89,6 +89,17 @@ export const CLIENT_ERROR_CODES = {
|
|
|
89
89
|
* the reply if the backend completes later.
|
|
90
90
|
*/
|
|
91
91
|
STREAM_STALLED: "STREAM_STALLED",
|
|
92
|
+
/**
|
|
93
|
+
* A RESUMED thread's history read was refused (401 after the one
|
|
94
|
+
* forceRefresh retry) — the persisted threadId exists but the CURRENT
|
|
95
|
+
* identity cannot read it (guuey#413: the identity-drift face; an
|
|
96
|
+
* expired-and-unrefreshable session is the benign sibling). Surfaced
|
|
97
|
+
* LOUDLY instead of the silent fresh-looking boot: the transcript the
|
|
98
|
+
* user expects exists and cannot be shown, which is an ERROR, not an
|
|
99
|
+
* empty chat. Sends still work (the pod may fork a fresh thread) — the
|
|
100
|
+
* error names why the history is missing.
|
|
101
|
+
*/
|
|
102
|
+
THREAD_HISTORY_UNAVAILABLE: "THREAD_HISTORY_UNAVAILABLE",
|
|
92
103
|
} as const;
|
|
93
104
|
|
|
94
105
|
/** One of this SDK's client-originated codes — see {@link CLIENT_ERROR_CODES}. */
|
package/src/history.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function threadHistoryRowsToMessages(rows: ThreadHistoryRow[]): AgentMess
|
|
|
67
67
|
const messages: AgentMessage[] = [];
|
|
68
68
|
for (const row of rows) {
|
|
69
69
|
if (row.kind !== "text" || row.text == null) continue;
|
|
70
|
-
messages.push({ role: row.authorRole === "user" ? "user" : "assistant", text: row.text });
|
|
70
|
+
messages.push({ role: row.authorRole === "user" ? "user" : "assistant", text: row.text, seq: row.seq });
|
|
71
71
|
}
|
|
72
72
|
return messages;
|
|
73
73
|
}
|
package/src/types.ts
CHANGED
|
@@ -26,6 +26,14 @@ export interface AgentMessage {
|
|
|
26
26
|
* join key (`UseAgentInvokeReturn.sendStates`).
|
|
27
27
|
*/
|
|
28
28
|
clientMessageId?: string;
|
|
29
|
+
/**
|
|
30
|
+
* The read plane's transcript `seq` for history-rehydrated entries
|
|
31
|
+
* (guuey#423) — server-allocated, gap-free per thread. Present ONLY on
|
|
32
|
+
* rows the history loader mapped; live turns carry none. The transcript
|
|
33
|
+
* planner uses it to interleave persisted cards at their true positions
|
|
34
|
+
* instead of the R13 tail.
|
|
35
|
+
*/
|
|
36
|
+
seq?: number;
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
/**
|
package/src/useAgentInvoke.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { invokeTurn, toInvokeUrl } from "./invoke-turn.js";
|
|
|
27
27
|
import { AgentResponseError } from "./errors.js";
|
|
28
28
|
import { withActivityObserver } from "./transport.js";
|
|
29
29
|
import { CLIENT_ERROR_CODES } from "./error-codes.js";
|
|
30
|
+
import { HistoryUnauthorizedError } from "./history.js";
|
|
30
31
|
import type {
|
|
31
32
|
AgentInvokeAdapters,
|
|
32
33
|
AgentInvokeStatus,
|
|
@@ -256,8 +257,29 @@ export function useAgentInvoke(opts: UseAgentInvokeOptions): UseAgentInvokeRetur
|
|
|
256
257
|
let result: HistoryLoadResult;
|
|
257
258
|
try {
|
|
258
259
|
result = await history.load(tid);
|
|
259
|
-
} catch {
|
|
260
|
-
|
|
260
|
+
} catch (err) {
|
|
261
|
+
// guuey#413 fail-LOUD carve-out from the best-effort rule: an
|
|
262
|
+
// UNAUTHORIZED read on a RESUMED threadId means a transcript the
|
|
263
|
+
// user expects exists and cannot be shown — silently booting a
|
|
264
|
+
// fresh-looking empty chat hid the identity-drift outage for
|
|
265
|
+
// exactly the accounts holding old threads. Auth refusal surfaces
|
|
266
|
+
// as an error item; every other failure (offline, transient)
|
|
267
|
+
// keeps the best-effort swallow — chat continues without history.
|
|
268
|
+
if (!cancelled && err instanceof HistoryUnauthorizedError) {
|
|
269
|
+
// Same guard as the `gone` arm below: clear + fresh (functional)
|
|
270
|
+
// + the notice (loud). Same concurrency guard — never clobber a
|
|
271
|
+
// threadId a mid-flight send just established.
|
|
272
|
+
if (threadIdRef.current === tid) {
|
|
273
|
+
threadIdRef.current = null;
|
|
274
|
+
setThreadId(null);
|
|
275
|
+
void adaptersRef.current.storage.save(threadStorageKey(appId), "");
|
|
276
|
+
}
|
|
277
|
+
setError(
|
|
278
|
+
"Couldn't restore your previous conversation — started a new one. (This session was not authorized to read the old thread.)",
|
|
279
|
+
);
|
|
280
|
+
setErrorCode(CLIENT_ERROR_CODES.THREAD_HISTORY_UNAVAILABLE);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
261
283
|
}
|
|
262
284
|
if (cancelled) return;
|
|
263
285
|
if ("gone" in result) {
|
|
@@ -269,6 +291,16 @@ export function useAgentInvoke(opts: UseAgentInvokeOptions): UseAgentInvokeRetur
|
|
|
269
291
|
threadIdRef.current = null;
|
|
270
292
|
setThreadId(null);
|
|
271
293
|
void adaptersRef.current.storage.save(threadStorageKey(appId), "");
|
|
294
|
+
// guuey#413: the hydration guard's LOUD half. `gone` covers 403 as
|
|
295
|
+
// well as 404 (history.ts) — an owner-mismatch refusal on a drifted
|
|
296
|
+
// identity flowed through THIS arm as a silent fresh-looking boot,
|
|
297
|
+
// which is the exact outage face this guard exists to kill. The
|
|
298
|
+
// fresh mint stays (functional); the notice makes it honest. Loud
|
|
299
|
+
// AND functional, never one without the other.
|
|
300
|
+
setError(
|
|
301
|
+
"Couldn't restore your previous conversation — started a new one.",
|
|
302
|
+
);
|
|
303
|
+
setErrorCode(CLIENT_ERROR_CODES.THREAD_HISTORY_UNAVAILABLE);
|
|
272
304
|
return;
|
|
273
305
|
}
|
|
274
306
|
// Single decision authority: `applyHistoryResult` runs INSIDE the
|
package/src/web-adapters.ts
CHANGED
|
@@ -305,7 +305,10 @@ export function __resetRelayEndpointWarning(): void {
|
|
|
305
305
|
*/
|
|
306
306
|
export function createUiResourceReader(
|
|
307
307
|
options: CreateUiResourceReaderOptions,
|
|
308
|
-
): (
|
|
308
|
+
): (
|
|
309
|
+
resourceUri: string,
|
|
310
|
+
hints?: { origin?: "live" | "history" },
|
|
311
|
+
) => Promise<ResolvedViewMount | undefined> {
|
|
309
312
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
310
313
|
// A platform door without a pod door is almost always a live surface
|
|
311
314
|
// that forgot `endpointUrl` — its cards would die silently for the whole
|
|
@@ -386,9 +389,16 @@ export function createUiResourceReader(
|
|
|
386
389
|
};
|
|
387
390
|
|
|
388
391
|
const podUrl = options.endpointUrl ? toUiResourceUrl(options.endpointUrl) : null;
|
|
389
|
-
const readResource = async (
|
|
392
|
+
const readResource = async (
|
|
393
|
+
resourceUri: string,
|
|
394
|
+
hints?: { origin?: "live" | "history" },
|
|
395
|
+
): Promise<McpResourceReadResult | undefined> => {
|
|
390
396
|
const query = `?uri=${encodeURIComponent(resourceUri)}`;
|
|
391
|
-
|
|
397
|
+
// guuey#421: a PERSISTED card's locator skips the pod door — pods serve
|
|
398
|
+
// live turns only and 404 such reads by construction; the old
|
|
399
|
+
// pod-first-always order fired a 404 pair on every old-conversation
|
|
400
|
+
// load (noise that read as breakage in every capture).
|
|
401
|
+
if (podUrl !== null && hints?.origin !== "history") {
|
|
392
402
|
const live = await readDoor(`${podUrl}${query}`);
|
|
393
403
|
if (live !== undefined) return live;
|
|
394
404
|
}
|