@burdenoff/fe-libs 2026.1001.4 → 2026.1001.6

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.
Files changed (45) hide show
  1. package/dist/shared/assistant/api.d.ts +12 -0
  2. package/dist/shared/assistant/api.d.ts.map +1 -1
  3. package/dist/shared/assistant/api.js +159 -154
  4. package/dist/shared/assistant/createSandboxAssistantTransport.d.ts.map +1 -1
  5. package/dist/shared/assistant/createSandboxAssistantTransport.js +4 -1
  6. package/dist/shared/assistant/index.d.ts +2 -0
  7. package/dist/shared/assistant/index.d.ts.map +1 -1
  8. package/dist/shared/assistant/permissionError.d.ts +15 -2
  9. package/dist/shared/assistant/permissionError.d.ts.map +1 -1
  10. package/dist/shared/assistant/permissionError.js +24 -14
  11. package/dist/shared/assistant/preview/AssistantPreviewOverlay.js +4 -4
  12. package/dist/shared/assistant/preview/types.d.ts +13 -0
  13. package/dist/shared/assistant/preview/types.d.ts.map +1 -1
  14. package/dist/shared/assistant/preview/useAssistantPreviewBridge.d.ts +21 -1
  15. package/dist/shared/assistant/preview/useAssistantPreviewBridge.d.ts.map +1 -1
  16. package/dist/shared/assistant/preview/useAssistantPreviewBridge.js +1 -1
  17. package/dist/shared/assistant/preview/writeActionResults.d.ts +10 -0
  18. package/dist/shared/assistant/preview/writeActionResults.d.ts.map +1 -0
  19. package/dist/shared/assistant/preview/writeActionResults.js +26 -0
  20. package/dist/shared/assistant/progress.d.ts +9 -1
  21. package/dist/shared/assistant/progress.d.ts.map +1 -1
  22. package/dist/shared/assistant/progress.js +49 -46
  23. package/dist/shared/assistant/quota.d.ts +18 -2
  24. package/dist/shared/assistant/quota.d.ts.map +1 -1
  25. package/dist/shared/assistant/quota.js +46 -42
  26. package/dist/shared/assistant/sandboxProxyError.d.ts +91 -0
  27. package/dist/shared/assistant/sandboxProxyError.d.ts.map +1 -0
  28. package/dist/shared/assistant/sandboxProxyError.js +43 -0
  29. package/dist/shared/assistant/transportErrors.d.ts +14 -1
  30. package/dist/shared/assistant/transportErrors.d.ts.map +1 -1
  31. package/dist/shared/assistant/transportErrors.js +20 -14
  32. package/dist/shared/assistant/turnOutcome.d.ts +27 -3
  33. package/dist/shared/assistant/turnOutcome.d.ts.map +1 -1
  34. package/dist/shared/assistant/turnOutcome.js +82 -31
  35. package/dist/shared/assistant/turnOutcomeCopy.d.ts +24 -0
  36. package/dist/shared/assistant/turnOutcomeCopy.d.ts.map +1 -1
  37. package/dist/shared/assistant/turnOutcomeCopy.js +24 -0
  38. package/dist/shared/assistant/ui/AIAssistantPanel.js +14 -14
  39. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  40. package/dist/shared/assistant/ui/AssistantChatArea.js +3 -2
  41. package/dist/shared/assistant/ui/AssistantHeader.js +4 -4
  42. package/dist/shared/assistant/ui/useWriteProposals.d.ts.map +1 -1
  43. package/dist/shared/assistant/ui/useWriteProposals.js +126 -99
  44. package/dist/shared-assistant.js +181 -179
  45. package/package.json +1 -1
@@ -1,76 +1,80 @@
1
+ import { isAssistantLlmTerminalCode as e } from "./sandboxProxyError.js";
1
2
  //#region src/shared/assistant/quota.ts
