@tangle-network/agent-app 0.60.191 → 0.60.193

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 (51) hide show
  1. package/dist/app-auth/index.js +3 -3
  2. package/dist/assistant/index.js +8 -8
  3. package/dist/chat-react/index.js +2 -2
  4. package/dist/chat-routes/attachment-upload.d.ts +1 -1
  5. package/dist/chat-routes/attachment-validation.d.ts +50 -1
  6. package/dist/chat-routes/index.js +16 -82
  7. package/dist/chat-routes/index.js.map +1 -1
  8. package/dist/chat-routes/model-failover-stream.d.ts +8 -0
  9. package/dist/chat-routes/resolve-attachments.d.ts +1 -25
  10. package/dist/chat-routes/sandbox-producer.d.ts +12 -0
  11. package/dist/chat-routes/turn-routes.d.ts +14 -0
  12. package/dist/chat-store/index.js +2 -2
  13. package/dist/{chunk-MSAGTFN4.js → chunk-6RFNLZCK.js} +2 -2
  14. package/dist/{chunk-TNWDYAFX.js → chunk-E6UTFXKQ.js} +4 -4
  15. package/dist/{chunk-Y2SOQOJE.js → chunk-KNTRS7OZ.js} +2 -2
  16. package/dist/{chunk-QAF7ZTO3.js → chunk-L5JLOC2F.js} +4 -4
  17. package/dist/{chunk-WTC6AOPL.js → chunk-PBQYVAB6.js} +82 -2
  18. package/dist/chunk-PBQYVAB6.js.map +1 -0
  19. package/dist/chunk-XELWWXJJ.js +101 -0
  20. package/dist/chunk-XELWWXJJ.js.map +1 -0
  21. package/dist/{chunk-J26IXWFK.js → chunk-XP77DJEF.js} +17 -2
  22. package/dist/chunk-XP77DJEF.js.map +1 -0
  23. package/dist/{chunk-63EKFZOE.js → chunk-ZLX4BA27.js} +15 -1
  24. package/dist/chunk-ZLX4BA27.js.map +1 -0
  25. package/dist/model-resolution/failover.d.ts +16 -2
  26. package/dist/model-resolution/index.d.ts +42 -0
  27. package/dist/model-resolution/index.js +30 -5
  28. package/dist/model-resolution/index.js.map +1 -1
  29. package/dist/operator/chat-adapter.d.ts +9 -0
  30. package/dist/operator/contract.d.ts +11 -1
  31. package/dist/operator/index.js +18 -4
  32. package/dist/operator/index.js.map +1 -1
  33. package/dist/operator/server.d.ts +7 -0
  34. package/dist/policy-filters/index.d.ts +166 -0
  35. package/dist/policy-filters/index.js +23 -0
  36. package/dist/policy-filters/index.js.map +1 -0
  37. package/dist/public-consultation/index.d.ts +1 -1
  38. package/dist/public-consultation/index.js +4 -3
  39. package/dist/public-consultation/index.js.map +1 -1
  40. package/dist/sandbox/index.js +2 -2
  41. package/dist/settings-react/index.js +1 -1
  42. package/dist/tools/index.js +2 -2
  43. package/dist/web-react/index.js +12 -12
  44. package/package.json +6 -1
  45. package/dist/chunk-63EKFZOE.js.map +0 -1
  46. package/dist/chunk-J26IXWFK.js.map +0 -1
  47. package/dist/chunk-WTC6AOPL.js.map +0 -1
  48. /package/dist/{chunk-MSAGTFN4.js.map → chunk-6RFNLZCK.js.map} +0 -0
  49. /package/dist/{chunk-TNWDYAFX.js.map → chunk-E6UTFXKQ.js.map} +0 -0
  50. /package/dist/{chunk-Y2SOQOJE.js.map → chunk-KNTRS7OZ.js.map} +0 -0
  51. /package/dist/{chunk-QAF7ZTO3.js.map → chunk-L5JLOC2F.js.map} +0 -0
@@ -1,11 +1,11 @@
1
+ import {
2
+ noticeEmail
3
+ } from "../chunk-WOTWQ2ST.js";
1
4
  import {
2
5
  createAuthGuard,
3
6
  createBetterAuthSessionCookieMinter,
4
7
  createTangleSsoHandlers
5
8
  } from "../chunk-OGLTKK72.js";
6
- import {
7
- noticeEmail
8
- } from "../chunk-WOTWQ2ST.js";
9
9
  import "../chunk-D6UJEOZQ.js";
10
10
  import "../chunk-UTAIRVOK.js";
