@tangle-network/agent-app 0.43.67 → 0.43.69

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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/assistant/index.d.ts +4 -2
  3. package/dist/assistant/index.js +6 -3
  4. package/dist/assistant/index.js.map +1 -1
  5. package/dist/{attachment-validation-B2FFna9E.d.ts → attachment-validation-Dv1A_Puy.d.ts} +1 -1
  6. package/dist/chat-routes/index.d.ts +4 -3
  7. package/dist/chat-routes/index.js +6 -4
  8. package/dist/chat-routes/index.js.map +1 -1
  9. package/dist/chat-store/index.d.ts +3 -2
  10. package/dist/chat-store/index.js +4 -1
  11. package/dist/chat-store/index.js.map +1 -1
  12. package/dist/{chunk-JWBZ74TW.js → chunk-7ESQUSAC.js} +5 -3
  13. package/dist/{chunk-JWBZ74TW.js.map → chunk-7ESQUSAC.js.map} +1 -1
  14. package/dist/{chunk-X3N2H6JE.js → chunk-AFNTRJQ7.js} +10 -1
  15. package/dist/chunk-AFNTRJQ7.js.map +1 -0
  16. package/dist/chunk-F2CBC4DY.js +193 -0
  17. package/dist/chunk-F2CBC4DY.js.map +1 -0
  18. package/dist/chunk-HRH7ASAG.js +759 -0
  19. package/dist/chunk-HRH7ASAG.js.map +1 -0
  20. package/dist/{chunk-YTSEDJWA.js → chunk-RXOTWZ4G.js} +22 -6
  21. package/dist/chunk-RXOTWZ4G.js.map +1 -0
  22. package/dist/chunk-UDSY2F6N.js +331 -0
  23. package/dist/chunk-UDSY2F6N.js.map +1 -0
  24. package/dist/chunk-UOAYS72M.js +80 -0
  25. package/dist/chunk-UOAYS72M.js.map +1 -0
  26. package/dist/chunk-UP33Z633.js +141 -0
  27. package/dist/chunk-UP33Z633.js.map +1 -0
  28. package/dist/{chunk-FMDMI25K.js → chunk-V55WJSR4.js} +2 -2
  29. package/dist/{chunk-YKBDH2UY.js → chunk-WL7XHLDK.js} +2 -2
  30. package/dist/{chunk-7CTIUCQ4.js → chunk-YEFFHORB.js} +2 -73
  31. package/dist/chunk-YEFFHORB.js.map +1 -0
  32. package/dist/eval-campaign/index.d.ts +2 -81
  33. package/dist/index.d.ts +5 -1
  34. package/dist/index.js +62 -8
  35. package/dist/{parts-Bg8qcDvB.d.ts → parts-2ymE5cs-.d.ts} +15 -2
  36. package/dist/queue-C24V13h9.d.ts +68 -0
  37. package/dist/runtime/index.js +3 -2
  38. package/dist/sandbox/index.js +3 -2
  39. package/dist/teams/index.js +5 -5
  40. package/dist/teams/invitations-api.js +4 -4
  41. package/dist/teams-react/index.js +3 -3
  42. package/dist/tools/index.js +8 -6
  43. package/dist/trust-gate-Dcm5xSva.d.ts +83 -0
  44. package/dist/turn-stream/index.d.ts +185 -24
  45. package/dist/turn-stream/index.js.map +1 -1
  46. package/dist/types-CEchbvgz.d.ts +268 -0
  47. package/dist/web-react/index.d.ts +97 -5
  48. package/dist/web-react/index.js +31 -4
  49. package/dist/work-product/index.d.ts +331 -0
  50. package/dist/work-product/index.js +54 -0
  51. package/dist/work-product/index.js.map +1 -0
  52. package/dist/work-product-react/index.d.ts +36 -0
  53. package/dist/work-product-react/index.js +180 -0
  54. package/dist/work-product-react/index.js.map +1 -0
  55. package/package.json +15 -1
  56. package/dist/chunk-7CTIUCQ4.js.map +0 -1
  57. package/dist/chunk-X3N2H6JE.js.map +0 -1
  58. package/dist/chunk-YTSEDJWA.js.map +0 -1
  59. /package/dist/{chunk-FMDMI25K.js.map → chunk-V55WJSR4.js.map} +0 -0
  60. /package/dist/{chunk-YKBDH2UY.js.map → chunk-WL7XHLDK.js.map} +0 -0
