@guuey/agent-client 0.14.1 → 0.14.2
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/useAgentInvoke.d.ts.map +1 -1
- package/dist/useAgentInvoke.js +30 -2
- package/package.json +2 -2
- package/src/error-codes.ts +11 -0
- package/src/useAgentInvoke.ts +34 -2
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
|
};
|
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/agent-client",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2",
|
|
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.14.
|
|
38
|
+
"@guuey/mcp-apps-host": "0.14.2"
|
|
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/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
|