11
11
  import "../chunk-RN4WPTBH.js";
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  ReasoningRow,
3
3
  chatToolCallPart
4
- } from "../chunk-Y2SOQOJE.js";
5
- import "../chunk-3HUFJ5LO.js";
4
+ } from "../chunk-KNTRS7OZ.js";
6
5
  import "../chunk-KMIDRUUH.js";
6
+ import "../chunk-3HUFJ5LO.js";
7
7
  import "../chunk-FBVLEGEG.js";
8
8
  import "../chunk-Y6PRDUFJ.js";
9
+ import "../chunk-GEYACSFW.js";
9
10
  import {
10
11
  ChatComposer
11
- } from "../chunk-MSAGTFN4.js";
12
+ } from "../chunk-6RFNLZCK.js";
12
13
  import "../chunk-L7MB2LLM.js";
13
14
  import "../chunk-GNBBY3KN.js";
14
15
  import "../chunk-A2GG4D4A.js";
@@ -20,22 +21,21 @@ import "../chunk-HEPEGY6Q.js";
20
21
  import {
21
22
  ModelPicker
22
23
  } from "../chunk-XG6FODYO.js";
23
- import "../chunk-GEYACSFW.js";
24
24
  import "../chunk-ATQQCG4I.js";
25
25
  import "../chunk-WSEXFTN4.js";
26
- import "../chunk-RASGKEAL.js";
27
26
  import {
28
27
  AsyncView
29
28
  } from "../chunk-AVP5SNIG.js";
29
+ import "../chunk-RASGKEAL.js";
30
30
  import "../chunk-FQYAJYPW.js";
31
- import "../chunk-WTC6AOPL.js";
31
+ import "../chunk-PBQYVAB6.js";
32
32
  import "../chunk-VBRUG4N5.js";
33
33
  import "../chunk-B7CL7ENS.js";
34
34
  import "../chunk-PV33JZKV.js";
35
35
  import "../chunk-AMUXRAUO.js";
36
- import "../chunk-TNWDYAFX.js";
37
- import "../chunk-YHRWZZJN.js";
36
+ import "../chunk-E6UTFXKQ.js";
38
37
  import "../chunk-ZVEEWGDK.js";
38
+ import "../chunk-YHRWZZJN.js";
39
39
  import "../chunk-TXD5HXLE.js";
40
40
  import "../chunk-ZGUXI5SI.js";
41
41
  import "../chunk-6VQCFJWP.js";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  ComposerModeControls,
3
3
  EntryComposer
4
- } from "../chunk-MSAGTFN4.js";
4
+ } from "../chunk-6RFNLZCK.js";
5
5
  import "../chunk-L7MB2LLM.js";
6
6
  import "../chunk-SJWIZT7B.js";
7
7
  import "../chunk-5IS3GCMR.js";
8
8
  import "../chunk-HEPEGY6Q.js";
9
9
  import "../chunk-XG6FODYO.js";
10
10
  import "../chunk-RASGKEAL.js";
11
- import "../chunk-WTC6AOPL.js";
11
+ import "../chunk-PBQYVAB6.js";
12
12
  import "../chunk-VBRUG4N5.js";
13
13
  import "../chunk-AMUXRAUO.js";
14
14
  import "../chunk-YHRWZZJN.js";
@@ -29,7 +29,7 @@
29
29
  */
30
30
  import type { ChatAttachmentKind } from './wire';
31
31
  import { type AtomicAttachmentWriter, type WriteAttachmentFn } from './attachment-store';
32
- import { type AttachmentPathCheck } from './resolve-attachments';
32
+ import { type AttachmentPathCheck } from './attachment-validation';
33
33
  /** Stable authorization result for the original writer contract. */