@@ -0,0 +1,68 @@
1
+ import { i as WorkProductRecord, j as WorkProductRef, h as WorkProductProvenance } from './types-CEchbvgz.js';
2
+
3
+ /**
4
+ * The review queue is a PROJECTION, not a store — a client-safe pure fold of
5
+ * existing sources into queue items (the `/missions` events.ts pattern: pure
6
+ * data, re-validation at JSON boundaries). The only genuinely-new durable
7
+ * state behind it is the {@link WorkProductRecord} row and its status
8
+ * machine; everything else reads what already exists:
9
+ *
10
+ * - intake: a chat thread for the engagement scope with NO record yet
11
+ * - missing_info: the open record's thread has a PENDING `/interactions` ask
12
+ * - working: record status `draft` (the live token tail stays on the chat
13
+ * surface's existing running-turns endpoint — the projection tracks no
14
+ * live runs, per the reuse-the-primitive invariant)
15
+ * - ready_for_review / changes_requested / approved / blocked: read directly
16
+ * off `WorkProductRecord.status` (blocked surfaces its unresolved count)
17
+ */
18
+
19
+ type ReviewQueueState = 'intake' | 'missing_info' | 'working' | 'ready_for_review' | 'changes_requested' | 'approved' | 'blocked';
20
+ /** One row of the review queue projection for an engagement scope */
21
+ interface ReviewQueueItem {
22
+ scopeKey: string;
23
+ state: ReviewQueueState;
24
+ threadId: string | null;
25
+ workProduct?: WorkProductRef & {
26
+ title: string;
27
+ kind: string;
28
+ };
29
+ /** The pending `/interactions` ask parking this scope, when any. */
30
+ pendingAsk?: {
31
+ interactionId: string;
32
+ title: string;
33
+ };
34
+ blockingExceptions: number;
35
+ failedChecks: number;
36
+ provenance?: Pick<WorkProductProvenance, 'profileHash' | 'servingModels'>;
37
+ updatedAt: number;
38
+ }
39
+ /** An engagement-scoped chat thread — the intake candidate source. Products
40
+ * that scope threads already carry a scopeKey-style column. */
41
+ interface ReviewQueueThread {
42
+ scopeKey: string;
43
+ threadId: string;
44
+ updatedAt: number;
45
+ }
46
+ /** A pending `/interactions` ask on a thread (from the existing list
47
+ * endpoint) — the missing_info source. */
48
+ interface ReviewQueuePendingAsk {
49
+ threadId: string;
50
+ interactionId: string;
51
+ title: string;
52
+ }
53
+ /** Existing-source inputs the projection folds — no new stores */
54
+ interface ReviewQueueInputs {
55
+ workProducts: readonly WorkProductRecord[];
56
+ /** Engagement threads with no work product yet → intake items. */
57
+ threads?: readonly ReviewQueueThread[];
58
+ /** Pending asks by thread → missing_info override on open records. */
59
+ pendingAsks?: readonly ReviewQueuePendingAsk[];
60
+ }
61
+ /** Fold the existing sources into queue items, newest first. */
62
+ declare function projectReviewQueue(inputs: ReviewQueueInputs): ReviewQueueItem[];
63
+ /** Re-validate one JSON-boundary row into a queue item; null for junk. The
64
+ * client-side twin of the server projection, for payloads that cross a
65
+ * fetch boundary. */
66
+ declare function parseReviewQueueItem(raw: unknown): ReviewQueueItem | null;
67
+
68
+ export { type ReviewQueueInputs as R, type ReviewQueueItem as a, type ReviewQueuePendingAsk as b, type ReviewQueueState as c, type ReviewQueueThread as d, projectReviewQueue as e, parseReviewQueueItem as p };
@@ -8,7 +8,7 @@ import {
8
8
  runToolLoop,
9
9
  streamToolLoop,
10
10
  toLoopEvents
11
- } from "../chunk-JWBZ74TW.js";
11
+ } from "../chunk-7ESQUSAC.js";
12
12
  import {
13
13
  DEFAULT_TANGLE_BILLING_ENFORCEMENT_ENV_VAR,
14
14
  DEFAULT_TANGLE_ROUTER_BASE_URL,
@@ -24,7 +24,8 @@ import {
24
24
  tangleExecutionKeyHttpError,
25
25
  trimOrNull
26
26
  } from "../chunk-JML7WKWU.js";
27
- import "../chunk-7CTIUCQ4.js";
27
+ import "../chunk-UOAYS72M.js";
28
+ import "../chunk-YEFFHORB.js";
28
29
  import {
29
30
  __resetCatalogCache,
30
31
  buildCatalog,
@@ -60,11 +60,12 @@ import {
60
60
  writeProfileFilesToBox
61
61
  } from "../chunk-3ALFBTIW.js";
62
62
  import "../chunk-CQZSAR77.js";
63
- import "../chunk-YKBDH2UY.js";
63
+ import "../chunk-WL7XHLDK.js";
64
64
  import "../chunk-3EJ6SFJI.js";
65
65
  import "../chunk-S5SRJJQG.js";
66
66
  import "../chunk-JML7WKWU.js";
67
- import "../chunk-7CTIUCQ4.js";
67
+ import "../chunk-UOAYS72M.js";
68
+ import "../chunk-YEFFHORB.js";
68
69
  export {
69
70
  DEFAULT_SANDBOX_RESOURCES,
70
71
  ENV_TOTAL_MAX_BYTES,
@@ -1,3 +1,8 @@
1
+ import {
2
+ generateInviteToken,
3
+ isInviteTokenShape,
4
+ validateInviteToken
5
+ } from "../chunk-DJ4VJIH5.js";
1
6
  import {
2
7
  INVITATION_EXPIRY_DAYS,
3
8
  generateInvitationToken,
@@ -7,11 +12,6 @@ import {
7
12
  parseInvitationPermission,
8
13
  renderInvitationEmail
9
14
  } from "../chunk-2DRYTJHI.js";
10
- import {
11
- generateInviteToken,
12
- isInviteTokenShape,
13
- validateInviteToken
14
- } from "../chunk-DJ4VJIH5.js";
15
15
  import {
16
16
  ASSIGNABLE_WORKSPACE_ROLES,
17
17
  ORGANIZATION_ROLES,
@@ -1,3 +1,7 @@
1
+ import {
2
+ SeatLimitError
3
+ } from "../chunk-MEUNTJL5.js";
4
+ import "../chunk-DJ4VJIH5.js";
1
5
  import {
2
6
  generateInvitationToken,
3
7
  getInvitationExpiresAt,
@@ -5,10 +9,6 @@ import {
5
9
  normalizeInvitationEmail,
6
10
  parseInvitationPermission
7
11
  } from "../chunk-2DRYTJHI.js";
8
- import {
9
- SeatLimitError
10
- } from "../chunk-MEUNTJL5.js";
11
- import "../chunk-DJ4VJIH5.js";
12
12
  import {
13
13
  hasWorkspaceRole
14
14
  } from "../chunk-6XIAPIW6.js";
@@ -1,12 +1,12 @@
1
+ import {
2
+ InviteAcceptPage
3
+ } from "../chunk-VCPZ3HTN.js";
1
4
  import {
2
5
  MembersPanel
3
6
  } from "../chunk-S564OFTL.js";
4
7
  import {
5
8
  InvitationsPanel
6
9
  } from "../chunk-5SXS3YAB.js";
7
- import {
8
- InviteAcceptPage
9
- } from "../chunk-VCPZ3HTN.js";
10
10
  import "../chunk-6XIAPIW6.js";
11
11
  export {
12
12
  InvitationsPanel,
@@ -6,7 +6,7 @@ import {
6
6
  restrictTaxonomy,
7
7
  verifyCapabilityToken,
8
8
  verifyExpiringCapabilityToken
9
- } from "../chunk-YKBDH2UY.js";
9
+ } from "../chunk-WL7XHLDK.js";
10
10
  import {
11
11
  DEFAULT_APP_TOOL_PATHS,
12
12
  DEFAULT_HEADER_NAMES,
@@ -19,18 +19,20 @@ import {
19
19
  readToolArgs
20
20
  } from "../chunk-3EJ6SFJI.js";
21
21
  import "../chunk-S5SRJJQG.js";
22
+ import {
23
+ createAppToolRuntimeExecutor,
24
+ dispatchAppTool,
25
+ outcomeStatus
26
+ } from "../chunk-UOAYS72M.js";
22
27
  import {
23
28
  APP_TOOL_NAMES,
24
29
  ToolInputError,
25
30
  buildAppToolOpenAITools,
26
- createAppToolRuntimeExecutor,
27
31
  customToolToOpenAI,
28
32
  defineAppTool,
29
- dispatchAppTool,
30
33
  findCustomTool,
31
- isAppToolName,
32
- outcomeStatus
33
- } from "../chunk-7CTIUCQ4.js";
34
+ isAppToolName
35
+ } from "../chunk-YEFFHORB.js";
34
36
  export {
35
37
  APP_TOOL_NAMES,
36
38
  DEFAULT_APP_TOOL_PATHS,
@@ -0,0 +1,83 @@
1
+ import { JudgeVerdict } from '@tangle-network/agent-eval';
2
+
3
+ /**
4
+ * Trust gate — decides whether an ensemble's scores are allowed to be BELIEVED,
5
+ * one level up from {@link aggregateJudgeVerdicts} (which only reduces ONE
6
+ * artifact's raters to a composite). A composite is a number; this is the check
7
+ * that the number means anything. It is the code "Enforced by" for the
8
+ * measurement-validation skill's after-gate ("is this result allowed to be
9
+ * believed").
10
+ *
11
+ * Three checks, each fail-loud and named in `trustReasons`:
12
+ * (1) inter-rater reliability over the corpus ≥ `irrFloor` — raters that
13
+ * disagree no better than chance carry no signal to optimize against.
14
+ * (2) per-item rater spread ≤ `spreadCeiling` — for EACH item, raters must
15
+ * converge on THAT item.
16
+ * (3) surviving raters per item ≥ `minSurvivors` — a mean over one or two
17
+ * raters is an anecdote, not an ensemble.
18
+ *
19
+ * CRITICAL metric semantics — per-item spread is rater disagreement about the
20
+ * SAME item: `max(score) − min(score)` across the raters that scored THAT item
21
+ * (max over its dimensions), never pooled across different items or across the
22
+ * baseline/candidate sides. Pooling reads a genuine quality gap BETWEEN items as
23
+ * "the raters split" and so trips the gate exactly when the finding is largest —
24
+ * the failure mode the after-gate exists to prevent. The corpus IRR (check 1)
25
+ * leans on the substrate's `interRaterReliability`, whose expected-disagreement
26
+ * denominator already pools across items, so genuine item-to-item variation
27
+ * RAISES reliability rather than lowering it.
28
+ */
29
+
30
+ /** One item's raters: the per-judge verdicts {@link aggregateJudgeVerdicts}
31
+ * reduces, tagged with the item they scored so spread stays within-item. */
32
+ interface TrustItem<D extends string = string> {
33
+ /** Stable item identifier — surfaces in `perItemSpread` and `trustReasons`. */
34
+ itemId: string;
35
+ /** The raters' verdicts for THIS item (one per judge call). A failed judge
36
+ * (`perDimension: null`) is dropped before spread/IRR, never folded as 0. */
37
+ verdicts: readonly JudgeVerdict<D>[];
38
+ }
39
+ /** Thresholds for {@link trustVerdicts}. All overridable; defaults are the
40
+ * conservative after-gate bar. */
41
+ interface TrustThresholds {
42
+ /** Minimum corpus inter-rater reliability (Krippendorff-style α). Below this
43
+ * the raters agree no better than chance. Default 0.2. */
44
+ irrFloor?: number;
45
+ /** Maximum per-item rater spread (`max − min` over a single item's surviving
46
+ * raters, across its dimensions). Above this the raters split ON THAT ITEM.
47
+ * Default 0.5. */
48
+ spreadCeiling?: number;
49
+ /** Minimum surviving (non-failed) raters required per item. Default 3. */
50
+ minSurvivors?: number;
51
+ }
52
+ /** Result of the trust gate. `trustworthy` iff every check passed; `trustReasons`
53
+ * is empty iff `trustworthy`. */
54
+ interface TrustVerdict {
55
+ /** True iff IRR ≥ floor AND every item's spread ≤ ceiling AND every item has
56
+ * ≥ `minSurvivors` surviving raters. */
57
+ trustworthy: boolean;
58
+ /** One entry per FAILED check, each naming its number + the offending value.
59
+ * Empty iff `trustworthy`. */
60
+ trustReasons: string[];
61
+ /** Corpus inter-rater reliability actually measured (the check-1 value). */
62
+ interRaterReliability: number;
63
+ /** Per-item spread (`max − min` over surviving raters, max over dimensions),
64
+ * keyed by `itemId`. The check-2 input, surfaced for drill-down. */
65
+ perItemSpread: Record<string, number>;
66
+ }
67
+ /**
68
+ * Decide whether an ensemble's per-item verdicts are trustworthy enough to
69
+ * believe a lift computed from them. Pure: no LLM, no I/O, no clock, no random —
70
+ * the same `items` + `thresholds` always yield the same verdict.
71
+ *
72
+ * Sibling to {@link aggregateJudgeVerdicts}: that reduces ONE item's raters to a
73
+ * composite; this audits the raters ACROSS items and reports whether the
74
+ * composites are believable. Run it on the corpus of held-out items before
75
+ * reporting any lift over their scores.
76
+ *
77
+ * @throws if `items` is empty — an empty corpus has no measurable trust, and a
78
+ * silent `trustworthy: true` over zero evidence is the exact lie the gate
79
+ * exists to refuse.
80
+ */
81
+ declare function trustVerdicts<D extends string>(items: readonly TrustItem<D>[], thresholds?: TrustThresholds): TrustVerdict;
82
+
83
+ export { type TrustItem as T, type TrustThresholds as a, type TrustVerdict as b, trustVerdicts as t };
@@ -14,6 +14,46 @@ import { d as TurnEventStore } from '../turn-buffer-DGnAPKwa.js';
14
14
  * (`./adapters`). Everything here is plain data + functions — no
15
15
  * `cloudflare:workers`, no storage, no sockets — so the semantics are
16
16
  * unit-testable in Node and the DO stays a thin shell.
17
+ *
18
+ * ── The two-lane rule (measured, not assumed) ────────────────────────────
19
+ *
20
+ * A 4-arm A/B on production (sandbox.tangle.tools, SDK 0.12.0, one box, one
21
+ * gateway client per arm) established which sandbox lane a browser can see:
22
+ *
23
+ * | turn driver | raw turn events | seen at gateway |
24
+ * | ------------------------------------ | --------------- | --------------- |
25
+ * | `box.streamPrompt()` (run/stream) | 71 / 527 / 408 | 0 / 0 / 0 |
26
+ * | `box.session(id).sendMessage()` | 297 | 297 |
27
+ *
28
+ * `POST /agents/run/stream` publishes nothing to the sidecar session event
29
+ * bus, so a `SessionGatewayClient` attached to that session receives zero
30
+ * turn events — three different session-id strategies all got 0, the id was
31
+ * not the variable. `POST /agents/sessions/{id}/messages` publishes to the
32
+ * bus and the gateway delivered every frame, byte-matching the sidecar tail.
33
+ *
34
+ * Consequences for this module, and they cut both ways:
35
+ *
36
+ * 1. INTERACTIVE sandbox turns should be driven on the message lane and
37
+ * tailed by the browser through `box.mintScopedToken({ scope: 'session' })`
38
+ * + `SessionGatewayClient`. Re-broadcasting those same events through the
39
+ * per-turn SEGMENT buffer below duplicates the SDK and adds a worker hop.
40
+ * That half is `@deprecated` (see the tags on {@link createSegmentStore},
41
+ * {@link appendSegmentEvent}, {@link replayActiveSegment} and
42
+ * `broadcastTurnStreamEvent` in `./adapters`).
43
+ * 2. DETACHED/autonomous turns are INVISIBLE to the gateway:
44
+ * `dispatchPrompt({ detach: true })` and `driveTurn` both go through
45
+ * `streamPrompt` internally, i.e. the run/stream lane, which does not fan
46
+ * out. A browser that must tail an unattended run still needs a buffer —
47
+ * `runDetachedTurn` (`/chat-routes`) over the durable turn-event rows
48
+ * below. That half is NOT deprecated and has no SDK replacement today.
49
+ * 3. The LOCK and the per-workspace SIGNALS have no gateway equivalent at
50
+ * all (the gateway is per-session and read-only). They stay canonical.
51
+ *
52
+ * Server-side resume of a run/stream turn is also already solved by the SDK
53
+ * and needs nothing here: `box.streamPrompt('', { executionId, lastEventId })`
54
+ * replays strictly after the cursor without re-dispatching — measured across
55
+ * a SIGKILL mid-run and a fresh process resuming from the cursor alone:
56
+ * 0 lost, 0 duplicated, 0 out-of-order, ids 1..517 contiguous.
17
57
  */
18
58
  /** One event on a turn-stream channel. `seq` is monotonic within a turn
19
59
  * segment and assigned by {@link appendSegmentEvent} on arrival at the DO. */
@@ -24,57 +64,113 @@ interface TurnStreamEvent {
24
64
  seq?: number;
25
65
  }
26
66
  /** Terminal run markers: they close a turn segment and auto-release the
27
- * channel's chat-turn lock for the segment's execution. */
67
+ * channel's chat-turn lock for the segment's execution.
68
+ *
69
+ * KEPT (not deprecated with the segment buffer): the lock auto-release
70
+ * reads it. A product that stops broadcasting turn events to the thread
71
+ * channel loses only that auto-release — the cooperative release on settle
72
+ * (`createDurableTurnLock().release`) and `reconcileStaleDurableTurnLock`
73
+ * both still fire, which is what actually frees a wedged lane. */
28
74
  declare function isTerminalRunEvent(type: string): boolean;
29
75
  /** Define the scope level for acquiring a turn lock within thread or workspace contexts */
30
76
  type TurnLockScope = 'thread' | 'workspace';
31
- /** Generate a unique string key combining workspace and thread identifiers */
77
+ /** Generate a unique string key combining workspace and thread identifiers.
78
+ *
79
+ * KEPT: thread-scope LOCKS are keyed on it (see {@link turnLockChannelKey}).
80
+ * Only its second use — addressing a live-viewer socket for interactive
81
+ * sandbox-turn rebroadcast — is superseded by the session gateway. */
32
82
  declare function threadChannelKey(workspaceId: string, threadId: string): string;
33
- /** Generate a unique channel key based on the given workspace identifier */
83
+ /** Generate a unique channel key based on the given workspace identifier.
84
+ *
85
+ * KEPT and canonical: the per-workspace signal channel (`thread.created`,
86
+ * `thread.activity`) plus workspace-scope locks. The session gateway is
87
+ * per-SESSION and read-only, so it cannot carry either. */
34
88
  declare function workspaceChannelKey(workspaceId: string): string;
35
89
  /** The channel a lock lives on: workspace-scope locks serialize every thread
36
90
  * in the workspace (one shared sandbox), thread-scope locks serialize one
37
91
  * thread (router lane). Same keying as the reference consumer, so a product
38
92
  * swapping its fork for this package contends on identical instances. */
39
93
  declare function turnLockChannelKey(workspaceId: string, threadId: string, scope: TurnLockScope): string;
40
- /** Generate a storage channel key string for a given turn identifier */
94
+ /** Generate a storage channel key string for a given turn identifier.
95
+ *
96
+ * KEPT and canonical: the DETACHED lane's durable turn-event rows live on
97
+ * this instance. A detached run never reaches the session gateway, so this
98
+ * is the only way a browser tails one. */
41
99
  declare function turnStorageChannelKey(turnId: string): string;
42
- /** Generate a unique channel key string based on the provided scope identifier */
100
+ /** Generate a unique channel key string based on the provided scope identifier.
101
+ *
102
+ * KEPT and canonical: backs `TurnEventStore.listRunning`, which is how a
103
+ * reloaded client rediscovers an in-flight DETACHED turn. */
43
104
  declare function scopeIndexChannelKey(scopeId: string): string;
44
- /** Represent a segment of a turn containing events, sequence limit, and terminal status */
105
+ /** DEPRECATED (interactive turn-rebroadcast buffer) — represent a segment of a turn containing events, sequence limit, and terminal status.
106
+ *
107
+ * @deprecated Part of the interactive turn-rebroadcast buffer — see the
108
+ * two-lane rule in this file's header. Removal is a major-version change. */
45
109
  interface TurnSegment {
46
110
  events: TurnStreamEvent[];
47
111
  maxSeq: number;
48
112
  terminal: boolean;
49
113
  }
50
- /** Define a store managing segments and tracking the active execution identifier */
114
+ /** DEPRECATED (interactive turn-rebroadcast buffer) — define a store managing segments and tracking the active execution identifier.
115
+ *
116
+ * @deprecated Part of the interactive turn-rebroadcast buffer — see the
117
+ * two-lane rule in this file's header. Removal is a major-version change. */
51
118
  interface SegmentStore {
52
119
  segments: Map<string, TurnSegment>;
53
120
  activeExecutionId: string | null;
54
121
  }
55
- /** Per-turn replay window. Generous enough for normal turns; a turn that
122
+ /** DEPRECATED (interactive turn-rebroadcast buffer) — per-turn replay window. Generous enough for normal turns; a turn that
56
123
  * exceeds it loses its earliest deltas from replay (a late resumer
57
- * self-heals via the final `result` event + loader revalidation). */
124
+ * self-heals via the final `result` event + loader revalidation).
125
+ *
126
+ * @deprecated Sizes the interactive turn-rebroadcast buffer only. The
127
+ * DETACHED lane's durable rows (`turnEvent:` storage) are uncapped and are
128
+ * not affected. */
58
129
  declare const MAX_SEGMENT_EVENTS = 2000;
59
- /** Recent `thread.created` markers kept for late-connecting sidebars. */
130
+ /** Recent `thread.created` markers kept for late-connecting sidebars.
131
+ *
132
+ * KEPT: a workspace-level signal, not a turn rebroadcast. */
60
133
  declare const MAX_RECENT_CREATED = 50;
61
134
  /** A responding marker older than this is treated as stale, so a dropped
62
135
  * `end` broadcast can't leave a permanently-stuck "responding" dot. */
63
136
  declare const ACTIVITY_TTL_MS: number;
64
- /** Create a SegmentStore with initialized segments and no active execution ID */
137
+ /** DEPRECATED (interactive sandbox-turn rebroadcast; the SDK's session gateway replaces it) — create a SegmentStore with initialized segments and no active execution ID.
138
+ *
139
+ * @deprecated Backs the interactive sandbox-turn rebroadcast, which the
140
+ * sandbox SDK already does better (measured: run/stream → 0 frames at the
141
+ * gateway, message lane → 297/297; see the two-lane rule in this file's
142
+ * header). Sandbox turns: drive on `box.session(id).sendMessage()` and let
143
+ * the browser attach with `box.mintScopedToken({ scope: 'session' })` +
144
+ * `SessionGatewayClient`. Sandbox-FREE turns: `/stream`'s
145
+ * `replayTurnEvents` (`GET /chat/stream/:turnId`) already follows a running
146
+ * turn from a cursor. Detached turns keep the durable turn-event rows —
147
+ * they are a different, non-deprecated lane. Removal is a major-version
148
+ * change; nothing is deleted here. */
65
149
  declare function createSegmentStore(): SegmentStore;
66
150
  /**
67
- * Append a per-turn event to its execution's segment, assigning a monotonic
151
+ * DEPRECATED (interactive turn-rebroadcast buffer) — append a per-turn event to
152
+ * its execution's segment, assigning a monotonic
68
153
  * `seq`. A `session.run.started` (or the first-seen event for an execution)
69
154
  * opens a fresh segment, makes it active, and drops prior turns' buffers so a
70
155
  * resumer only ever replays the current turn. A terminal run event marks the
71
156
  * segment terminal. Returns the seq-stamped event to broadcast.
157
+ *
158
+ * @deprecated The interactive rebroadcast half — {@link createSegmentStore}
159
+ * names the replacement per lane; this file's header holds the measurement.
72
160
  */
73
161
  declare function appendSegmentEvent(store: SegmentStore, executionId: string, incoming: TurnStreamEvent, maxEvents?: number): TurnStreamEvent;
74
162
  /**
75
- * Events of the active, non-terminal turn with `seq > afterSeq` — what a
163
+ * DEPRECATED (interactive turn-rebroadcast buffer; the SDK replays losslessly on
164
+ * both lanes) — events of the active, non-terminal turn with `seq > afterSeq`,
165
+ * i.e. what a
76
166
  * (re)connecting client replays before going live. A terminal (finished) turn
77
167
  * replays nothing: the client falls back to the loader's persisted row.
168
+ *
169
+ * @deprecated The interactive rebroadcast half — {@link createSegmentStore}
170
+ * names the replacement per lane. The SDK's own reconnect replay is
171
+ * `SessionGatewayClient` + `lastEventId` (browser) or
172
+ * `box.streamPrompt('', { executionId, lastEventId })` (worker); both were
173
+ * measured lossless.
78
174
  */
79
175
  declare function replayActiveSegment(store: SegmentStore, afterSeq: number): TurnStreamEvent[];
80
176
  /**
@@ -86,7 +182,12 @@ declare function pruneStaleThreads(active: Map<string, number>, now: number, ttl
86
182
  /** Default lifetime of an unreleased lock. Long enough that a legitimately
87
183
  * slow sandbox turn never loses its guard mid-run; the way OUT of a wedge is
88
184
  * never the TTL but `reconcileStaleTurnLock` (in `/chat-routes`), which
89
- * probes the execution's actual state. */
185
+ * probes the execution's actual state.
186
+ *
187
+ * Everything from here down is the LOCK, and it is fully KEPT. The sandbox
188
+ * SDK ships no single-flight primitive — the session gateway is a read-only
189
+ * fanout — so moving a product to the message lane changes nothing about
190
+ * who is allowed to start a turn. */
90
191
  declare const TURN_LOCK_TTL_MS: number;
91
192
  /** The stored single-flight lock. Field-compatible with the reference
92
193
  * consumer's `ChatTurnLock` so adoption is a swap, not a migration. */
@@ -199,17 +300,23 @@ declare function turnEventStorageKey(seq: number): string;
199
300
  * core (`./core`). One class serves every channel family; the instance NAME
200
301
  * decides which endpoints a given instance ever sees:
201
302
  *
202
- * - **thread channel** (`${workspaceId}:${threadId}`) — the live chat turn:
203
- * WebSocket fanout, per-turn segments with `sync`/`afterSeq` reconnect
204
- * replay, and the thread-scope lock.
303
+ * - **thread channel** (`${workspaceId}:${threadId}`) — the thread-scope lock
304
+ * (KEPT), plus the live turn rebroadcast: WebSocket fanout and per-turn
305
+ * segments with `sync`/`afterSeq` reconnect replay. That rebroadcast is
306
+ * `@deprecated` for sandbox-backed interactive turns — the sandbox session
307
+ * gateway already does it, browser-direct, when the turn is driven on the
308
+ * message lane (`./core`'s header has the production measurement).
205
309
  * - **workspace channel** (`${workspaceId}`) — coarse sidebar signals
206
310
  * (`thread.activity` responding set, durable across eviction;
207
- * `thread.created` recent list) and the workspace-scope lock.
311
+ * `thread.created` recent list) and the workspace-scope lock. KEPT: the
312
+ * gateway is per-session and read-only, so it carries neither.
208
313
  * - **turn storage** (`turn:${turnId}`) — the durable `TurnEventStore` rows +
209
314
  * status for one buffered turn (replay survives DO eviction — this is what
210
- * graduates the vertical's `turnStore` from no-op).
315
+ * graduates the vertical's `turnStore` from no-op). KEPT and load-bearing:
316
+ * a DETACHED run never reaches the gateway, so this is the only way a
317
+ * browser tails autonomous work.
211
318
  * - **scope index** (`scope:${scopeId}`) — the running-turn index backing
212
- * `TurnEventStore.listRunning` reconnect discovery.
319
+ * `TurnEventStore.listRunning` reconnect discovery. KEPT.
213
320
  *
214
321
  * The class is a PLAIN class over a structural {@link TurnStreamDOState} —
215
322
  * no `cloudflare:workers` import, so this package stays substrate-free and
@@ -345,9 +452,21 @@ declare class TurnStreamDO {
345
452
  * Live fanout is deliberately NOT a side effect of the turn-event store: the
346
453
  * store is keyed by turnId/scopeId while viewer sockets live on the
347
454
  * `${workspaceId}:${threadId}` channel, and only the product's per-turn
348
- * context knows both. Products wire {@link broadcastTurnStreamEvent} (and the
349
- * workspace helpers) into `createChatTurnRoutes`' `onEvent` — the same
350
- * contract the reference consumer already runs.
455
+ * context knows both. Products wire the workspace signal helpers into
456
+ * `createChatTurnRoutes`' `onEvent`.
457
+ *
458
+ * Which adapters are still the right answer (see `./core`'s header for the
459
+ * production measurement behind this split):
460
+ *
461
+ * | adapter | status |
462
+ * | ------------------------------------ | --------------------------------- |
463
+ * | {@link createDurableTurnLock} | KEPT — no SDK equivalent |
464
+ * | {@link reconcileStaleDurableTurnLock}| KEPT — no SDK equivalent |
465
+ * | {@link createDurableObjectTurnEventStore} | KEPT — the DETACHED lane |
466
+ * | {@link broadcastWorkspaceActivity} | KEPT — workspace signal |
467
+ * | {@link broadcastThreadCreated} | KEPT — workspace signal |
468
+ * | {@link createTurnStreamUpgradeHandler} | KEPT for the workspace channel |
469
+ * | {@link broadcastTurnStreamEvent} | `@deprecated` for sandbox turns |
351
470
  */
352
471
 
353
472
  /** Resolve a stub interface for handling fetch requests with optional initialization parameters */
@@ -366,6 +485,15 @@ interface TurnStreamNamespaceLike {
366
485
  * live channel). Each buffered turn lives on its own `turn:<turnId>` DO
367
486
  * instance; `listRunning` reconnect discovery rides a per-scope index
368
487
  * instance. Drops in wherever `createD1TurnEventStore(env.DB)` would.
488
+ *
489
+ * KEPT and load-bearing for AUTONOMOUS work. A detached run
490
+ * (`dispatchPrompt({ detach: true })`, `driveTurn`) executes on the sandbox
491
+ * run/stream lane, which publishes nothing to the session event bus — a
492
+ * `SessionGatewayClient` attached to that session sees zero turn events
493
+ * (measured: 0 of 71 / 0 of 527 / 0 of 408 across three session-id
494
+ * strategies). So a browser that must tail a mission step, a queue job, or
495
+ * an inbound-email review has no SDK path; it needs these durable rows plus
496
+ * `runDetachedTurn` (`/chat-routes`). Nothing here is deprecated.
369
497
  */
370
498
  declare function createDurableObjectTurnEventStore(namespace: TurnStreamNamespaceLike): TurnEventStore;
371
499
  /** Define input parameters required to acquire a durable turn lock in a workspace thread context */
@@ -478,11 +606,36 @@ declare function createDurableTurnLock<TContext>(options: CreateDurableTurnLockO
478
606
  release(handle: unknown): Promise<void>;
479
607
  };
480
608
  /**
481
- * Fan a turn event out to the per-thread channel. `executionId` groups events
609
+ * DEPRECATED for sandbox-backed interactive turns (drive on the session-message
610
+ * lane + `SessionGatewayClient` instead) — fan a turn event out to the
611
+ * per-thread channel. `executionId` groups events
482
612
  * into a per-turn segment with a monotonic seq, so a reconnecting client
483
613
  * replays only the active turn and resumes from a cursor. Callers MUST await
484
614
  * (the DO assigns seq on arrival — emission order matters); failures are
485
615
  * swallowed (fanout is best-effort and never breaks chat delivery).
616
+ *
617
+ * @deprecated For a SANDBOX-backed interactive turn this re-broadcasts events
618
+ * the sandbox platform already fans out, at the cost of a worker hop. Drive
619
+ * the turn on the session-MESSAGE lane instead —
620
+ * `box.createSession({ sessionId, backend })` then
621
+ * `box.session(id).sendMessage({ parts: [{ type: 'text', text }] })` — and let
622
+ * the tab attach with `box.mintScopedToken({ scope: 'session', sessionId,
623
+ * runtimeSessionId })` + `SessionGatewayClient`
624
+ * (`@tangle-network/sandbox/session-gateway`). Measured on production
625
+ * (4 arms, SDK 0.12.0): turns driven with `box.streamPrompt()` delivered
626
+ * 0 of 71 / 0 of 527 / 0 of 408 turn events to a gateway client, because
627
+ * `POST /agents/run/stream` publishes nothing to the session event bus;
628
+ * the message lane delivered 297 of 297.
629
+ *
630
+ * Two things this deprecation does NOT cover, both still supported:
631
+ * DETACHED runs (no gateway fanout at all — keep `runDetachedTurn` over the
632
+ * durable turn-event rows) and the per-workspace signals
633
+ * ({@link broadcastWorkspaceActivity} / {@link broadcastThreadCreated}).
634
+ * A SANDBOX-FREE copilot that wants a second viewer should use `/stream`'s
635
+ * `replayTurnEvents` (`GET /chat/stream/:turnId`), which follows a running
636
+ * turn from a cursor without a second broadcast fabric.
637
+ *
638
+ * Kept for back-compat; removal is a major-version change.
486
639
  */
487
640
  declare function broadcastTurnStreamEvent(namespace: TurnStreamNamespaceLike, input: {
488
641
  workspaceId: string;
@@ -530,6 +683,14 @@ interface CreateTurnStreamUpgradeHandlerOptions {
530
683
  *
531
684
  * After the 101, the client sends `{type:'sync', afterSeq}` and receives the
532
685
  * replay-then-live stream (see {@link TurnStreamDO.webSocketMessage}).
686
+ *
687
+ * NOT deprecated — the workspace variant (no `threadId`) is the canonical
688
+ * transport for the per-workspace signals, which the session gateway cannot
689
+ * carry (it is per-session and read-only). The THREAD variant is the
690
+ * deprecated half: for a sandbox-backed interactive turn the tab should
691
+ * attach to the session gateway directly instead of to this socket. See
692
+ * {@link broadcastTurnStreamEvent} for the measurement and the replacement
693
+ * wiring.
533
694
  */
534
695
  declare function createTurnStreamUpgradeHandler(options: CreateTurnStreamUpgradeHandlerOptions): (request: Request) => Promise<Response | null>;
535
696