2
- function e(e, t) {
3
+ function t(e, t) {
3
4
  if (!e || typeof e != "object") return;
4
5
  let n = e[t];
5
6
  return Array.isArray(n) ? n : void 0;
6
7
  }
7
- function t(e) {
8
- let t = i(e);
9
- if (t) return t === "exhausted";
10
- if (!(e instanceof Error)) return !1;
11
- let n = e.message.toLowerCase();
12
- return n.includes("quota") && (n.includes("exhaust") || n.includes("exceeded"));
8
+ function n(t) {
9
+ let n = a(t);
10
+ if (n) return n === "exhausted";
11
+ if (i(t).some(e) || !(t instanceof Error)) return !1;
12
+ let r = t.message.toLowerCase();
13
+ return r.includes("quota") && (r.includes("exhaust") || r.includes("exceeded"));
13
14
  }
14
- var n = {
15
+ var r = {
15
16
  QUOTA_EXHAUSTED: "exhausted",
16
17
  QUOTA_NOT_PROVISIONED: "not-provisioned"
17
18
  };
18
- function r(t) {
19
- if (!t || typeof t != "object") return [];
20
- let r = [
21
- t,
22
- t.result,
23
- t.networkError
19
+ function i(e) {
20
+ if (!e || typeof e != "object") return [];
21
+ let n = [
22
+ e,
23
+ e.result,
24
+ e.networkError
24
25
  ], i = [];
25
- for (let t of r) {
26
- let n = t?.extensions;
26
+ for (let e of n) {
27
+ let n = e?.extensions;
27
28
  n?.code && i.push(n.code), n?.errorCode && i.push(n.errorCode);
28
- for (let n of e(t, "errors") ?? []) n.extensions?.code && i.push(n.extensions.code), n.extensions?.errorCode && i.push(n.extensions.errorCode);
29
+ for (let n of t(e, "errors") ?? []) n.extensions?.code && i.push(n.extensions.code), n.extensions?.errorCode && i.push(n.extensions.errorCode);
29
30
  }
30
- let a = t.bodyText, o = t instanceof Error ? t.message : void 0;
31
- for (let e of [a, o]) if (typeof e == "string") for (let t of Object.keys(n)) e.includes(t) && i.push(t);
31
+ let a = e.bodyText, o = e instanceof Error ? e.message : void 0;
32
+ for (let e of [a, o]) if (typeof e == "string") for (let t of Object.keys(r)) e.includes(t) && i.push(t);
32
33
  return i;
33
34
  }
34
- function i(e) {
35
- let t = r(e);
36
- if (t.includes("QUOTA_NOT_PROVISIONED")) return "not-provisioned";
37
- if (t.includes("QUOTA_EXHAUSTED")) return "exhausted";
38
- let n = e?.statusCode;
39
- return typeof n == "number" && n === 429 ? "exhausted" : null;
40
- }
41
35
  function a(t) {
42
- if (!t || typeof t != "object") return [];
36
+ let n = i(t);
37
+ if (n.includes("ASSISTANT_DAILY_LIMIT")) return "daily-limit";
38
+ if (n.includes("QUOTA_NOT_PROVISIONED")) return "not-provisioned";
39
+ if (n.includes("QUOTA_EXHAUSTED")) return "exhausted";
40
+ if (n.some(e)) return null;
41
+ let r = t?.statusCode;
42
+ return typeof r == "number" && r === 429 ? "exhausted" : null;
43
+ }
44
+ function o(e) {
45
+ if (!e || typeof e != "object") return [];
43
46
  let n = [
44
- t,
45
- t.result,
46
- t.networkError
47
+ e,
48
+ e.result,
49
+ e.networkError
47
50
  ], r = [];
48
- for (let t of n) {
49
- if (!t || typeof t != "object") continue;
50
- let n = t.extensions;
51
+ for (let e of n) {
52
+ if (!e || typeof e != "object") continue;
53
+ let n = e.extensions;
51
54
  n && typeof n == "object" && r.push(n);
52
- for (let n of e(t, "errors") ?? []) n.extensions && typeof n.extensions == "object" && r.push(n.extensions);
55
+ for (let n of t(e, "errors") ?? []) n.extensions && typeof n.extensions == "object" && r.push(n.extensions);
53
56
  }
54
57
  return r;
55
58
  }
56
- function o(e) {
57
- let n = i(e) ?? (t(e) ? "exhausted" : null);
58
- if (!n) return null;
59
+ function s(e) {
60
+ let t = a(e) ?? (n(e) ? "exhausted" : null);
61
+ if (!t) return null;
59
62
  let r = (t) => {
60
- for (let n of a(e)) {
63
+ for (let n of o(e)) {
61
64
  let e = n[t];
62
65
  if (typeof e == "string" && e.length > 0) return e;
63
66
  }
64
67
  return null;
65
68
  };
66
69
  return {
67
- refusal: n,
70
+ refusal: t,
68
71
  quotaName: r("quotaName"),
69
- traceId: r("traceId")
72
+ traceId: r("traceId"),
73
+ resetsAt: r("resetsAt")
70
74
  };
71
75
  }
72
- function s(e) {
76
+ function c(e) {
73
77
  return `${e}:quota-exhausted`;
74
78
  }
75
79
  //#endregion
76
- export { i as classifyQuotaError, o as describeQuotaError, a as extensionObjectsIn, t as isQuotaExhaustedError, s as quotaExhaustedEventName };
80
+ export { a as classifyQuotaError, s as describeQuotaError, o as extensionObjectsIn, n as isQuotaExhaustedError, c as quotaExhaustedEventName };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * A refusal a sandbox request came back with, kept typed (BOFF-8124 §4.8(c)).
3
+ *
4
+ * ★★ WHY THIS EXISTS. A turn is sent with `prompt-async`: the image answers
5
+ * 202 and runs the turn in a detached watcher. Once platform keys leave the
6
+ * session, the model is reached through a scoped LLM proxy that can refuse a
7
+ * call — a daily limit, a revoked capability, a body too large. Two paths
8
+ * bring that refusal back:
9
+ *
10
+ * - wspace-sandbox-svc refuses the SEND itself when a daily limit is already
11
+ * reached: 429 `{error, code: "ASSISTANT_DAILY_LIMIT", quotaName, resetsAt}`;
12
+ * - the image records a mid-turn refusal and returns it on
13
+ * `/sessions/:id/messages` as `turnTerminal`
14
+ * (`{code, error, status, at, quotaName?, resetsAt?}`).
15
+ *
16
+ * Before this, `proxyToSandbox` threw `new Error(errBody.error)` and dropped the
17
+ * code and the status, and nothing read `turnTerminal` at all: a daily limit
18
+ * either became a bare 429 — which `classifyQuotaError` calls `exhausted`, the
19
+ * one outcome that offers an UPGRADE — or a turn that polled until the client
20
+ * budget ran out and closed as "incomplete".
21
+ *
22
+ * ★ The message stays the body's `error` text, so every substring rule in
23
+ * `transportErrors.ts` and `progress.ts` keeps reading what it read before.
24
+ * The code rides in `extensions`, the shape `extensionObjectsIn` already walks.
25
+ *
26
+ * ★ A LEAF MODULE: no imports. `quota.ts`, `progress.ts` and
27
+ * `transportErrors.ts` read it, and none of them may pull `api.ts` (which
28
+ * imports the store) just to recognise an error.
29
+ */
30
+ /** What rides in `extensions`: only these four, and only as non-empty strings. */
31
+ export interface SandboxProxyErrorExtensions {
32
+ code: string;
33
+ quotaName?: string;
34
+ resetsAt?: string;
35
+ i18nKey?: string;
36
+ }
37
+ export declare class SandboxProxyError extends Error {
38
+ /**
39
+ * The HTTP status the refusal carried: the proxied response's for a refused
40
+ * request, the LLM proxy's for a `turnTerminal`. Null when the source named
41
+ * none — never invented.
42
+ */
43
+ readonly status: number | null;
44
+ readonly extensions: SandboxProxyErrorExtensions;
45
+ constructor(message: string, status: number | null, extensions: SandboxProxyErrorExtensions);
46
+ }
47
+ /**
48
+ * The codes the image reports when a turn ends on a terminal refusal from the
49
+ * assistant LLM proxy (design §4.7; `imageCode` in the mirrored
50
+ * `contract/llm-refusal-contract.json`). The svc's synchronous prompt-async
51
+ * refusal uses `ASSISTANT_DAILY_LIMIT` too.
52
+ */
53
+ export declare const ASSISTANT_LLM_TERMINAL_CODES: readonly ["ASSISTANT_SESSION_REVOKED", "ASSISTANT_LLM_UNAVAILABLE", "ASSISTANT_CONVERSATION_TOO_LONG", "ASSISTANT_DAILY_LIMIT", "ASSISTANT_LLM_BUSY"];
54
+ export type AssistantLlmTerminalCode = (typeof ASSISTANT_LLM_TERMINAL_CODES)[number];
55
+ export declare function isAssistantLlmTerminalCode(code: unknown): code is AssistantLlmTerminalCode;
56
+ /**
57
+ * The terminal LLM code a refusal carries, or null.
58
+ *
59
+ * ★ Read from the error's OWN `extensions` (where `SandboxProxyError` puts
60
+ * it), duck-typed rather than `instanceof`: a second copy of this module in a
61
+ * consumer's bundle must not turn a daily limit back into a retry.
62
+ */
63
+ export declare function assistantLlmTerminalCodeOf(error: unknown): AssistantLlmTerminalCode | null;
64
+ /**
65
+ * Is this worth one retry with a fresh sandbox, as far as a terminal LLM code
66
+ * says? `true`/`false` when the error carries one, `null` when it does not
67
+ * (the caller's own rules decide).
68
+ *
69
+ * ★ Only `ASSISTANT_SESSION_REVOKED` retries: the sandbox's capability no
70
+ * longer verifies, and a fresh sandbox gets a fresh one. A daily limit, a busy
71
+ * or unavailable proxy, or a conversation too long for the model is the same
72
+ * in any sandbox — a replay only spends another provision and another prompt.
73
+ */
74
+ export declare function terminalCodeRecoverability(error: unknown): boolean | null;
75
+ /**
76
+ * The typed error for a refusal body, or null when the body carries no string
77
+ * `code` (the caller then throws exactly what it threw before).
78
+ *
79
+ * `message` is the caller's, unchanged: the body's `error` text or its
80
+ * `Proxy error: <status>` fallback.
81
+ */
82
+ export declare function sandboxProxyErrorFromBody(message: string, status: number | null, body: unknown): SandboxProxyError | null;
83
+ /**
84
+ * The typed error for a `/messages` body's `turnTerminal`, or null when there
85
+ * is none (or it names no code, so it cannot be classified).
86
+ *
87
+ * ★ Its `status` is the LLM proxy's (402 for a daily limit, 429 for busy),
88
+ * never the 200 of the `/messages` read that carried it.
89
+ */
90
+ export declare function sandboxProxyErrorFromTurnTerminal(turnTerminal: unknown): SandboxProxyError | null;
91
+ //# sourceMappingURL=sandboxProxyError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxProxyError.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/sandboxProxyError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,kFAAkF;AAClF,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,2BAA2B,CAAC;gBAG/C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,UAAU,EAAE,2BAA2B;CAO1C;AAED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,uJAM/B,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAClC,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,OAAO,GACZ,IAAI,IAAI,wBAAwB,CAKlC;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,wBAAwB,GAAG,IAAI,CAMjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAIzE;AAKD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,IAAI,EAAE,OAAO,GACZ,iBAAiB,GAAG,IAAI,CAS1B;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,YAAY,EAAE,OAAO,GACpB,iBAAiB,GAAG,IAAI,CAW1B"}
@@ -0,0 +1,43 @@
1
+ //#region src/shared/assistant/sandboxProxyError.ts
2
+ var e = class extends Error {
3
+ status;
4
+ extensions;
5
+ constructor(e, t, n) {
6
+ super(e), this.name = "SandboxProxyError", this.status = t, this.extensions = n;
7
+ }
8
+ }, t = [
9
+ "ASSISTANT_SESSION_REVOKED",
10
+ "ASSISTANT_LLM_UNAVAILABLE",
11
+ "ASSISTANT_CONVERSATION_TOO_LONG",
12
+ "ASSISTANT_DAILY_LIMIT",
13
+ "ASSISTANT_LLM_BUSY"
14
+ ];
15
+ function n(e) {
16
+ return typeof e == "string" && t.includes(e);
17
+ }
18
+ function r(e) {
19
+ if (!e || typeof e != "object") return null;
20
+ let t = e.extensions;
21
+ if (!t || typeof t != "object") return null;
22
+ let r = t.code;
23
+ return n(r) ? r : null;
24
+ }
25
+ function i(e) {
26
+ let t = r(e);
27
+ return t === null ? null : t === "ASSISTANT_SESSION_REVOKED";
28
+ }
29
+ var a = (e) => typeof e == "string" && e.length > 0;
30
+ function o(t, n, r) {
31
+ if (!r || typeof r != "object") return null;
32
+ let i = r;
33
+ if (!a(i.code)) return null;
34
+ let o = { code: i.code };
35
+ return a(i.quotaName) && (o.quotaName = i.quotaName), a(i.resetsAt) && (o.resetsAt = i.resetsAt), a(i.i18nKey) && (o.i18nKey = i.i18nKey), new e(t, n, o);
36
+ }
37
+ function s(e) {
38
+ if (!e || typeof e != "object") return null;
39
+ let t = e, n = typeof t.status == "number" && Number.isInteger(t.status) ? t.status : null;
40
+ return o(a(t.error) ? t.error : `Proxy error: ${n ?? "unknown"}`, n, t);
41
+ }
42
+ //#endregion
43
+ export { t as ASSISTANT_LLM_TERMINAL_CODES, e as SandboxProxyError, r as assistantLlmTerminalCodeOf, n as isAssistantLlmTerminalCode, o as sandboxProxyErrorFromBody, s as sandboxProxyErrorFromTurnTerminal, i as terminalCodeRecoverability };
@@ -35,7 +35,20 @@
35
35
  * the multimodal parts?
36
36
  */
37
37
  export declare function isMultimodalBodyRejection(error: unknown): boolean;
38
- /** A refusal (rate limit, unauthorized) — never cured by another sandbox or a probe. */
38
+ /**
39
+ * A refusal (rate limit, unauthorized) — never cured by another sandbox or a probe.
40
+ *
41
+ * ★ BOFF-8124: so is every assistant LLM refusal but a revoked session (see
42
+ * `terminalCodeRecoverability`).
43
+ */
39
44
  export declare function isNeverRecoverableAssistantError(error: unknown): boolean;
45
+ /**
46
+ * Worth one replay against a fresh sandbox and session?
47
+ *
48
+ * ★★ BOFF-8124 §4.8(c): an assistant LLM refusal is decided by its CODE
49
+ * before any fragment is read — only `ASSISTANT_SESSION_REVOKED` keeps the
50
+ * single retry with a fresh sandbox. A daily limit replayed would provision
51
+ * again only to be refused again.
52
+ */
40
53
  export declare function isRecoverableAssistantError(error: unknown): boolean;
41
54
  //# sourceMappingURL=transportErrors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transportErrors.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/transportErrors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAmCH;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASjE;AA6CD,wFAAwF;AACxF,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAKxE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASnE"}
1
+ {"version":3,"file":"transportErrors.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/transportErrors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAwCH;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAYjE;AA6CD;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOxE;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWnE"}
@@ -1,5 +1,6 @@
1
+ import { assistantLlmTerminalCodeOf as e, terminalCodeRecoverability as t } from "./sandboxProxyError.js";
1
2
  //#region src/shared/assistant/transportErrors.ts
2
- var e = [
3
+ var n = [
3
4
  "failed to fetch",
4
5
  "networkerror",
5
6
  "network request failed",
@@ -11,7 +12,7 @@ var e = [
11
12
  "too many requests",
12
13
  "the server is having trouble",
13
14
  "unexpected error"
14
- ], t = [
15
+ ], r = [
15
16
  "the request could not be processed",
16
17
  "payload too large",
17
18
  "request body exceeds maximum size",
@@ -22,15 +23,16 @@ var e = [
22
23
  "proxy error: 415",
23
24
  "proxy error: 422"
24
25
  ];
25
- function n(n) {
26
- let r = (n instanceof Error ? n.message : String(n)).toLowerCase();
27
- return e.some((e) => r.includes(e)) ? !1 : t.some((e) => r.includes(e));
26
+ function i(t) {
27
+ if (e(t) !== null) return !1;
28
+ let i = (t instanceof Error ? t.message : String(t)).toLowerCase();
29
+ return n.some((e) => i.includes(e)) ? !1 : r.some((e) => i.includes(e));
28
30
  }
29
- var r = [
31
+ var a = [
30
32
  "rate limit exceeded",
31
33
  "unauthorized",
32
34
  "k8s api error 401"
33
- ], i = [
35
+ ], o = [
34
36
  "sandbox not found",
35
37
  "sandbox is not running",
36
38
  "sandbox service not available yet",
@@ -44,13 +46,17 @@ var r = [
44
46
  "unable to connect",
45
47
  "able to access the url"
46
48
  ];
47
- function a(e) {
48
- let t = (e instanceof Error ? e.message : String(e)).toLowerCase();
49
- return r.some((e) => t.includes(e));
49
+ function s(e) {
50
+ let n = t(e);
51
+ if (n !== null) return !n;
52
+ let r = (e instanceof Error ? e.message : String(e)).toLowerCase();
53
+ return a.some((e) => r.includes(e));
50
54
  }
51
- function o(e) {
52
- let t = (e instanceof Error ? e.message : String(e)).toLowerCase();
53
- return r.some((e) => t.includes(e)) ? !1 : i.some((e) => t.includes(e));
55
+ function c(e) {
56
+ let n = t(e);
57
+ if (n !== null) return n;
58
+ let r = (e instanceof Error ? e.message : String(e)).toLowerCase();
59
+ return a.some((e) => r.includes(e)) ? !1 : o.some((e) => r.includes(e));
54
60
  }
55
61
  //#endregion
56
- export { n as isMultimodalBodyRejection, a as isNeverRecoverableAssistantError, o as isRecoverableAssistantError };
62
+ export { i as isMultimodalBodyRejection, s as isNeverRecoverableAssistantError, c as isRecoverableAssistantError };
@@ -24,6 +24,12 @@ export interface TurnOutcome {
24
24
  quotaName: string | null;
25
25
  /** The server's trace id, for support — shown as a reference, never as the message. */
26
26
  traceId: string | null;
27
+ /**
28
+ * A daily limit's reset time (ISO-8601, BOFF-8124), set only when the copy
29
+ * shows it — and only when it parses, so the copy never says "resets at"
30
+ * with no time.
31
+ */
32
+ resetsAt?: string;
27
33
  }
28
34
  /**
29
35
  * Could the failed turn NOT have confirmed an action? (D3, BOFF-7803.) Only
@@ -53,8 +59,9 @@ export declare function turnConfirmsNoAction({ mode, capabilities, }: {
53
59
  * ★★ Order matters: a client refusal first (it never reached a server); then
54
60
  * the usage wall, BEFORE permission — a sandbox quota refusal can also carry a
55
61
  * denial-shaped code, and permission checked first would swallow it and the
56
- * upgrade dialog would never open; then permission; and only what is left is
57
- * temporary. "Temporary" is the honest default for the rest: a network drop, a
62
+ * upgrade dialog would never open; then the LLM proxy's own refusals
63
+ * (BOFF-8124: a daily limit is usage without an upgrade, the rest never read
64
+ * as permission); then permission; and only what is left is temporary. "Temporary" is the honest default for the rest: a network drop, a
58
65
  * timeout, a 5xx, a sandbox that did not come up — retrying can succeed, and
59
66
  * nothing about the person's plan or access is implied.
60
67
  */
@@ -67,6 +74,15 @@ export declare function classifyTurnFailure(error: unknown,
67
74
  options?: {
68
75
  confirmsNoAction?: boolean;
69
76
  }): TurnOutcome;
77
+ /**
78
+ * `{{time}}` for a daily limit: the reset time in the reader's own time zone,
79
+ * written the way `locale` writes times (BOFF-8124 §4.16). Null when the time
80
+ * does not parse.
81
+ *
82
+ * ★ An unknown or malformed locale tag makes `Intl.DateTimeFormat` throw a
83
+ * RangeError; English formatting stands in rather than losing the outcome.
84
+ */
85
+ export declare function formatDailyLimitResetTime(resetsAt: string, locale: string | undefined): string | null;
70
86
  /**
71
87
  * What the outcome says: `text` for the conversation, `headline` alone for
72
88
  * compact surfaces (a preview's end state), and whether it is `translated`.
@@ -82,7 +98,15 @@ options?: {
82
98
  * a Tamil reply under an English interface gets an English outcome, correctly
83
99
  * stamped `en`. The translator has no way to ask for another language.
84
100
  */
85
- export declare function turnOutcomeCopy(outcome: TurnOutcome, tr: AssistantTr): {
101
+ export declare function turnOutcomeCopy(outcome: TurnOutcome, tr: AssistantTr,
102
+ /**
103
+ * `locale`: the INTERFACE locale — the one `tr` resolves in — used to write
104
+ * a daily limit's `{{time}}` (BOFF-8124 §4.16). English copy writes it in
105
+ * English, so a message is never half in another language.
106
+ */
107
+ options?: {
108
+ locale?: string;
109
+ }): {
86
110
  text: string;
87
111
  headline: string;
88
112
  translated: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"turnOutcome.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnOutcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEjE,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GACzB,oBAAoB,GACpB,qBAAqB,GACrB,kBAAkB,GAClB,iBAAiB,GACjB,qBAAqB,GAErB,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;gBAEvB,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAKvD;AAED,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,YAAY,GACZ,cAAc,GACd,WAAW,CAAC;AAEhB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,6BAA6B;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,oFAAoF;IACpF,aAAa,EAAE,OAAO,CAAC;IACvB,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uFAAuF;IACvF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AA2BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,GACb,EAAE;IACD,qCAAqC;IACrC,IAAI,EAAE,aAAa,CAAC;IACpB,sEAAsE;IACtE,YAAY,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,CAAC;CAC3D,GAAG,OAAO,CAMV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO;AACd;;;;GAIG;AACH,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3C,WAAW,CAuCb;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,WAAW,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAuBzD"}
1
+ {"version":3,"file":"turnOutcome.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnOutcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAO1C,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEjE,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GACzB,oBAAoB,GACpB,qBAAqB,GACrB,kBAAkB,GAClB,iBAAiB,GACjB,qBAAqB,GAErB,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;gBAEvB,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAKvD;AAED,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,YAAY,GACZ,cAAc,GACd,WAAW,CAAC;AAEhB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,6BAA6B;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,oFAAoF;IACpF,aAAa,EAAE,OAAO,CAAC;IACvB,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uFAAuF;IACvF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA0DD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,GACb,EAAE;IACD,qCAAqC;IACrC,IAAI,EAAE,aAAa,CAAC;IACpB,sEAAsE;IACtE,YAAY,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,CAAC;CAC3D,GAAG,OAAO,CAMV;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO;AACd;;;;GAIG;AACH,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3C,WAAW,CAkEb;AAQD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,GAAG,IAAI,CAQf;AAmBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,WAAW;AACf;;;;GAIG;AACH,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CA8CzD"}
@@ -1,13 +1,14 @@
1
- import { describeQuotaError as e, extensionObjectsIn as t } from "./quota.js";
2
- import { TURN_OUTCOME_COPY as n } from "./turnOutcomeCopy.js";
3
- import { describePermissionError as r } from "./permissionError.js";
1
+ import { assistantLlmTerminalCodeOf as e } from "./sandboxProxyError.js";
2
+ import { describeQuotaError as t, extensionObjectsIn as n } from "./quota.js";
3
+ import { TURN_OUTCOME_COPY as r } from "./turnOutcomeCopy.js";
4
+ import { describePermissionError as i, permissionRefusalCopyId as a } from "./permissionError.js";
4
5
  //#region src/shared/assistant/turnOutcome.ts
5
- var i = class extends Error {
6
+ var o = class extends Error {
6
7
  reason;
7
8
  constructor(e, t) {
8
9
  super(t), this.name = "AssistantSendRefusal", this.reason = e;
9
10
  }
10
- }, a = {
11
+ }, s = {
11
12
  "confirm-write-mode": {
12
13
  kind: "confirmation",
13
14
  copy: "confirmWriteMode"
@@ -37,54 +38,104 @@ var i = class extends Error {
37
38
  copy: "usageNotRecorded"
38
39
  }
39
40
  };
40
- function o(e, n) {
41
- for (let r of t(e)) {
42
- let e = r[n];
41
+ function c(e) {
42
+ return e === null ? null : Number.isFinite(Date.parse(e)) ? e : null;
43
+ }
44
+ function l(e, t) {
45
+ if (!t) return "usageDailyLimitReachedNoTime";
46
+ switch (e) {
47
+ case "assistant.llm.actor_daily": return "usageDailyLimitReached";
48
+ case "assistant.llm.workspace_daily": return "usageDailyLimitReachedWorkspace";
49
+ default: return "usageDailyLimitReachedPlatform";
50
+ }
51
+ }
52
+ function u(e, t) {
53
+ for (let r of n(e)) {
54
+ let e = r[t];
43
55
  if (typeof e == "string" && e.length > 0) return e;
44
56
  }
45
57
  return null;
46
58
  }
47
- function s({ mode: e, capabilities: t }) {
59
+ function d({ mode: e, capabilities: t }) {
48
60
  return e === "assistant" || t?.proposals === !0 && t.writeApprovalMode === "proposal-v1";
49
61
  }
50
- function c(t, n = {}) {
51
- let s = o(t, "traceId");
52
- if (t instanceof i) return {
53
- ...a[t.reason],
62
+ function f(n, r = {}) {
63
+ let d = u(n, "traceId");
64
+ if (n instanceof o) return {
65
+ ...s[n.reason],
54
66
  offersUpgrade: !1,
55
67
  quotaName: null,
56
68
  traceId: null
57
69
  };
58
- let c = e(t);
59
- if (c) return {
70
+ let f = t(n);
71
+ if (f?.refusal === "daily-limit") {
72
+ let e = c(f.resetsAt);
73
+ return {
74
+ kind: "usage",
75
+ copy: l(f.quotaName, e !== null),
76
+ offersUpgrade: !1,
77
+ quotaName: f.quotaName,
78
+ traceId: f.traceId ?? d,
79
+ ...e === null ? {} : { resetsAt: e }
80
+ };
81
+ }
82
+ if (f) return {
60
83
  kind: "usage",
61
- copy: c.refusal === "exhausted" ? "usageAllowanceReached" : "usageNotProvisioned",
62
- offersUpgrade: c.refusal === "exhausted",
63
- quotaName: c.quotaName,
64
- traceId: c.traceId ?? s
84
+ copy: f.refusal === "exhausted" ? "usageAllowanceReached" : "usageNotProvisioned",
85
+ offersUpgrade: f.refusal === "exhausted",
86
+ quotaName: f.quotaName,
87
+ traceId: f.traceId ?? d
65
88
  };
66
- let l = r(t);
67
- return l ? {
89
+ let p = e(n);
90
+ if (p === "ASSISTANT_CONVERSATION_TOO_LONG") return {
91
+ kind: "temporary",
92
+ copy: "conversationTooLong",
93
+ offersUpgrade: !1,
94
+ quotaName: null,
95
+ traceId: d
96
+ };
97
+ let m = p === null ? i(n) : null;
98
+ return m ? {
68
99
  kind: "permission",
69
- copy: l.refusal === "session" ? "sessionUnverified" : "permissionDenied",
100
+ copy: a(m.refusal),
70
101
  offersUpgrade: !1,
71
102
  quotaName: null,
72
- traceId: s
103
+ traceId: d
73
104
  } : {
74
105
  kind: "temporary",
75
- copy: n.confirmsNoAction === !0 ? "temporaryNotConfirmed" : "temporary",
106
+ copy: r.confirmsNoAction === !0 ? "temporaryNotConfirmed" : "temporary",
76
107
  offersUpgrade: !1,
77
108
  quotaName: null,
78
- traceId: s
109
+ traceId: d
79
110
  };
80
111
  }
81
- function l(e, t) {
82
- let r = n[e.copy], i = t(r.key, r.fallback), a = n.reference, o = e.traceId ? a.fallback.replace("{{id}}", e.traceId) : null, s = e.traceId ? t(a.key, a.fallback, { id: e.traceId }) : null, c = i !== r.fallback && (s === null || s !== o), l = c ? i : r.fallback, u = c ? s : o, d = [e.quotaName, u].filter((e) => !!e);
112
+ var p = {
113
+ hour: "numeric",
114
+ minute: "2-digit",
115
+ timeZoneName: "short"
116
+ };
117
+ function m(e, t) {
118
+ let n = Date.parse(e);
119
+ if (!Number.isFinite(n)) return null;
120
+ try {
121
+ return new Intl.DateTimeFormat(t, p).format(n);
122
+ } catch {
123
+ return new Intl.DateTimeFormat("en", p).format(n);
124
+ }
125
+ }
126
+ function h(e) {
127
+ return e && /^en(?:-|$)/i.test(e) ? e : "en";
128
+ }
129
+ function g(e, t) {
130
+ return t ? e.replace(/\{\{(\w+)\}\}/g, (e, n) => t[n] ?? e) : e;
131
+ }
132
+ function _(e, t, n = {}) {
133
+ let i = e.resetsAt ? m(e.resetsAt, n.locale) : null, a = e.resetsAt ? m(e.resetsAt, h(n.locale)) : null, o = r[i === null && r[e.copy].fallback.includes("{{time}}") ? "usageDailyLimitReachedNoTime" : e.copy], s = i === null ? void 0 : { time: i }, c = t(o.key, o.fallback, s), l = g(o.fallback, a === null ? void 0 : { time: a }), u = r.reference, d = e.traceId ? u.fallback.replace("{{id}}", e.traceId) : null, f = e.traceId ? t(u.key, u.fallback, { id: e.traceId }) : null, p = c !== g(o.fallback, s) && (f === null || f !== d), _ = p ? c : l, v = p ? f : d, y = [e.quotaName, v].filter((e) => !!e);
83
134
  return {
84
- text: d.length ? `${l}\n\n${d.join(" · ")}` : l,
85
- headline: l,
86
- translated: c
135
+ text: y.length ? `${_}\n\n${y.join(" · ")}` : _,
136
+ headline: _,
137
+ translated: p
87
138
  };
88
139
  }
89
140
  //#endregion
90
- export { i as AssistantSendRefusal, c as classifyTurnFailure, s as turnConfirmsNoAction, l as turnOutcomeCopy };
141
+ export { o as AssistantSendRefusal, f as classifyTurnFailure, m as formatDailyLimitResetTime, d as turnConfirmsNoAction, _ as turnOutcomeCopy };
@@ -39,6 +39,22 @@ export declare const TURN_OUTCOME_COPY: {
39
39
  readonly key: "outcome.usageNotRecorded";
40
40
  readonly fallback: "We couldn't record usage for your last reply, so the assistant is paused for a moment. Try again shortly.";
41
41
  };
42
+ readonly usageDailyLimitReached: {
43
+ readonly key: "outcome.usageDailyLimitReached";
44
+ readonly fallback: "You've reached your daily AI assistant limit. It resets at {{time}}.";
45
+ };
46
+ readonly usageDailyLimitReachedWorkspace: {
47
+ readonly key: "outcome.usageDailyLimitReachedWorkspace";
48
+ readonly fallback: "This workspace has reached its daily AI assistant limit. It resets at {{time}}.";
49
+ };
50
+ readonly usageDailyLimitReachedPlatform: {
51
+ readonly key: "outcome.usageDailyLimitReachedPlatform";
52
+ readonly fallback: "The AI assistant has reached today's usage limit. It resets at {{time}}.";
53
+ };
54
+ readonly usageDailyLimitReachedNoTime: {
55
+ readonly key: "outcome.usageDailyLimitReachedNoTime";
56
+ readonly fallback: "You've reached today's AI assistant limit. Try again tomorrow.";
57
+ };
42
58
  readonly permissionDenied: {
43
59
  readonly key: "outcome.permissionDenied";
44
60
  readonly fallback: "You do not have permission to do that in this workspace. Ask someone who administers it for access.";
@@ -47,6 +63,10 @@ export declare const TURN_OUTCOME_COPY: {
47
63
  readonly key: "outcome.sessionUnverified";
48
64
  readonly fallback: "Your session could not be verified for this workspace. Reopen the page, then send again.";
49
65
  };
66
+ readonly provisioningNotPermitted: {
67
+ readonly key: "outcome.provisioningNotPermitted";
68
+ readonly fallback: "The AI assistant isn't available for your role in this workspace yet.";
69
+ };
50
70
  readonly modeWorkspaceAdminOnly: {
51
71
  readonly key: "outcome.modeWorkspaceAdminOnly";
52
72
  readonly fallback: "This assistant mode is only available to workspace admins. Switch to another mode and send again.";
@@ -75,6 +95,10 @@ export declare const TURN_OUTCOME_COPY: {
75
95
  readonly key: "outcome.temporaryNotConfirmed";
76
96
  readonly fallback: "The assistant couldn't finish this just now, and no action was confirmed. It's a temporary problem on our side — not your plan or your access. Try again in a moment.";
77
97
  };
98
+ readonly conversationTooLong: {
99
+ readonly key: "outcome.conversationTooLong";
100
+ readonly fallback: "This conversation is too long for the assistant. Start a new conversation to continue.";
101
+ };
78
102
  readonly reference: {
79
103
  readonly key: "outcome.reference";
80
104
  readonly fallback: "Reference: {{id}}";
@@ -1 +1 @@
1
- {"version":3,"file":"turnOutcomeCopy.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnOutcomeCopy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyFwC,CAAC;AAEvE,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,iBAAiB,CAAC"}
1
+ {"version":3,"file":"turnOutcomeCopy.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnOutcomeCopy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkIwC,CAAC;AAEvE,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,iBAAiB,CAAC"}