34
34
  export type AttachmentUploadAuthorization = {
35
35
  ok: true;
@@ -2,7 +2,9 @@
2
2
  * Shared attachment validation core — constants, type-gate, and filename
3
3
  * sanitization used by BOTH the (server) attachment upload route and the
4
4
  * (browser) composer's client-side pre-validation, so a rejection never
5
- * differs depending on which side classified the bytes first.
5
+ * differs depending on which side classified the bytes first. The structural
6
+ * `attachments` parser lives here too, so the chat route and the operator API
7
+ * refuse the same turn bodies without either pulling in the chat store.
6
8
  *
7
9
  * ≈ gtm-agent's `src/lib/attachment-limits.ts`, minus what agent-app already
8
10
  * has (`ATTACHMENT_MAX_COUNT`/`MAX_ATTACHMENT_TOTAL_BYTES`/
@@ -14,6 +16,7 @@
14
16
  * (`tests/browser-safe-subpaths.test.ts` walks the graph), so nothing here
15
17
  * may reach a Node builtin or an engine package.
16
18
  */
19
+ import { type ChatAttachmentInput } from './wire';
17
20
  import type { SniffResult } from './binary-sniff';
18
21
  /** Ceiling on a binary attachment's raw (pre-encoding) byte size. */
19
22
  export declare const MAX_BINARY_ATTACHMENT_BYTES: number;
@@ -93,3 +96,49 @@ export declare function attachmentSizeErrorMessage(name: string, actualBytes: nu
93
96
  /** Human-readable error for a chat message whose combined attachments exceed
94
97
  * the aggregate raw-byte ceiling. */
95
98
  export declare function attachmentTotalSizeErrorMessage(totalBytes: number, limitBytes: number): string;
99
+ /** Verdict of a path check: OK, or a rejection naming why. Mirrors
100
+ * `SandboxMentionPathCheck` in `./wire`. */
101
+ export type AttachmentPathCheck = {
102
+ succeeded: true;
103
+ } | {
104
+ succeeded: false;
105
+ error: string;
106
+ };
107
+ /**
108
+ * Default path validator when a caller supplies none. Rejects the ways a path
109
+ * picked in a client can escape the store root — traversal (`..` segment),
110
+ * absolute (leading `/`), backslashes, null bytes, control characters (see
111
+ * {@link CONTROL_CHARS} — a path also feeds {@link buildAttachmentPromptBlock}'s
112
+ * `(vault: ${path})` pointer, so it is exposed to the same injection surface as
113
+ * `name`) — plus a dotfile/hidden segment (a leading `.` on any segment).
114
+ * Generalized from gtm's `validateVaultFilePath`, in the spirit of
115
+ * `validateSandboxMentionPath` (`/chat-routes`'s wire mention-path validator) —
116
+ * but the dotfile rejection here is INTENTIONALLY stricter than that sibling:
117
+ * an uploaded attachment path is sanitized store-relative storage the product
118
+ * itself assigned, whereas a mention path points at a file that already exists
119
+ * in the sandbox and may legitimately live under a dotfile segment. A caller
120
+ * that needs gtm's exact (looser) rule can supply `validatePath` to override
121
+ * this default entirely.
122
+ */
123
+ export declare function defaultValidateAttachmentPath(path: string): AttachmentPathCheck;
124
+ /** Structural limits for {@link parseChatAttachmentInputs}. */
125
+ export interface ParseChatAttachmentInputsOptions {
126
+ /** Most attachments one request may carry. Default {@link ATTACHMENT_MAX_COUNT}. */
127
+ maxCount?: number;
128
+ /** Path validator override. Default {@link defaultValidateAttachmentPath}. */
129
+ validatePath?: (path: string) => AttachmentPathCheck;
130
+ }
131
+ /**
132
+ * Validate an `attachments` value's shape without reading the store: an
133
+ * array of at most `maxCount` {@link ChatAttachmentInput}s with valid,
134
+ * distinct paths. Absent (`undefined`/`null`) is an empty list. Sizes are
135
+ * still client-reported here; {@link resolveChatAttachments} re-derives them
136
+ * from the store.
137
+ */
138
+ export declare function parseChatAttachmentInputs(value: unknown, options?: ParseChatAttachmentInputsOptions): {
139
+ succeeded: true;
140
+ value: ChatAttachmentInput[];
141
+ } | {
142
+ succeeded: false;
143
+ error: string;
144
+ };
@@ -22,9 +22,11 @@ import {
22
22
  attachmentSizeErrorMessage,
23
23
  attachmentTotalSizeErrorMessage,
24
24
  checkAttachmentType,
25
+ defaultValidateAttachmentPath,
26
+ parseChatAttachmentInputs,
25
27
  sanitizeAttachmentFileName,
26
28
  sniffBinary
27
- } from "../chunk-WTC6AOPL.js";
29
+ } from "../chunk-PBQYVAB6.js";
28
30
  import {
29
31
  DEFAULT_STALE_TURN_LOCK_GRACE_MS,
30
32
  DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS,
@@ -43,13 +45,13 @@ import {
43
45
  readHttpStatusHint,
44
46
  readUpstreamUnavailableCode,
45
47
  runWithModelFailover
46
- } from "../chunk-63EKFZOE.js";
48
+ } from "../chunk-ZLX4BA27.js";
47
49
  import "../chunk-VBRUG4N5.js";
48
50
  import "../chunk-LWSJK546.js";
49
- import "../chunk-QAF7ZTO3.js";
51
+ import "../chunk-L5JLOC2F.js";
50
52
  import "../chunk-6A7MYOUI.js";
51
- import "../chunk-S5SRJJQG.js";
52
53
  import "../chunk-2RCPPOQ4.js";
54
+ import "../chunk-S5SRJJQG.js";
53
55
  import "../chunk-IJAXOQJU.js";
54
56
  import "../chunk-UGWQLQDS.js";
55
57
  import "../chunk-E65YV7VV.js";
@@ -72,7 +74,7 @@ import {
72
74
  rowIdOf,
73
75
  storeSupportsDraftPersistence,
74
76
  streamChatRouteAsSandboxEvents
75
- } from "../chunk-J26IXWFK.js";
77
+ } from "../chunk-XP77DJEF.js";
76
78
  import "../chunk-Q7WEEN7P.js";
77
79
  import "../chunk-UTAIRVOK.js";
78
80
  import "../chunk-RN4WPTBH.js";
@@ -87,7 +89,8 @@ import {
87
89
  attachmentInputToPart,
88
90
  attachmentKindForMime,
89
91
  toChatMessageParts
90
- } from "../chunk-TNWDYAFX.js";
92
+ } from "../chunk-E6UTFXKQ.js";
93
+ import "../chunk-ZVEEWGDK.js";
91
94
  import {
92
95
  ChatTurnInputError,
93
96
  DISPATCH_MAX_MEDIA_PARTS,
@@ -121,7 +124,6 @@ import {
121
124
  turnResponseEventFor,
122
125
  validateSandboxMentionPath
123
126
  } from "../chunk-YHRWZZJN.js";
124
- import "../chunk-ZVEEWGDK.js";
125
127
  import {
126
128
  isWorkspaceFileExportable
127
129
  } from "../chunk-TXD5HXLE.js";
@@ -154,6 +156,7 @@ import {
154
156
  planFollowUpTurnId,
155
157
  planToPersistedPart
156
158
  } from "../chunk-LQYIBL3G.js";
159
+ import "../chunk-XELWWXJJ.js";
157
160
 
158
161
  // src/chat-routes/model-failover-stream.ts
159
162
  var TERMINAL_FAILURE_TYPES = /* @__PURE__ */ new Set(["error", "session.run.failed"]);
@@ -483,6 +486,7 @@ function streamWithModelFailover(options) {
483
486
  const settled = runWithModelFailover({
484
487
  models: options.models,
485
488
  run: probe,
489
+ ...options.policy ? { policy: options.policy } : {},
486
490
  // The probe has already classified the raw payload with
487
491
  // `isUpstreamUnavailable`; this reads its verdict rather than
488
492
  // re-classifying a wrapper object, so the two can never disagree.
@@ -767,6 +771,7 @@ function createSandboxChatProducer(options) {
767
771
  models: chain,
768
772
  open: options.openEvents,
769
773
  log,
774
+ ...options.modelPolicy ? { policy: options.modelPolicy } : {},
770
775
  ...options.openTimeoutMs !== void 0 ? { openTimeoutMs: options.openTimeoutMs } : {},
771
776
  ...options.firstResponseTimeoutMs !== void 0 ? { firstResponseTimeoutMs: options.firstResponseTimeoutMs } : {},
772
777
  ...options.emptyTurnRetries !== void 0 ? { emptyTurnRetries: options.emptyTurnRetries } : {},
@@ -2465,83 +2470,11 @@ function createAtomicAttachmentWriter(input) {
2465
2470
  }
2466
2471
 
2467
2472
  // src/chat-routes/resolve-attachments.ts
2468
- var MAX_ATTACHMENT_NAME_LENGTH = 256;
2469
- function isAttachmentKind(value) {
2470
- return value === "image" || value === "file";
2471
- }
2472
- var CONTROL_CHARS = /[\x00-\x1F\x7F]/;
2473
- function defaultValidateAttachmentPath(path) {
2474
- if (path.includes("\0")) return { succeeded: false, error: "attachment path must not contain null bytes" };
2475
- if (path.includes("\\")) return { succeeded: false, error: "attachment path must not contain backslashes" };
2476
- if (CONTROL_CHARS.test(path)) return { succeeded: false, error: "attachment path must not contain control characters" };
2477
- if (path.startsWith("/")) return { succeeded: false, error: "attachment path must be store-relative, not absolute" };
2478
- const segments = path.split("/");
2479
- if (segments.some((segment) => segment === "..")) {
2480
- return { succeeded: false, error: 'attachment path must not contain ".." segments' };
2481
- }
2482
- if (segments.some((segment) => segment.startsWith("."))) {
2483
- return { succeeded: false, error: "attachment path must not contain a hidden (dotfile) segment" };
2484
- }
2485
- return { succeeded: true };
2486
- }
2487
- function parseAttachmentInput(value, index, validatePath) {
2488
- if (!value || typeof value !== "object" || Array.isArray(value)) {
2489
- return { succeeded: false, error: `attachments[${index}] must be an object` };
2490
- }
2491
- const record2 = value;
2492
- const path = record2.path;
2493
- if (typeof path !== "string" || !path) {
2494
- return { succeeded: false, error: `attachments[${index}].path must be a non-empty string` };
2495
- }
2496
- const name = record2.name;
2497
- if (typeof name !== "string" || !name.trim()) {
2498
- return { succeeded: false, error: `attachments[${index}].name must be a non-empty string` };
2499
- }
2500
- if (name.length > MAX_ATTACHMENT_NAME_LENGTH) {
2501
- return { succeeded: false, error: `attachments[${index}].name must not exceed ${MAX_ATTACHMENT_NAME_LENGTH} characters` };
2502
- }
2503
- if (CONTROL_CHARS.test(name)) {
2504
- return { succeeded: false, error: `attachments[${index}].name must not contain control characters` };
2505
- }
2506
- const size = record2.size;
2507
- if (typeof size !== "number" || !Number.isFinite(size)) {
2508
- return { succeeded: false, error: `attachments[${index}].size must be a finite number` };
2509
- }
2510
- if (size < 0) {
2511
- return { succeeded: false, error: `attachments[${index}].size must not be negative` };
2512
- }
2513
- const mediaType = record2.mediaType;
2514
- if (typeof mediaType !== "string") {
2515
- return { succeeded: false, error: `attachments[${index}].mediaType must be a string` };
2516
- }
2517
- const kind = record2.kind;
2518
- if (!isAttachmentKind(kind)) {
2519
- return { succeeded: false, error: `attachments[${index}].kind must be "image" or "file"` };
2520
- }
2521
- const pathCheck = validatePath(path);
2522
- if (!pathCheck.succeeded) return { succeeded: false, error: pathCheck.error };
2523
- return { succeeded: true, value: { path, name, size, mediaType, kind } };
2524
- }
2525
2473
  async function resolveChatAttachments(value, options) {
2526
- const maxCount = options.maxCount ?? ATTACHMENT_MAX_COUNT;
2527
2474
  const maxTotalBytes = options.maxTotalBytes ?? MAX_ATTACHMENT_TOTAL_BYTES;
2528
- const validatePath = options.validatePath ?? defaultValidateAttachmentPath;
2529
- if (value === void 0 || value === null) return { succeeded: true, value: [] };
2530
- if (!Array.isArray(value)) return { succeeded: false, error: "attachments must be an array" };
2531
- if (value.length > maxCount) {
2532
- return { succeeded: false, error: `attachments must not exceed ${maxCount} entries` };
2533
- }
2534
- const inputs = [];
2535
- const seenPaths = /* @__PURE__ */ new Set();
2536
- for (let index = 0; index < value.length; index += 1) {
2537
- const parsed = parseAttachmentInput(value[index], index, validatePath);
2538
- if (!parsed.succeeded) return parsed;
2539
- if (seenPaths.has(parsed.value.path)) {
2540
- return { succeeded: false, error: `attachments must not repeat a path: ${parsed.value.path}` };
2541
- }
2542
- seenPaths.add(parsed.value.path);
2543
- inputs.push(parsed.value);
2544
- }
2475
+ const parsed = parseChatAttachmentInputs(value, options);
2476
+ if (!parsed.succeeded) return parsed;
2477
+ const inputs = parsed.value;
2545
2478
  const advisoryTotal = inputs.reduce((sum2, input) => sum2 + input.size, 0);
2546
2479
  if (advisoryTotal > maxTotalBytes) {
2547
2480
  return { succeeded: false, error: attachmentTotalSizeErrorMessage(advisoryTotal, maxTotalBytes) };
@@ -3636,6 +3569,7 @@ export {
3636
3569
  normalizeChatPromptForSandbox,
3637
3570
  observeChatTurnStream,
3638
3571
  observeNativeCompletion,
3572
+ parseChatAttachmentInputs,
3639
3573
  parseChatTurnParts,
3640
3574
  parseFileMentions,
3641
3575
  parsePlanFollowUpAttach,