@gatherthread/dsh-host 0.1.0-alpha.8 → 0.1.0-beta.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.
@@ -1050,9 +1050,9 @@ function floatSafeRemainder(val, step) {
1050
1050
  return ratio - roundedRatio;
1051
1051
  }
1052
1052
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
1053
- function defineLazy(object2, key, getter) {
1053
+ function defineLazy(object3, key, getter) {
1054
1054
  let value = void 0;
1055
- Object.defineProperty(object2, key, {
1055
+ Object.defineProperty(object3, key, {
1056
1056
  get() {
1057
1057
  if (value === EVALUATING) {
1058
1058
  return void 0;
@@ -1064,7 +1064,7 @@ function defineLazy(object2, key, getter) {
1064
1064
  return value;
1065
1065
  },
1066
1066
  set(v) {
1067
- Object.defineProperty(object2, key, {
1067
+ Object.defineProperty(object3, key, {
1068
1068
  value: v
1069
1069
  // configurable: true,
1070
1070
  });
@@ -1598,16 +1598,16 @@ function cleanEnum(obj) {
1598
1598
  }
1599
1599
  function base64ToUint8Array(base643) {
1600
1600
  const binaryString = atob(base643);
1601
- const bytes = new Uint8Array(binaryString.length);
1601
+ const bytes2 = new Uint8Array(binaryString.length);
1602
1602
  for (let i = 0; i < binaryString.length; i++) {
1603
- bytes[i] = binaryString.charCodeAt(i);
1603
+ bytes2[i] = binaryString.charCodeAt(i);
1604
1604
  }
1605
- return bytes;
1605
+ return bytes2;
1606
1606
  }
1607
- function uint8ArrayToBase64(bytes) {
1607
+ function uint8ArrayToBase64(bytes2) {
1608
1608
  let binaryString = "";
1609
- for (let i = 0; i < bytes.length; i++) {
1610
- binaryString += String.fromCharCode(bytes[i]);
1609
+ for (let i = 0; i < bytes2.length; i++) {
1610
+ binaryString += String.fromCharCode(bytes2[i]);
1611
1611
  }
1612
1612
  return btoa(binaryString);
1613
1613
  }
@@ -1616,22 +1616,22 @@ function base64urlToUint8Array(base64url3) {
1616
1616
  const padding = "=".repeat((4 - base643.length % 4) % 4);
1617
1617
  return base64ToUint8Array(base643 + padding);
1618
1618
  }
1619
- function uint8ArrayToBase64url(bytes) {
1620
- return uint8ArrayToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1619
+ function uint8ArrayToBase64url(bytes2) {
1620
+ return uint8ArrayToBase64(bytes2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1621
1621
  }
1622
1622
  function hexToUint8Array(hex3) {
1623
1623
  const cleanHex = hex3.replace(/^0x/, "");
1624
1624
  if (cleanHex.length % 2 !== 0) {
1625
1625
  throw new Error("Invalid hex string length");
1626
1626
  }
1627
- const bytes = new Uint8Array(cleanHex.length / 2);
1627
+ const bytes2 = new Uint8Array(cleanHex.length / 2);
1628
1628
  for (let i = 0; i < cleanHex.length; i += 2) {
1629
- bytes[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1629
+ bytes2[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1630
1630
  }
1631
- return bytes;
1631
+ return bytes2;
1632
1632
  }
1633
- function uint8ArrayToHex(bytes) {
1634
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1633
+ function uint8ArrayToHex(bytes2) {
1634
+ return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
1635
1635
  }
1636
1636
  var Class = class {
1637
1637
  constructor(..._args) {
@@ -16131,8 +16131,8 @@ function foldObjects(members2) {
16131
16131
  }
16132
16132
  const properties = {};
16133
16133
  const required2 = /* @__PURE__ */ new Set();
16134
- for (const object2 of objects) {
16135
- for (const key in object2.properties) {
16134
+ for (const object3 of objects) {
16135
+ for (const key in object3.properties) {
16136
16136
  if (Object.prototype.hasOwnProperty.call(properties, key))
16137
16137
  continue;
16138
16138
  const parts = [];
@@ -16146,18 +16146,18 @@ function foldObjects(members2) {
16146
16146
  const merged = parts.length === 1 ? parts[0] : foldObjects(parts) ?? { allOf: parts };
16147
16147
  assignProp(properties, key, merged);
16148
16148
  }
16149
- for (const key of object2.required ?? [])
16149
+ for (const key of object3.required ?? [])
16150
16150
  required2.add(key);
16151
16151
  }
16152
16152
  const folded = { type: "object", properties };
16153
16153
  if (required2.size)
16154
16154
  folded.required = [...required2];
16155
- if (objects.every((object2) => object2.additionalProperties === false)) {
16155
+ if (objects.every((object3) => object3.additionalProperties === false)) {
16156
16156
  folded.additionalProperties = false;
16157
16157
  } else {
16158
16158
  const constraints = [];
16159
- for (const object2 of objects) {
16160
- const constraint = undeclaredConstraint(object2);
16159
+ for (const object3 of objects) {
16160
+ const constraint = undeclaredConstraint(object3);
16161
16161
  if (constraint && !constraints.some((seen) => JSON.stringify(seen) === JSON.stringify(constraint)))
16162
16162
  constraints.push(constraint);
16163
16163
  }
@@ -19996,6 +19996,28 @@ function date4(params) {
19996
19996
  return _coercedDate(ZodDate, params);
19997
19997
  }
19998
19998
 
19999
+ // ../protocol/dist/src/live-output.js
20000
+ var utf8 = (maximum) => external_exports.string().refine((value) => new TextEncoder().encode(value).length <= maximum, "Live output is too large");
20001
+ var LiveOutputPayloadSchema = external_exports.object({
20002
+ content: utf8(24 * 1024),
20003
+ phase: external_exports.literal("stream"),
20004
+ stream_id: external_exports.string().uuid(),
20005
+ stream_mode: external_exports.literal("snapshot"),
20006
+ stream_kind: external_exports.enum(["answer", "reasoning", "tool", "plan"]),
20007
+ stream_revision: external_exports.number().int().min(1).max(1200),
20008
+ stream_state: external_exports.enum(["running", "completed", "failed"]),
20009
+ title: utf8(256).optional(),
20010
+ plan: external_exports.array(external_exports.object({ step: utf8(512), status: external_exports.enum(["pending", "in_progress", "completed"]) }).strict()).max(64).optional(),
20011
+ status: external_exports.enum(["thinking", "running"]).optional(),
20012
+ occurred_at: external_exports.string().datetime().optional(),
20013
+ capture_fidelity: external_exports.literal("harness_transcript").optional(),
20014
+ source_harness: external_exports.string().min(1).max(80).optional()
20015
+ }).strict().superRefine((value, context) => {
20016
+ if (value.stream_kind === "plan" !== (value.plan !== void 0)) {
20017
+ context.addIssue({ code: "custom", message: "Only plan snapshots carry plan steps" });
20018
+ }
20019
+ });
20020
+
19999
20021
  // ../protocol/dist/src/code-sync.js
20000
20022
  var CODE_SYNC_MAX_FILES = 1e3;
20001
20023
  var CODE_SYNC_MAX_FILE_BYTES = 2 * 1024 * 1024;
@@ -20032,34 +20054,42 @@ function isCodeSyncPathAllowed(path5) {
20032
20054
  return !/\.(?:pem|p12|pfx|key)$/iu.test(lower) && !/^(?:id_rsa|id_ed25519)(?:\.|$)/iu.test(lower);
20033
20055
  });
20034
20056
  }
20035
- var CodeFileSchema = external_exports.object({
20036
- path: external_exports.string().refine(isCodeSyncPathAllowed, "Unsafe or private code path"),
20037
- content_base64: external_exports.string().max(4 * Math.ceil(CODE_SYNC_MAX_FILE_BYTES / 3)).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
20038
- executable: external_exports.boolean()
20039
- }).strict();
20040
- var CodeFilesSchema = external_exports.array(CodeFileSchema).max(CODE_SYNC_MAX_FILES).superRefine((files, context) => {
20041
- let size = 0;
20042
- const names = /* @__PURE__ */ new Set();
20043
- for (const [index, file2] of files.entries()) {
20044
- const bytes = file2.content_base64.length * 3 / 4 - (file2.content_base64.endsWith("==") ? 2 : file2.content_base64.endsWith("=") ? 1 : 0);
20045
- size += bytes;
20046
- const normalized = portablePathKey(file2.path);
20047
- if (bytes > CODE_SYNC_MAX_FILE_BYTES || names.has(normalized))
20048
- context.addIssue({ code: "custom", path: [index], message: "File limit or duplicate portable path" });
20049
- names.add(normalized);
20050
- }
20051
- if (size > CODE_SYNC_MAX_SNAPSHOT_BYTES)
20052
- context.addIssue({ code: "custom", message: "Code snapshot exceeds 8 MiB" });
20053
- for (const name2 of names) {
20054
- const parts = name2.split("/");
20055
- parts.pop();
20056
- while (parts.length) {
20057
- if (names.has(parts.join("/")))
20058
- context.addIssue({ code: "custom", message: "File and directory paths overlap" });
20057
+ var CLOUD_CODE_SYNC_LIMITS = { maxFiles: CODE_SYNC_MAX_FILES, maxFileBytes: CODE_SYNC_MAX_FILE_BYTES, maxSnapshotBytes: CODE_SYNC_MAX_SNAPSHOT_BYTES };
20058
+ var GITHUB_CODE_SYNC_LIMITS = { maxFiles: 1e4, maxFileBytes: 20 * 1024 * 1024, maxSnapshotBytes: 128 * 1024 * 1024 };
20059
+ function createCodeFileSchema(limits) {
20060
+ return external_exports.object({
20061
+ path: external_exports.string().refine(isCodeSyncPathAllowed, "Unsafe or private code path"),
20062
+ content_base64: external_exports.string().max(4 * Math.ceil(limits.maxFileBytes / 3)).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
20063
+ executable: external_exports.boolean()
20064
+ }).strict();
20065
+ }
20066
+ var CodeFileSchema = createCodeFileSchema(CLOUD_CODE_SYNC_LIMITS);
20067
+ function createCodeFilesSchema(limits) {
20068
+ return external_exports.array(createCodeFileSchema(limits)).max(limits.maxFiles).superRefine((files, context) => {
20069
+ let size = 0;
20070
+ const names = /* @__PURE__ */ new Set();
20071
+ for (const [index, file2] of files.entries()) {
20072
+ const bytes2 = file2.content_base64.length * 3 / 4 - (file2.content_base64.endsWith("==") ? 2 : file2.content_base64.endsWith("=") ? 1 : 0);
20073
+ size += bytes2;
20074
+ const normalized = portablePathKey(file2.path);
20075
+ if (bytes2 > limits.maxFileBytes || names.has(normalized))
20076
+ context.addIssue({ code: "custom", path: [index], message: "File limit or duplicate portable path" });
20077
+ names.add(normalized);
20078
+ }
20079
+ if (size > limits.maxSnapshotBytes)
20080
+ context.addIssue({ code: "custom", message: "Code snapshot exceeds provider limit" });
20081
+ for (const name2 of names) {
20082
+ const parts = name2.split("/");
20059
20083
  parts.pop();
20084
+ while (parts.length) {
20085
+ if (names.has(parts.join("/")))
20086
+ context.addIssue({ code: "custom", message: "File and directory paths overlap" });
20087
+ parts.pop();
20088
+ }
20060
20089
  }
20061
- }
20062
- });
20090
+ });
20091
+ }
20092
+ var CodeFilesSchema = createCodeFilesSchema(CLOUD_CODE_SYNC_LIMITS);
20063
20093
  var CodeEnableInputSchema = external_exports.object({ idempotency_key: Key }).strict();
20064
20094
  var CodeDisableInputSchema = external_exports.object({ idempotency_key: Key }).strict();
20065
20095
  var CodeCheckpointInputSchema = external_exports.object({
@@ -20121,6 +20151,159 @@ var CodeSnapshotResultSchema = external_exports.object({ snapshot: external_expo
20121
20151
  }).strict() }).strict();
20122
20152
  var codeSyncRequestKinds = ["code_sync_status", "code_upload", "code_download", "code_recover", "code_auto_upload_enable", "code_auto_upload_disable"];
20123
20153
 
20154
+ // ../protocol/dist/src/github-sync.js
20155
+ var GitHubRepositorySchema = external_exports.string().max(140).regex(/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?\/[A-Za-z0-9_.-]{1,100}$/).refine((value) => {
20156
+ const repository = value.split("/")[1];
20157
+ return repository !== "." && repository !== ".." && !repository.toLowerCase().endsWith(".git");
20158
+ }, "Use owner/repository without a .git suffix");
20159
+ function isGitHubBranchAllowed(value) {
20160
+ return value.length > 0 && value.length <= 200 && /^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(value) && !value.includes("..") && value.split("/").every((part) => !!part && !part.startsWith(".") && !part.endsWith(".") && !part.toLowerCase().endsWith(".lock")) && value !== "HEAD";
20161
+ }
20162
+ var GitHubBranchSchema = external_exports.string().refine(isGitHubBranchAllowed, "Unsafe GitHub branch name");
20163
+ var GitHubBaseBranchSchema = GitHubBranchSchema.refine((value) => !value.startsWith("gatherthread/"), "The shared base cannot use the GatherThread personal branch namespace");
20164
+ var GitHubPersonalBranchSchema = external_exports.string().regex(/^gatherthread\/[a-f0-9]{24}\/[a-f0-9]{24}$/);
20165
+ var GitHubConnectionSchema = external_exports.object({
20166
+ repository: GitHubRepositorySchema,
20167
+ base_branch: GitHubBaseBranchSchema,
20168
+ enabled: external_exports.boolean(),
20169
+ revision: external_exports.string().uuid()
20170
+ }).strict();
20171
+ var GitHubProjectStatusSchema = external_exports.object({
20172
+ connection: GitHubConnectionSchema.nullable(),
20173
+ branch: GitHubPersonalBranchSchema,
20174
+ can_configure: external_exports.boolean(),
20175
+ // GatherThread membership only. GitHub permissions must be checked locally.
20176
+ can_write: external_exports.boolean()
20177
+ }).strict();
20178
+ var GitHubConnectionInputSchema = external_exports.object({
20179
+ repository: GitHubRepositorySchema,
20180
+ base_branch: GitHubBaseBranchSchema,
20181
+ enabled: external_exports.boolean(),
20182
+ expected_revision: external_exports.string().uuid().nullable()
20183
+ }).strict();
20184
+ var githubCodeSyncRequestKinds = [
20185
+ "github_auth_connect",
20186
+ "github_code_sync_status",
20187
+ "github_code_upload",
20188
+ "github_code_download",
20189
+ "github_code_recover",
20190
+ "github_code_auto_upload_enable",
20191
+ "github_code_auto_upload_disable",
20192
+ "github_code_update"
20193
+ ];
20194
+
20195
+ // ../protocol/dist/src/registration.js
20196
+ var RegistrationEmailSchema = external_exports.string().max(254).trim().toLowerCase().regex(/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/).refine((value) => value.split("@")[0].length <= 64 && value.split("@")[1].split(".").every((part) => part.length <= 63));
20197
+ var Label = external_exports.string().regex(/^[^\u0000-\u001f\u007f-\u009f]*$/u).trim().min(1).max(120);
20198
+ var SendRegistrationInputSchema = external_exports.object({
20199
+ email: RegistrationEmailSchema,
20200
+ challenge_token: external_exports.string().min(1).max(2048),
20201
+ idempotency_key: external_exports.string().uuid(),
20202
+ locale: external_exports.enum(["en", "zh-CN"])
20203
+ }).strict();
20204
+ var AccountPasswordSchema = external_exports.string().min(8).max(128).refine((value) => new TextEncoder().encode(value).byteLength <= 512);
20205
+ var EmailLoginInputSchema = external_exports.object({
20206
+ email: RegistrationEmailSchema,
20207
+ password: AccountPasswordSchema,
20208
+ device_name: Label,
20209
+ remember_device: external_exports.boolean().default(false)
20210
+ }).strict();
20211
+ var LauncherProjectId = external_exports.string().min(1).max(128).refine((value) => /^[A-Za-z0-9]/u.test(value) && !/[^A-Za-z0-9._:-]/u.test(value));
20212
+ var CreateCodexLauncherAuthorizationInputSchema = external_exports.object({
20213
+ project_id: LauncherProjectId,
20214
+ email: RegistrationEmailSchema
20215
+ }).strict();
20216
+ var ClaimCodexLauncherAuthorizationInputSchema = external_exports.object({
20217
+ authorization_id: external_exports.string().uuid().toLowerCase(),
20218
+ project_id: LauncherProjectId,
20219
+ email: RegistrationEmailSchema,
20220
+ password: AccountPasswordSchema,
20221
+ device_name: Label
20222
+ }).strict();
20223
+ var VerifyRegistrationInputSchema = external_exports.object({
20224
+ registration_id: external_exports.string().uuid(),
20225
+ code: external_exports.string().regex(/^\d{8}$/),
20226
+ display_name: Label,
20227
+ device_name: Label,
20228
+ remember_device: external_exports.boolean().default(false),
20229
+ privacy_acknowledged: external_exports.literal(true),
20230
+ password: AccountPasswordSchema
20231
+ }).strict();
20232
+ var RegistrationStatusSchema = external_exports.object({
20233
+ enabled: external_exports.boolean(),
20234
+ site_key: external_exports.string().nullable(),
20235
+ challenge_binding: external_exports.string().nullable()
20236
+ }).strict();
20237
+ var RegistrationSentSchema = external_exports.object({
20238
+ registration_id: external_exports.string().uuid(),
20239
+ expires_in_seconds: external_exports.literal(600),
20240
+ resend_after_seconds: external_exports.literal(60)
20241
+ }).strict();
20242
+ var PasswordResetSentSchema = external_exports.object({
20243
+ reset_id: external_exports.string().uuid(),
20244
+ expires_in_seconds: external_exports.literal(600),
20245
+ resend_after_seconds: external_exports.literal(60)
20246
+ }).strict();
20247
+ var VerifyPasswordResetInputSchema = external_exports.object({
20248
+ reset_id: external_exports.string().uuid(),
20249
+ email: RegistrationEmailSchema,
20250
+ code: external_exports.string().regex(/^\d{8}$/),
20251
+ password: AccountPasswordSchema,
20252
+ password_confirmation: AccountPasswordSchema,
20253
+ locale: external_exports.enum(["en", "zh-CN"])
20254
+ }).strict().refine((value) => value.password === value.password_confirmation);
20255
+ var EmailAccountSessionSchema = external_exports.object({
20256
+ actor: external_exports.object({ user_id: external_exports.string(), display_name: external_exports.string(), device_id: external_exports.string(), can_create_projects: external_exports.literal(true) }).strict(),
20257
+ expires_at: external_exports.string().datetime()
20258
+ }).strict();
20259
+
20260
+ // ../protocol/dist/src/cloud-api.js
20261
+ var CloudApiProviderIdSchema = external_exports.enum(["openai", "anthropic", "deepseek", "siliconflow-cn", "siliconflow-global", "openrouter", "qwen", "glm", "doubao"]);
20262
+ var CloudApiModelSchema = external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u0020\u007f-\u009f]+$/u);
20263
+ var Label2 = external_exports.string().trim().min(1).max(80).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u);
20264
+ var CloudApiPutInputSchema = external_exports.object({
20265
+ expected_revision: external_exports.string().uuid().nullable(),
20266
+ provider_id: CloudApiProviderIdSchema,
20267
+ label: Label2,
20268
+ model: CloudApiModelSchema,
20269
+ enabled: external_exports.boolean(),
20270
+ api_key: external_exports.string().min(8).max(4096).regex(/^[\x21-\x7e]+$/u).optional()
20271
+ }).strict();
20272
+ var CloudApiDeleteInputSchema = external_exports.object({ expected_revision: external_exports.string().uuid() }).strict();
20273
+ var CloudApiConfigurationSchema = external_exports.object({
20274
+ id: external_exports.string().uuid(),
20275
+ revision: external_exports.string().uuid(),
20276
+ provider_id: CloudApiProviderIdSchema,
20277
+ profile_id: external_exports.string().regex(/^api-[0-9a-f-]{36}$/u),
20278
+ label: Label2,
20279
+ model: CloudApiModelSchema,
20280
+ enabled: external_exports.boolean(),
20281
+ has_key: external_exports.literal(true),
20282
+ updated_at: external_exports.string().datetime()
20283
+ }).strict();
20284
+ var CloudApiProviderSchema = external_exports.object({
20285
+ id: CloudApiProviderIdSchema,
20286
+ label: external_exports.string().max(80),
20287
+ transport: external_exports.enum(["openai-chat", "anthropic-messages"]),
20288
+ base_url: external_exports.string().url().max(200),
20289
+ docs_url: external_exports.string().url().max(300),
20290
+ default_model: CloudApiModelSchema.optional()
20291
+ }).strict();
20292
+ var CloudApiStatusSchema = external_exports.object({
20293
+ enabled: external_exports.boolean(),
20294
+ providers: external_exports.array(CloudApiProviderSchema).max(16),
20295
+ configurations: external_exports.array(CloudApiConfigurationSchema).max(8)
20296
+ }).strict();
20297
+ var CloudApiSavedSchema = external_exports.object({ configuration: CloudApiConfigurationSchema }).strict();
20298
+ var PersonalCloudRevisionSchema = external_exports.string().uuid().optional();
20299
+ function hasValidPersonalCloudRevision(value) {
20300
+ return value.profile_id.startsWith("api-") ? /^api-[0-9a-f-]{36}$/u.test(value.profile_id) && value.api_config_revision !== void 0 : value.api_config_revision === void 0;
20301
+ }
20302
+ var HostedAgentSelectionSchema = external_exports.object({
20303
+ profile_id: external_exports.string().min(1).max(64),
20304
+ api_config_revision: PersonalCloudRevisionSchema
20305
+ }).strict().refine(hasValidPersonalCloudRevision, "Personal Cloud Agent selection requires its exact revision");
20306
+
20124
20307
  // ../protocol/dist/src/history-summary.js
20125
20308
  var HISTORY_SUMMARY_MAX_SOURCE_BYTES = 20 * 1024;
20126
20309
  var HISTORY_SUMMARY_MAX_PROMPT_BYTES = 30 * 1024;
@@ -20136,7 +20319,7 @@ function record2(value) {
20136
20319
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
20137
20320
  }
20138
20321
  function historySummaryMarker(event) {
20139
- if (event.type !== "agent_request")
20322
+ if (event.deleted || event.type !== "agent_request")
20140
20323
  return void 0;
20141
20324
  const marker = record2(record2(event.payload)?.history_summary);
20142
20325
  const ids = marker?.source_event_ids;
@@ -20145,6 +20328,105 @@ function historySummaryMarker(event) {
20145
20328
  return { version: 1, source_event_ids: ids, source_digest: marker.source_digest };
20146
20329
  }
20147
20330
 
20331
+ // ../protocol/dist/src/test-gate.js
20332
+ var TestGateExchangeInputSchema = external_exports.object({
20333
+ admission_code: external_exports.string().regex(/^gte_[A-Za-z0-9_-]{43}$/)
20334
+ }).strict();
20335
+ var TestGateStatusSchema = external_exports.object({
20336
+ enabled: external_exports.boolean(),
20337
+ admitted: external_exports.boolean(),
20338
+ environment: external_exports.enum(["production", "test"])
20339
+ }).strict();
20340
+
20341
+ // ../protocol/dist/src/hosted-github.js
20342
+ var Key2 = external_exports.string().min(8).max(200);
20343
+ var HostedGithubRepositoryInputSchema = external_exports.object({
20344
+ repository: external_exports.string().regex(/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/u).max(140),
20345
+ base_branch: external_exports.string().min(1).max(200).refine((v) => !/[\s~^:?*\[\\]/u.test(v) && !v.includes("..") && !v.startsWith("-") && !v.endsWith("/") && !v.endsWith(".lock"))
20346
+ }).strict();
20347
+ var HostedGithubTaskInputSchema = external_exports.object({
20348
+ content: external_exports.string().trim().min(1).max(6e3),
20349
+ profile_id: external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/u),
20350
+ idempotency_key: Key2,
20351
+ continue_task_id: external_exports.string().regex(/^gh-task-[a-f0-9]{32}$/u).optional(),
20352
+ reply_to_event_id: external_exports.string().min(1).max(128).nullable().optional(),
20353
+ api_config_revision: PersonalCloudRevisionSchema,
20354
+ content_revision: external_exports.number().int().nonnegative().optional()
20355
+ }).strict().refine(hasValidPersonalCloudRevision, { message: "Personal cloud profiles require their exact configuration revision" });
20356
+ var HostedGithubCompleteInputSchema = external_exports.object({
20357
+ state: external_exports.string().regex(/^[A-Za-z0-9_-]{43}$/u),
20358
+ code: external_exports.string().min(1).max(500)
20359
+ }).strict();
20360
+ var HostedGithubPrInputSchema = external_exports.object({
20361
+ title: external_exports.string().trim().min(1).max(200),
20362
+ body: external_exports.string().max(6e3),
20363
+ expected_revision: external_exports.string().regex(/^[a-f0-9]{64}$/u)
20364
+ }).strict();
20365
+ var Login = external_exports.string().regex(/^[A-Za-z0-9-]{1,39}$/u);
20366
+ var TaskId = external_exports.string().regex(/^gh-task-[a-f0-9]{32}$/u);
20367
+ var Sha = external_exports.string().regex(/^[a-f0-9]{40}$/u).nullable();
20368
+ var Revision = external_exports.string().regex(/^[a-f0-9]{64}$/u).nullable();
20369
+ var PullUrl = external_exports.string().max(2048).regex(/^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/pull\/[1-9][0-9]*$/u).nullable();
20370
+ var HostedGithubBindingSchema = HostedGithubRepositoryInputSchema;
20371
+ var HostedGithubStatusSchema = external_exports.union([
20372
+ external_exports.object({ enabled: external_exports.literal(false) }).strict(),
20373
+ external_exports.object({
20374
+ enabled: external_exports.literal(true),
20375
+ connected: external_exports.boolean(),
20376
+ login: Login.nullable(),
20377
+ binding: HostedGithubBindingSchema.nullable(),
20378
+ installation_url: external_exports.string().max(2048).regex(/^https:\/\/github\.com\/apps\/[A-Za-z0-9_.-]+\/installations\/new$/u)
20379
+ }).strict().refine((v) => v.connected ? v.login !== null : v.login === null && v.binding === null)
20380
+ ]);
20381
+ var HostedGithubAuthorizationSchema = external_exports.object({ authorization_url: external_exports.string().max(4096).refine((value) => {
20382
+ try {
20383
+ const url2 = new URL(value);
20384
+ return url2.origin === "https://github.com" && url2.pathname === "/login/oauth/authorize" && !url2.username && !url2.password && !url2.hash && /^[A-Za-z0-9_-]{43}$/u.test(url2.searchParams.get("state") ?? "") && [...url2.searchParams.keys()].every((key) => ["client_id", "redirect_uri", "state", "code_challenge", "code_challenge_method", "prompt"].includes(key));
20385
+ } catch {
20386
+ return false;
20387
+ }
20388
+ }) }).strict();
20389
+ var HostedGithubConnectionSchema = external_exports.object({ connected: external_exports.literal(true), login: Login }).strict();
20390
+ var HostedGithubDisconnectionSchema = external_exports.object({ connected: external_exports.literal(false) }).strict();
20391
+ var HostedGithubTaskSummarySchema = external_exports.object({
20392
+ id: TaskId,
20393
+ session_id: external_exports.string().min(1).max(128),
20394
+ profile_id: HostedGithubTaskInputSchema.shape.profile_id,
20395
+ resumable: external_exports.boolean(),
20396
+ state: external_exports.enum(["running", "completed", "failed", "interrupted"]),
20397
+ repository: HostedGithubRepositoryInputSchema.shape.repository,
20398
+ base_branch: HostedGithubRepositoryInputSchema.shape.base_branch,
20399
+ base_sha: Sha,
20400
+ revision: Revision,
20401
+ error_code: external_exports.string().regex(/^[a-z][a-z0-9_]{0,63}$/u).nullable(),
20402
+ pull_request_url: PullUrl,
20403
+ expires_at: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER),
20404
+ api_config_revision: external_exports.string().uuid().optional()
20405
+ }).strict();
20406
+ var bytes = (value) => value.length / 4 * 3 - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
20407
+ var Source = external_exports.string().max(2796204).regex(/^[A-Za-z0-9+/]*={0,2}$/u).refine((value) => value.length % 4 === 0 && bytes(value) <= 2 * 1024 * 1024).nullable();
20408
+ var HostedGithubChangeSchema = external_exports.object({
20409
+ path: external_exports.string().max(4096).refine(isCodeSyncPathAllowed),
20410
+ before_base64: Source,
20411
+ after_base64: Source,
20412
+ before_executable: external_exports.boolean().nullable(),
20413
+ after_executable: external_exports.boolean().nullable()
20414
+ }).strict().refine((v) => v.before_base64 === null === (v.before_executable === null) && v.after_base64 === null === (v.after_executable === null) && (v.before_base64 !== null || v.after_base64 !== null));
20415
+ var HostedGithubTaskSchema = HostedGithubTaskSummarySchema.extend({
20416
+ answer: external_exports.string().max(14e3).nullable(),
20417
+ changes: external_exports.array(HostedGithubChangeSchema).max(2e3)
20418
+ }).strict().refine((v) => {
20419
+ if (new Set(v.changes.map((c) => c.path)).size !== v.changes.length)
20420
+ return false;
20421
+ for (const side of ["before_base64", "after_base64"]) {
20422
+ const values = v.changes.map((c) => c[side]).filter((s) => s !== null);
20423
+ if (values.length > 1e3 || values.reduce((sum, s) => sum + bytes(s), 0) > 8 * 1024 * 1024)
20424
+ return false;
20425
+ }
20426
+ return !v.resumable || v.state !== "running" && v.pull_request_url === null;
20427
+ });
20428
+ var HostedGithubTaskListSchema = external_exports.object({ tasks: external_exports.array(HostedGithubTaskSummarySchema).max(10) }).strict();
20429
+
20148
20430
  // ../protocol/dist/src/index.js
20149
20431
  var sessionModes = ["solo", "multi"];
20150
20432
  var membershipRoles = ["owner", "participant", "viewer"];
@@ -20159,7 +20441,8 @@ var eventTypes = [
20159
20441
  "attachment",
20160
20442
  "context_snapshot",
20161
20443
  "membership_change",
20162
- "session_state_change"
20444
+ "session_state_change",
20445
+ "message_deleted"
20163
20446
  ];
20164
20447
  var eventVisibilities = ["session", "owner_only"];
20165
20448
  var captureFidelities = [
@@ -20256,8 +20539,18 @@ var CanonicalEventSchema = external_exports.object({
20256
20539
  visibility: EventVisibilitySchema,
20257
20540
  reply_to_event_id: IdSchema.nullable(),
20258
20541
  payload: JsonValueSchema,
20259
- runtime_provenance: RuntimeProvenanceSchema.nullable()
20542
+ runtime_provenance: RuntimeProvenanceSchema.nullable(),
20543
+ content_revision: external_exports.number().int().nonnegative().optional(),
20544
+ deleted: external_exports.object({ deleted_at: external_exports.string().datetime(), reason: external_exports.enum(["author", "request", "summary_invalidated"]) }).strict().optional()
20260
20545
  });
20546
+ var DeleteMessageInputSchema = external_exports.object({ idempotency_key: IdempotencyKeySchema }).strict();
20547
+ var DeleteMessageResultSchema = external_exports.object({
20548
+ event: CanonicalEventSchema,
20549
+ target_event_id: IdSchema,
20550
+ content_revision: external_exports.number().int().nonnegative(),
20551
+ affected_event_ids: external_exports.array(IdSchema).max(256),
20552
+ affected_truncated: external_exports.boolean()
20553
+ }).strict();
20261
20554
  var MessageMentionsSchema = external_exports.array(external_exports.object({
20262
20555
  user_id: IdSchema,
20263
20556
  start: external_exports.number().int().nonnegative().max(1e6),
@@ -20286,9 +20579,70 @@ var AppendEventInputSchema = external_exports.object({
20286
20579
  payload: JsonValueSchema,
20287
20580
  runtime_id: IdSchema.optional(),
20288
20581
  claim_attempt: external_exports.number().int().positive().optional(),
20582
+ content_revision: external_exports.number().int().nonnegative().optional(),
20289
20583
  observed_model: external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
20290
20584
  observed_reasoning_effort: external_exports.string().trim().min(1).max(80).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional()
20291
20585
  });
20586
+ var HostedAgentRequestInputSchema = external_exports.object({
20587
+ profile_id: external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/u).default("default"),
20588
+ content: external_exports.string().trim().min(1).max(6e3),
20589
+ include_code: external_exports.boolean().default(false),
20590
+ idempotency_key: IdempotencyKeySchema,
20591
+ reply_to_event_id: IdSchema.nullable().optional(),
20592
+ github_task_id: external_exports.string().regex(/^gh-task-[a-f0-9]{32}$/u).optional(),
20593
+ continue_from_event_id: IdSchema.optional(),
20594
+ api_config_revision: PersonalCloudRevisionSchema,
20595
+ content_revision: external_exports.number().int().nonnegative().optional()
20596
+ }).strict().refine(hasValidPersonalCloudRevision, { message: "Personal cloud profiles require their exact configuration revision" });
20597
+ var HostedAgentFailurePayloadSchema = external_exports.object({
20598
+ content: external_exports.string().min(1).max(512),
20599
+ status: external_exports.literal("failed"),
20600
+ outcome: external_exports.enum(["timed_out", "failed"]),
20601
+ error: external_exports.object({
20602
+ code: external_exports.string().regex(/^[a-z][a-z0-9_]{0,63}$/u),
20603
+ provider_attempts: external_exports.number().int().min(0).max(64).optional()
20604
+ }).strict()
20605
+ }).strict();
20606
+ var HostedHistorySummaryInputSchema = CreateHistorySummaryInputSchema.omit({ execution_profile: true }).extend({ profile_id: HostedAgentRequestInputSchema.shape.profile_id.unwrap(), api_config_revision: PersonalCloudRevisionSchema, continue_from_event_id: IdSchema.optional() }).strict().refine(hasValidPersonalCloudRevision, { message: "Personal cloud profiles require their exact configuration revision" });
20607
+ var HostedAgentAcceptedSchema = external_exports.object({
20608
+ request_event: CanonicalEventSchema,
20609
+ replayed: external_exports.boolean()
20610
+ }).strict();
20611
+ var HostedAgentPausedSchema = external_exports.object({
20612
+ request_event_id: IdSchema,
20613
+ status: external_exports.literal("paused")
20614
+ }).strict();
20615
+ var HostedAgentStatusSchema = external_exports.discriminatedUnion("enabled", [
20616
+ external_exports.object({ enabled: external_exports.literal(false) }).strict(),
20617
+ external_exports.object({
20618
+ enabled: external_exports.literal(true),
20619
+ harness: external_exports.literal("opencode"),
20620
+ utc_day: external_exports.string(),
20621
+ user_limit_runs: external_exports.number().int().nonnegative().nullable(),
20622
+ user_used_runs: external_exports.number().int().nonnegative(),
20623
+ global_limit_runs: external_exports.number().int().nonnegative().nullable(),
20624
+ global_used_runs: external_exports.number().int().nonnegative(),
20625
+ rate_limits: external_exports.object({
20626
+ user_min_interval_seconds: external_exports.number().int().min(1).max(3600),
20627
+ user_max_concurrent: external_exports.number().int().min(1).max(8),
20628
+ user_active_runs: external_exports.number().int().nonnegative(),
20629
+ retry_after_seconds: external_exports.number().int().nonnegative()
20630
+ }).strict().optional(),
20631
+ profiles: external_exports.array(external_exports.object({
20632
+ id: external_exports.string(),
20633
+ label: external_exports.string(),
20634
+ provider: external_exports.string(),
20635
+ model: external_exports.string(),
20636
+ available: external_exports.boolean(),
20637
+ capacity: external_exports.number().int().nonnegative(),
20638
+ status: external_exports.enum(["available", "busy", "daily_limit", "cooldown", "user_busy", "rate_limit"]),
20639
+ source: external_exports.enum(["service", "personal"]).optional(),
20640
+ api_config_revision: external_exports.string().uuid().optional()
20641
+ }).strict()),
20642
+ capabilities: external_exports.array(external_exports.string()),
20643
+ privacy: external_exports.string()
20644
+ }).strict()
20645
+ ]);
20292
20646
  var SingleLineTitleSchema = external_exports.string().regex(/^[^\u0000-\u001f\u007f-\u009f]*$/u, "Title must not contain control characters").trim().min(1).max(200);
20293
20647
  var SessionTitleSchema = SingleLineTitleSchema;
20294
20648
  var ProjectTitleSchema = SingleLineTitleSchema;
@@ -20335,7 +20689,12 @@ var ProjectListItemSchema = ProjectRecordSchema.omit({ owner_user_id: true }).ex
20335
20689
  role: MembershipRoleSchema,
20336
20690
  session_count: external_exports.number().int().nonnegative()
20337
20691
  });
20692
+ var AvatarIdSchema = external_exports.enum(["cat", "fox", "bear", "rabbit", "penguin", "owl"]);
20693
+ var SetAccountAvatarInputSchema = external_exports.object({ avatar_id: AvatarIdSchema.nullable() }).strict();
20694
+ var AccountAvatarProfileSchema = external_exports.object({ user_id: IdSchema, avatar_id: AvatarIdSchema.nullable() });
20695
+ var SessionAvatarProfilesSchema = external_exports.object({ profiles: external_exports.array(AccountAvatarProfileSchema) });
20338
20696
  var ProjectMemberRecordSchema = external_exports.object({
20697
+ avatar_id: AvatarIdSchema.nullable().optional(),
20339
20698
  user_id: IdSchema,
20340
20699
  display_name: external_exports.string().trim().min(1).max(120),
20341
20700
  role: MembershipRoleSchema
@@ -20390,6 +20749,17 @@ var ClaimInvitationInputSchema = external_exports.object({
20390
20749
  var AcceptInvitationInputSchema = external_exports.object({
20391
20750
  invite_token: external_exports.string().min(32).max(512)
20392
20751
  });
20752
+ var PreviewProjectInvitationInputSchema = external_exports.object({
20753
+ invite_token: external_exports.string().regex(/^gti_[A-Za-z0-9_-]{32,508}$/)
20754
+ }).strict();
20755
+ var ProjectInvitationPreviewSchema = external_exports.object({
20756
+ project: external_exports.object({ id: IdSchema, title: external_exports.string().min(1).max(200) }).strict(),
20757
+ inviter_display_name: external_exports.string().min(1).max(120),
20758
+ role: InvitationRoleSchema,
20759
+ created_at: external_exports.string().datetime(),
20760
+ expires_at: external_exports.string().datetime(),
20761
+ already_member: external_exports.boolean()
20762
+ }).strict();
20393
20763
  var InvitationRecordSchema = external_exports.object({
20394
20764
  id: IdSchema,
20395
20765
  session_id: IdSchema,
@@ -20464,6 +20834,10 @@ var DeviceAuthorizationRecordSchema = external_exports.object({
20464
20834
  claimed_at: external_exports.string().datetime().nullable(),
20465
20835
  claimed_by_device_id: IdSchema.nullable()
20466
20836
  });
20837
+ var CodexLauncherAuthorizationSchema = external_exports.object({
20838
+ authorization: DeviceAuthorizationRecordSchema.strict(),
20839
+ email: RegistrationEmailSchema
20840
+ }).strict();
20467
20841
  var RotateDeviceTokenInputSchema = external_exports.object({
20468
20842
  expires_at: external_exports.string().datetime().nullable().optional()
20469
20843
  });
@@ -20498,6 +20872,7 @@ var RegisterRuntimeInputSchema = external_exports.object({
20498
20872
  provider: external_exports.string().trim().min(1).max(80),
20499
20873
  model: external_exports.string().trim().min(1).max(160),
20500
20874
  execution_profiles: RuntimeExecutionProfilesSchema.optional(),
20875
+ context_deletion_version: external_exports.literal(1).optional(),
20501
20876
  local_session_id: external_exports.string().trim().min(1).max(512),
20502
20877
  capture_fidelity: CaptureFidelitySchema
20503
20878
  });
@@ -20511,11 +20886,13 @@ var AgentRequestClaimSchema = external_exports.object({
20511
20886
  // `paused` is a decision by the requester, not a claim a runtime can execute.
20512
20887
  // It is reported so a connector can skip the request without advancing past it.
20513
20888
  status: external_exports.enum(["claimed", "completed", "paused"]),
20514
- attempt_count: external_exports.number().int().positive().optional()
20889
+ attempt_count: external_exports.number().int().positive().optional(),
20890
+ content_revision: external_exports.number().int().nonnegative().optional()
20515
20891
  }).strict();
20516
20892
  var CompleteAgentRequestInputSchema = external_exports.object({
20517
20893
  runtime_id: IdSchema,
20518
20894
  claim_attempt: external_exports.number().int().positive().optional(),
20895
+ content_revision: external_exports.number().int().nonnegative().optional(),
20519
20896
  idempotency_key: IdempotencyKeySchema,
20520
20897
  payload: JsonValueSchema,
20521
20898
  observed_model: external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
@@ -20530,6 +20907,7 @@ var CommitLocalTurnInputSchema = external_exports.object({
20530
20907
  local_turn_id: IdSchema,
20531
20908
  runtime_id: IdSchema,
20532
20909
  based_on_sequence: external_exports.number().int().nonnegative(),
20910
+ content_revision: external_exports.number().int().nonnegative().optional(),
20533
20911
  occurred_at: external_exports.string().datetime(),
20534
20912
  observed_model: external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
20535
20913
  observed_reasoning_effort: external_exports.string().trim().min(1).max(80).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
@@ -20550,6 +20928,7 @@ var snapshotRequestStatuses = ["pending", "claimed", "completed", "failed"];
20550
20928
  var SnapshotRequestStatusSchema = external_exports.enum(snapshotRequestStatuses);
20551
20929
  var snapshotRequestKinds = [
20552
20930
  ...codeSyncRequestKinds,
20931
+ ...githubCodeSyncRequestKinds,
20553
20932
  "immutable",
20554
20933
  "visible_history_replace",
20555
20934
  "local_sync_status",
@@ -20582,6 +20961,7 @@ var SnapshotRequestRecordSchema = external_exports.object({
20582
20961
  kind: SnapshotRequestKindSchema,
20583
20962
  through_sequence: external_exports.number().int().nonnegative(),
20584
20963
  status: SnapshotRequestStatusSchema,
20964
+ content_revision: external_exports.number().int().nonnegative().optional(),
20585
20965
  target_runtime_id: IdSchema.nullable(),
20586
20966
  claimed_by_runtime_id: IdSchema.nullable(),
20587
20967
  created_at: external_exports.string().datetime(),
@@ -20607,7 +20987,8 @@ var SubscribeMessageSchema = external_exports.object({
20607
20987
  var ReplayResponseSchema = external_exports.object({
20608
20988
  events: external_exports.array(CanonicalEventSchema),
20609
20989
  cursor: external_exports.number().int().nonnegative(),
20610
- has_more: external_exports.boolean()
20990
+ has_more: external_exports.boolean(),
20991
+ content_revision: external_exports.number().int().nonnegative().optional()
20611
20992
  });
20612
20993
  var SessionListItemSchema = external_exports.object({
20613
20994
  id: IdSchema,
@@ -20618,6 +20999,7 @@ var SessionListItemSchema = external_exports.object({
20618
20999
  state: external_exports.enum(["active", "archived"]),
20619
21000
  role: MembershipRoleSchema,
20620
21001
  current_sequence: external_exports.number().int().nonnegative(),
21002
+ content_revision: external_exports.number().int().nonnegative().optional(),
20621
21003
  member_count: external_exports.number().int().nonnegative().optional(),
20622
21004
  updated_at: external_exports.string().datetime()
20623
21005
  });
@@ -20721,7 +21103,8 @@ var HttpCollaborationClient = class {
20721
21103
  return {
20722
21104
  events,
20723
21105
  nextSequence: requiredNumber(body.cursor, "cursor"),
20724
- hasMore: body.has_more === true
21106
+ hasMore: body.has_more === true,
21107
+ ...body.content_revision === void 0 ? {} : { contentRevision: requiredRevision(body.content_revision, "events.content_revision") }
20725
21108
  };
20726
21109
  }
20727
21110
  async readContext(sessionId, view, throughSequence) {
@@ -20779,7 +21162,8 @@ var HttpCollaborationClient = class {
20779
21162
  status,
20780
21163
  requestId: requiredString2(body.request_event_id, "claim.request_event_id"),
20781
21164
  runtimeId: requiredString2(body.runtime_id, "claim.runtime_id"),
20782
- attemptCount
21165
+ attemptCount,
21166
+ ...body.content_revision === void 0 ? {} : { contentRevision: requiredRevision(body.content_revision, "claim.content_revision") }
20783
21167
  };
20784
21168
  }
20785
21169
  async completeAgentRequest(sessionId, requestId, input2) {
@@ -20788,6 +21172,7 @@ var HttpCollaborationClient = class {
20788
21172
  body: JSON.stringify({
20789
21173
  runtime_id: input2.runtimeId,
20790
21174
  ...input2.claimAttempt === void 0 ? {} : { claim_attempt: input2.claimAttempt },
21175
+ ...input2.contentRevision === void 0 ? {} : { content_revision: input2.contentRevision },
20791
21176
  idempotency_key: input2.idempotencyKey,
20792
21177
  payload: truncateJsonValue(input2.payload, 160 * 1024),
20793
21178
  ...input2.observedModel === void 0 ? {} : { observed_model: input2.observedModel },
@@ -20802,6 +21187,7 @@ var HttpCollaborationClient = class {
20802
21187
  body: JSON.stringify({
20803
21188
  runtime_id: input2.runtimeId,
20804
21189
  ...input2.claimAttempt === void 0 ? {} : { claim_attempt: input2.claimAttempt },
21190
+ ...input2.contentRevision === void 0 ? {} : { content_revision: input2.contentRevision },
20805
21191
  idempotency_key: input2.idempotencyKey,
20806
21192
  payload: truncateJsonValue(input2.payload, 32 * 1024),
20807
21193
  ...input2.observedModel === void 0 ? {} : { observed_model: input2.observedModel },
@@ -20818,6 +21204,7 @@ var HttpCollaborationClient = class {
20818
21204
  local_turn_id: input2.localTurnId,
20819
21205
  runtime_id: input2.runtimeId,
20820
21206
  based_on_sequence: input2.basedOnSequence,
21207
+ ...input2.contentRevision === void 0 ? {} : { content_revision: input2.contentRevision },
20821
21208
  occurred_at: input2.occurredAt,
20822
21209
  ...input2.observedModel === void 0 ? {} : { observed_model: input2.observedModel },
20823
21210
  ...input2.observedReasoningEffort === void 0 ? {} : { observed_reasoning_effort: input2.observedReasoningEffort },
@@ -20924,6 +21311,7 @@ function toWireEvent(event) {
20924
21311
  visibility: event.visibility ?? "session",
20925
21312
  runtime_id: event.runtimeId ?? event.runtime?.runtimeId,
20926
21313
  claim_attempt: event.claimAttempt,
21314
+ ...event.contentRevision === void 0 ? {} : { content_revision: event.contentRevision },
20927
21315
  observed_model: event.observedModel,
20928
21316
  observed_reasoning_effort: event.observedReasoningEffort
20929
21317
  };
@@ -20949,7 +21337,8 @@ function toWireRuntimeRegistration(runtime) {
20949
21337
  local_session_id: runtime.localSessionId,
20950
21338
  capture_fidelity: runtime.captureFidelity,
20951
21339
  ...runtime.capabilities === void 0 ? {} : { capabilities: [...runtime.capabilities] },
20952
- ...runtime.purpose === void 0 ? {} : { purpose: runtime.purpose }
21340
+ ...runtime.purpose === void 0 ? {} : { purpose: runtime.purpose },
21341
+ ...runtime.contextDeletionVersion === void 0 ? {} : { context_deletion_version: runtime.contextDeletionVersion }
20953
21342
  };
20954
21343
  }
20955
21344
  function validateContextReadInput(sessionId, view, throughSequence) {
@@ -21010,7 +21399,17 @@ function parseHistoryContext(value, expectedView, throughSequence) {
21010
21399
  if (items.some((item) => sourceIds.has(item.event_id))) {
21011
21400
  throw new Error("Collaboration API context repeats summarized sources");
21012
21401
  }
21013
- return { view: value.view, through_sequence: Number(value.through_sequence), items };
21402
+ return {
21403
+ view: value.view,
21404
+ through_sequence: Number(value.through_sequence),
21405
+ items,
21406
+ ...value.content_revision === void 0 ? {} : { content_revision: requiredRevision(value.content_revision, "context.content_revision") }
21407
+ };
21408
+ }
21409
+ function requiredRevision(value, label) {
21410
+ if (!Number.isSafeInteger(value) || Number(value) < 0)
21411
+ throw new Error(`Collaboration API returned invalid ${label}`);
21412
+ return Number(value);
21014
21413
  }
21015
21414
  function isContextId(value) {
21016
21415
  return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value);
@@ -21029,9 +21428,17 @@ function fromWireEvent(value) {
21029
21428
  ...typeof input2.reply_to_event_id === "string" ? { replyTo: input2.reply_to_event_id } : {},
21030
21429
  timestamp: requiredString2(input2.created_at, "event.created_at"),
21031
21430
  payload: input2.payload,
21431
+ ...input2.content_revision === void 0 ? {} : { contentRevision: requiredRevision(input2.content_revision, "event.content_revision") },
21432
+ ...input2.deleted === void 0 ? {} : { deleted: fromWireDeletion(input2.deleted) },
21032
21433
  ...runtime === void 0 ? {} : { runtime }
21033
21434
  };
21034
21435
  }
21436
+ function fromWireDeletion(value) {
21437
+ const input2 = requiredObject2(value);
21438
+ if (input2.reason !== "author" && input2.reason !== "request" && input2.reason !== "summary_invalidated")
21439
+ throw new Error("Collaboration API returned invalid event.deleted reason");
21440
+ return { deletedAt: requiredString2(input2.deleted_at, "event.deleted.deleted_at"), reason: input2.reason };
21441
+ }
21035
21442
  function fromWireSnapshotRequest(value) {
21036
21443
  const input2 = requiredObject2(value);
21037
21444
  const status = requiredString2(input2.status, "snapshot_request.status");
@@ -21067,6 +21474,7 @@ function fromWireSnapshotRequest(value) {
21067
21474
  kind,
21068
21475
  ...typeof input2.target_runtime_id === "string" ? { targetRuntimeId: input2.target_runtime_id } : {},
21069
21476
  throughSequence: requiredNumber(input2.through_sequence, "snapshot_request.through_sequence"),
21477
+ ...input2.content_revision === void 0 ? {} : { contentRevision: requiredRevision(input2.content_revision, "snapshot_request.content_revision") },
21070
21478
  status,
21071
21479
  ...createdAt === void 0 ? {} : { createdAt },
21072
21480
  ..."result" in input2 ? { result: input2.result } : {},
@@ -21086,7 +21494,8 @@ function fromWireSession(value) {
21086
21494
  ...input2.state === "active" || input2.state === "archived" ? { state: input2.state } : {},
21087
21495
  ...name2 === void 0 ? {} : { name: name2 },
21088
21496
  ...role === void 0 ? {} : { role },
21089
- ...latestSequence === void 0 ? {} : { latestSequence }
21497
+ ...latestSequence === void 0 ? {} : { latestSequence },
21498
+ ...input2.content_revision === void 0 ? {} : { contentRevision: requiredRevision(input2.content_revision, "session.content_revision") }
21090
21499
  };
21091
21500
  }
21092
21501
  function fromWireProject(value) {
@@ -21133,7 +21542,8 @@ function fromWireRuntime(value) {
21133
21542
  ...input2.execution_profiles === void 0 || input2.execution_profiles === null ? {} : { executionProfiles: fromWireExecutionProfiles(input2.execution_profiles) },
21134
21543
  localSessionId: requiredString2(input2.local_session_id, "runtime.local_session_id"),
21135
21544
  captureFidelity: requiredString2(input2.capture_fidelity, "runtime.capture_fidelity"),
21136
- purpose
21545
+ purpose,
21546
+ ...input2.context_deletion_version === 1 ? { contextDeletionVersion: 1 } : {}
21137
21547
  };
21138
21548
  }
21139
21549
  function fromWireExecutionProfiles(value) {
@@ -21264,8 +21674,8 @@ function isObject2(value) {
21264
21674
 
21265
21675
  // ../adapters/dist/src/redaction.js
21266
21676
  var REDACTED = "[REDACTED]";
21677
+ var PRIVATE_KEY_PATTERN = /-----BEGIN (?:ENCRYPTED |RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\s\S]*?(?:-----END (?:ENCRYPTED |RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----|$)/g;
21267
21678
  var DEFAULT_SECRET_PATTERNS = [
21268
- /-----BEGIN (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----/g,
21269
21679
  /\bAKIA[0-9A-Z]{16}\b/g,
21270
21680
  /\b(?:ghp|github_pat|glpat|sk|xox[baprs])[-_][A-Za-z0-9_-]{16,}\b/g,
21271
21681
  /\bBearer\s+[A-Za-z0-9._~+/=-]{8,}\b/gi,
@@ -21278,6 +21688,8 @@ var SENSITIVE_KEY_NAMES = /* @__PURE__ */ new Set([
21278
21688
  "accesstoken",
21279
21689
  "authtoken",
21280
21690
  "authorization",
21691
+ "cookie",
21692
+ "setcookie",
21281
21693
  "bearer",
21282
21694
  "clientsecret",
21283
21695
  "password",
@@ -21294,7 +21706,83 @@ var SENSITIVE_KEY_NAMES = /* @__PURE__ */ new Set([
21294
21706
  ]);
21295
21707
  function redactText(value, options = {}) {
21296
21708
  const replacement = options.replacement ?? REDACTED;
21297
- return [...DEFAULT_SECRET_PATTERNS, ...options.extraPatterns ?? []].reduce((redacted, pattern) => redacted.replace(cloneGlobal(pattern), (match, prefix) => typeof prefix === "string" && prefix.length < match.length ? `${prefix}${replacement}` : replacement), value);
21709
+ return [...DEFAULT_SECRET_PATTERNS, ...options.extraPatterns ?? []].reduce(
21710
+ (redacted, pattern) => redacted.replace(cloneGlobal(pattern), (match, prefix) => typeof prefix === "string" && prefix.length < match.length ? `${prefix}${replacement}` : replacement),
21711
+ // Mask PEM first: scanning `private_key: -----BEGIN ...` as an ordinary
21712
+ // assignment must not break its header and leave the following body public.
21713
+ redactSensitiveFields(value.replace(cloneGlobal(PRIVATE_KEY_PATTERN), () => replacement), replacement)
21714
+ );
21715
+ }
21716
+ function redactSensitiveFields(text, replacement) {
21717
+ const fields = /("(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'|\b[A-Za-z_][A-Za-z0-9_.-]*)(\s*[:=]\s*)/gu;
21718
+ const parts = [];
21719
+ let retainedFrom = 0;
21720
+ let match;
21721
+ while ((match = fields.exec(text)) !== null) {
21722
+ const encodedKey = match[1];
21723
+ let key = encodedKey;
21724
+ if (encodedKey.startsWith('"')) {
21725
+ try {
21726
+ key = JSON.parse(encodedKey);
21727
+ } catch {
21728
+ continue;
21729
+ }
21730
+ } else if (encodedKey.startsWith("'"))
21731
+ key = encodedKey.slice(1, -1);
21732
+ if (!isSensitiveKey(key))
21733
+ continue;
21734
+ const start = fields.lastIndex;
21735
+ const end = sensitiveValueEnd(text, start, encodedKey[0] !== '"' && encodedKey[0] !== "'" && /^(?:authorization|cookie|set-cookie)$/iu.test(key));
21736
+ const quote = text[start];
21737
+ const masked = quote === "'" ? `'${replacement.replace(/\\/gu, "\\\\").replace(/'/gu, "\\'")}'` : quote === '"' || encodedKey.startsWith('"') ? JSON.stringify(replacement) : replacement;
21738
+ parts.push(text.slice(retainedFrom, start), masked);
21739
+ retainedFrom = end;
21740
+ fields.lastIndex = end;
21741
+ }
21742
+ return parts.length === 0 ? text : parts.join("") + text.slice(retainedFrom);
21743
+ }
21744
+ function sensitiveValueEnd(text, start, header) {
21745
+ if (header) {
21746
+ const end = text.indexOf("\n", start);
21747
+ return end < 0 ? text.length : end;
21748
+ }
21749
+ const first = text[start];
21750
+ if (first === '"' || first === "'") {
21751
+ for (let index2 = start + 1; index2 < text.length; index2++) {
21752
+ if (text[index2] === "\\")
21753
+ index2++;
21754
+ else if (text[index2] === first)
21755
+ return index2 + 1;
21756
+ }
21757
+ return text.length;
21758
+ }
21759
+ if (first === "{" || first === "[") {
21760
+ const closing = [first === "{" ? "}" : "]"];
21761
+ let quote;
21762
+ for (let index2 = start + 1; index2 < text.length; index2++) {
21763
+ const character = text[index2];
21764
+ if (quote !== void 0) {
21765
+ if (character === "\\")
21766
+ index2++;
21767
+ else if (character === quote)
21768
+ quote = void 0;
21769
+ } else if (character === '"' || character === "'")
21770
+ quote = character;
21771
+ else if (character === "{" || character === "[")
21772
+ closing.push(character === "{" ? "}" : "]");
21773
+ else if (character === "}" || character === "]") {
21774
+ if (character !== closing.pop())
21775
+ return text.length;
21776
+ if (closing.length === 0)
21777
+ return index2 + 1;
21778
+ }
21779
+ }
21780
+ return text.length;
21781
+ }
21782
+ let index = start;
21783
+ while (index < text.length && !/[\s,;}\]]/u.test(text[index]))
21784
+ index++;
21785
+ return index;
21298
21786
  }
21299
21787
  function redactValue(value, options = {}) {
21300
21788
  if (typeof value === "string")
@@ -21316,6 +21804,208 @@ function cloneGlobal(pattern) {
21316
21804
  return new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`);
21317
21805
  }
21318
21806
 
21807
+ // ../adapters/dist/src/live-output.js
21808
+ import { randomUUID } from "node:crypto";
21809
+ var MAX_ITEMS = 128;
21810
+ var MAX_INPUT_BYTES = 96 * 1024;
21811
+ var MAX_PUBLIC_BYTES = 24 * 1024;
21812
+ var MAX_PUBLICATIONS = 1200;
21813
+ function createLiveOutputPublisher(options) {
21814
+ const items = /* @__PURE__ */ new Map();
21815
+ const now = options.now ?? Date.now;
21816
+ const intervalMs = options.intervalMs ?? 1500;
21817
+ let lastPublished, publications = 0, closed = false;
21818
+ let timer;
21819
+ let queue = Promise.resolve();
21820
+ let lastVisited;
21821
+ const serial = (operation) => {
21822
+ queue = queue.then(operation, operation);
21823
+ return queue;
21824
+ };
21825
+ const itemFor = (key, kind, title) => {
21826
+ let item = items.get(key);
21827
+ if (!item && items.size < MAX_ITEMS) {
21828
+ item = {
21829
+ streamId: randomUUID(),
21830
+ raw: "",
21831
+ kind,
21832
+ state: "running",
21833
+ revision: 0,
21834
+ acknowledged: "",
21835
+ dirty: true,
21836
+ truncated: false
21837
+ };
21838
+ items.set(key, item);
21839
+ }
21840
+ if (item && title !== void 0)
21841
+ item.title = bound(redactText(title, options.redaction), 256);
21842
+ return item;
21843
+ };
21844
+ const safe = (item) => {
21845
+ let content = item.raw;
21846
+ if (item.state === "running") {
21847
+ content = content.replace(/(?:\bBearer\s+|\b(?:api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|password|passwd|secret|token)["']?\s*[=:]\s*["']?)[^\n,;]*$/giu, "");
21848
+ let end = content.length;
21849
+ while (end > 0 && /[A-Za-z0-9_./~+=:@%\-]/u.test(content[end - 1]))
21850
+ end--;
21851
+ content = content.slice(0, end);
21852
+ }
21853
+ content = redactText(content, options.redaction);
21854
+ return bound(content, MAX_PUBLIC_BYTES, item.truncated);
21855
+ };
21856
+ const signatureFor = (item) => JSON.stringify([safe(item), item.state, item.title, item.plan]);
21857
+ const schedule = () => {
21858
+ if (closed || options.schedule === false || timer || ![...items.values()].some((x) => x.dirty))
21859
+ return;
21860
+ timer = setTimeout(() => {
21861
+ timer = void 0;
21862
+ void flush().catch(() => void 0);
21863
+ }, intervalMs);
21864
+ timer.unref();
21865
+ };
21866
+ const publishOne = async (item) => {
21867
+ if (!item.dirty || publications >= MAX_PUBLICATIONS)
21868
+ return;
21869
+ const content = safe(item);
21870
+ const signature = JSON.stringify([content, item.state, item.title, item.plan]);
21871
+ if (!item.pending && signature === item.acknowledged) {
21872
+ item.dirty = false;
21873
+ return;
21874
+ }
21875
+ if (!item.pending && !content.trim() && item.plan === void 0)
21876
+ return;
21877
+ const revision = item.revision + 1;
21878
+ const update = {
21879
+ id: `${item.streamId}:${revision}`,
21880
+ content,
21881
+ phase: "stream",
21882
+ streamId: item.streamId,
21883
+ streamMode: "snapshot",
21884
+ streamKind: item.kind,
21885
+ streamRevision: revision,
21886
+ streamState: item.state,
21887
+ ...item.title === void 0 ? {} : { title: item.title },
21888
+ ...item.plan === void 0 ? {} : { plan: item.plan }
21889
+ };
21890
+ item.pending ??= { update, signature };
21891
+ const pending = item.pending;
21892
+ try {
21893
+ if (await options.publish(pending.update) === false)
21894
+ return;
21895
+ item.revision = pending.update.streamRevision;
21896
+ item.acknowledged = pending.signature;
21897
+ delete item.pending;
21898
+ item.dirty = signatureFor(item) !== item.acknowledged;
21899
+ lastPublished = now();
21900
+ publications++;
21901
+ } catch {
21902
+ }
21903
+ };
21904
+ const flush = () => serial(async () => {
21905
+ if (closed || lastPublished !== void 0 && now() - lastPublished < intervalMs) {
21906
+ schedule();
21907
+ return;
21908
+ }
21909
+ const ordered = [...items.values()];
21910
+ const start = lastVisited === void 0 ? 0 : (ordered.indexOf(lastVisited) + 1) % ordered.length;
21911
+ for (let offset = 0; offset < ordered.length; offset++) {
21912
+ const item = ordered[(start + offset) % ordered.length];
21913
+ if (!item.dirty)
21914
+ continue;
21915
+ lastVisited = item;
21916
+ await publishOne(item);
21917
+ if (lastPublished !== void 0 && now() - lastPublished < intervalMs)
21918
+ break;
21919
+ }
21920
+ schedule();
21921
+ });
21922
+ return {
21923
+ async onDelta(key, delta, kind = "answer", title) {
21924
+ if (closed || !delta)
21925
+ return;
21926
+ const item = itemFor(key, kind, title);
21927
+ if (!item || item.state !== "running" || item.truncated)
21928
+ return;
21929
+ const raw = item.raw + delta;
21930
+ item.raw = bound(raw, MAX_INPUT_BYTES);
21931
+ item.truncated = Buffer.byteLength(raw) > MAX_INPUT_BYTES;
21932
+ item.dirty = true;
21933
+ await flush();
21934
+ },
21935
+ async onSnapshot(key, text, kind = "answer", title, state = "running") {
21936
+ if (closed)
21937
+ return;
21938
+ const item = itemFor(key, kind, title);
21939
+ if (!item)
21940
+ return;
21941
+ item.raw = bound(text, MAX_INPUT_BYTES);
21942
+ item.truncated = Buffer.byteLength(text) > MAX_INPUT_BYTES;
21943
+ item.state = state;
21944
+ item.dirty = true;
21945
+ await flush();
21946
+ },
21947
+ async onPlan(key, steps) {
21948
+ if (closed)
21949
+ return;
21950
+ const item = itemFor(key, "plan");
21951
+ if (!item)
21952
+ return;
21953
+ item.plan = steps.slice(0, 64).map((step) => ({ step: bound(redactText(step.step, options.redaction), 512), status: step.status }));
21954
+ item.raw = item.plan.map((step) => `${step.status}: ${step.step}`).join("\n");
21955
+ item.dirty = true;
21956
+ await flush();
21957
+ },
21958
+ flush,
21959
+ async finish(success2 = true) {
21960
+ if (timer) {
21961
+ clearTimeout(timer);
21962
+ timer = void 0;
21963
+ }
21964
+ await serial(async () => {
21965
+ if (closed)
21966
+ return;
21967
+ for (const item of [...items.values()].slice(0, 64)) {
21968
+ if (item.state === "running") {
21969
+ item.state = success2 ? "completed" : "failed";
21970
+ item.dirty = true;
21971
+ }
21972
+ await publishOne(item);
21973
+ if (item.dirty && !item.pending)
21974
+ await publishOne(item);
21975
+ }
21976
+ closed = true;
21977
+ items.clear();
21978
+ });
21979
+ },
21980
+ lastPublishedAt: () => lastPublished
21981
+ };
21982
+ }
21983
+ function liveOutputPayload(update) {
21984
+ return {
21985
+ content: update.content,
21986
+ phase: update.phase,
21987
+ stream_id: update.streamId,
21988
+ stream_mode: update.streamMode,
21989
+ stream_kind: update.streamKind,
21990
+ stream_revision: update.streamRevision,
21991
+ stream_state: update.streamState,
21992
+ ...update.title === void 0 ? {} : { title: update.title },
21993
+ ...update.plan === void 0 ? {} : { plan: update.plan.map((step) => ({ step: step.step, status: step.status })) }
21994
+ };
21995
+ }
21996
+ function bound(text, maxBytes, alreadyTruncated = false) {
21997
+ if (!alreadyTruncated && Buffer.byteLength(text) <= maxBytes)
21998
+ return text;
21999
+ const suffix = "\n[TRUNCATED]";
22000
+ const bytes2 = Buffer.from(text).subarray(0, maxBytes - Buffer.byteLength(suffix));
22001
+ let end = bytes2.length;
22002
+ while (end > 0 && (bytes2[end - 1] & 192) === 128)
22003
+ end--;
22004
+ if (end < bytes2.length || (bytes2[end - 1] & 128) !== 0)
22005
+ end = Math.max(0, end - 1);
22006
+ return bytes2.subarray(0, end).toString("utf8") + suffix;
22007
+ }
22008
+
21319
22009
  // ../adapters/dist/src/jsonl.js
21320
22010
  var DEFAULT_MAX_READ_BYTES = 4 * 1024 * 1024;
21321
22011
 
@@ -21412,6 +22102,9 @@ import { promisify } from "node:util";
21412
22102
  var execFileAsync = promisify(execFile);
21413
22103
  var MAX_BINDING_BYTES = 4 * 1024 * 1024;
21414
22104
 
22105
+ // ../bridge/dist/src/github-code-sync.js
22106
+ var filesSchema = createCodeFilesSchema(GITHUB_CODE_SYNC_LIMITS);
22107
+
21415
22108
  // dist/src/collaboration-api.js
21416
22109
  function createHttpDshCollaborationApi(options) {
21417
22110
  const client = new HttpCollaborationClient({
@@ -21532,12 +22225,12 @@ ${footer}`, "utf8");
21532
22225
  const retained = [];
21533
22226
  let used = 0;
21534
22227
  for (const line of contextLines.toReversed()) {
21535
- const bytes = Buffer.byteLength(`${line}
22228
+ const bytes2 = Buffer.byteLength(`${line}
21536
22229
  `, "utf8");
21537
- if (used + bytes > contextBudget)
22230
+ if (used + bytes2 > contextBudget)
21538
22231
  continue;
21539
22232
  retained.push(line);
21540
- used += bytes;
22233
+ used += bytes2;
21541
22234
  }
21542
22235
  retained.reverse();
21543
22236
  const omitted = retained.length < contextLines.length ? [`[${contextLines.length - retained.length} older public context update(s) omitted by size limit]`] : [];
@@ -21789,6 +22482,255 @@ function asObject2(value) {
21789
22482
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
21790
22483
  }
21791
22484
 
22485
+ // dist/src/live-event-mapper.js
22486
+ var MAX_ATTEMPTS = 64;
22487
+ var MAX_BLOCKS = 128;
22488
+ var MAX_TEXT = 96 * 1024;
22489
+ function createDshLiveEventMapper(publisher) {
22490
+ const attempts = /* @__PURE__ */ new Map();
22491
+ const steps = /* @__PURE__ */ new Map();
22492
+ const tools = /* @__PURE__ */ new Map();
22493
+ let revision = 0;
22494
+ const deliver = (operation) => {
22495
+ void operation.catch(() => void 0);
22496
+ };
22497
+ const snapshot = (block, state) => deliver(publisher.onSnapshot(block.key, block.text, block.kind, block.title, state));
22498
+ const toolFor = (id, fallbackKey) => {
22499
+ let tool = tools.get(id);
22500
+ if (tool === void 0 && tools.size < MAX_BLOCKS) {
22501
+ tool = { key: fallbackKey, arguments: "" };
22502
+ tools.set(id, tool);
22503
+ }
22504
+ return tool;
22505
+ };
22506
+ const settle2 = (attempt, state) => {
22507
+ if (state === "failed")
22508
+ attempt.failed = true;
22509
+ for (const block of attempt.blocks.values()) {
22510
+ if (block.kind !== "tool")
22511
+ snapshot(block, state);
22512
+ else if (state === "failed") {
22513
+ const argumentsText = block.callId === void 0 ? void 0 : tools.get(block.callId)?.arguments;
22514
+ deliver(publisher.onSnapshot(block.key, `Arguments:
22515
+ ${argumentsText || "[Unparseable tool arguments]"}`, "tool", block.title, state));
22516
+ }
22517
+ }
22518
+ };
22519
+ const onFrame = (frame) => {
22520
+ if (frame.revision <= revision)
22521
+ return;
22522
+ const identity = frame.attemptId;
22523
+ if (frame.type === "start") {
22524
+ if (attempts.has(identity) || attempts.size >= MAX_ATTEMPTS)
22525
+ return;
22526
+ revision = frame.revision;
22527
+ const attempt2 = { turn: frame.turn, step: frame.step, nextIndex: 0, closed: false, failed: false, blocks: /* @__PURE__ */ new Map() };
22528
+ attempts.set(identity, attempt2);
22529
+ steps.set(`${frame.turn}:${frame.step}`, attempt2);
22530
+ return;
22531
+ }
22532
+ const attempt = attempts.get(identity);
22533
+ if (attempt === void 0 || attempt.closed || frame.index !== attempt.nextIndex)
22534
+ return;
22535
+ revision = frame.revision;
22536
+ if (frame.type === "end") {
22537
+ attempt.closed = true;
22538
+ settle2(attempt, attempt.failed || frame.outcome.kind === "abandoned" || frame.outcome.eventType === "assistant/attempt" ? "failed" : "completed");
22539
+ return;
22540
+ }
22541
+ attempt.nextIndex++;
22542
+ const chunk = object2(frame.chunk);
22543
+ if (chunk?.type === "finish") {
22544
+ const reason = object2(chunk.reason)?.kind ?? chunk.reason;
22545
+ if (reason === "error" || reason === "aborted")
22546
+ settle2(attempt, "failed");
22547
+ return;
22548
+ }
22549
+ if (!integer2(chunk?.index) || Number(chunk.index) >= MAX_BLOCKS)
22550
+ return;
22551
+ const index = Number(chunk.index);
22552
+ if (chunk.type === "block-start") {
22553
+ const kind = chunk.blockType === "text" ? "answer" : chunk.blockType === "reasoning" ? "reasoning" : chunk.blockType === "tool-call" ? "tool" : void 0;
22554
+ if (kind !== void 0 && !attempt.blocks.has(index)) {
22555
+ attempt.blocks.set(index, { key: `${identity}:${index}`, kind, text: "" });
22556
+ }
22557
+ return;
22558
+ }
22559
+ const block = attempt.blocks.get(index);
22560
+ if (block === void 0)
22561
+ return;
22562
+ if (chunk.type === "text-delta" && block.kind === "answer" || chunk.type === "reasoning-delta" && block.kind === "reasoning") {
22563
+ if (typeof chunk.text !== "string")
22564
+ return;
22565
+ block.text = bound2(block.text + chunk.text);
22566
+ deliver(publisher.onDelta(block.key, chunk.text, block.kind));
22567
+ } else if (chunk.type === "tool-call-delta" && block.kind === "tool") {
22568
+ if (!identifier(chunk.id) || typeof chunk.argumentsDelta !== "string" || block.callId !== void 0 && block.callId !== chunk.id)
22569
+ return;
22570
+ block.callId = chunk.id;
22571
+ if (typeof chunk.name === "string")
22572
+ block.title = bound2(chunk.name).slice(0, 256);
22573
+ const tool = toolFor(block.callId, block.key);
22574
+ if (tool === void 0)
22575
+ return;
22576
+ block.key = tool.key;
22577
+ block.text = bound2(block.text + chunk.argumentsDelta);
22578
+ if (block.title !== void 0)
22579
+ tool.title = block.title;
22580
+ const argumentsText = parsedArguments(block.text);
22581
+ if (argumentsText !== void 0)
22582
+ tool.arguments = argumentsText;
22583
+ deliver(publisher.onSnapshot(block.key, argumentsText === void 0 ? "Preparing tool arguments.\n" : `Arguments:
22584
+ ${argumentsText}`, "tool", block.title));
22585
+ } else if (chunk.type === "block-end") {
22586
+ const content = object2(chunk.block);
22587
+ if ((content?.type === "text" && block.kind === "answer" || content?.type === "reasoning" && block.kind === "reasoning") && typeof content.text === "string") {
22588
+ block.text = bound2(content.text);
22589
+ snapshot(block, "completed");
22590
+ } else if (content?.type === "tool-call" && block.kind === "tool" && identifier(content.id) && typeof content.arguments === "string" && (block.callId === void 0 || content.id === block.callId)) {
22591
+ const tool = toolFor(content.id, block.key);
22592
+ if (tool === void 0)
22593
+ return;
22594
+ block.callId = content.id;
22595
+ block.key = tool.key;
22596
+ block.text = publicArguments(content.arguments);
22597
+ if (typeof content.name === "string")
22598
+ block.title = content.name.slice(0, 256);
22599
+ tool.arguments = block.text;
22600
+ if (block.title !== void 0)
22601
+ tool.title = block.title;
22602
+ snapshot(block, "running");
22603
+ }
22604
+ }
22605
+ };
22606
+ const onDurable = (event) => {
22607
+ const data = object2(event.data);
22608
+ if (data === void 0)
22609
+ return;
22610
+ if (event.type === "assistant/message" && integer2(data.turn) && integer2(data.step)) {
22611
+ const attempt = steps.get(`${data.turn}:${data.step}`);
22612
+ if (attempt !== void 0 && data.interrupted === true)
22613
+ attempt.failed = true;
22614
+ const message = object2(data.message);
22615
+ if (!Array.isArray(message?.content))
22616
+ return;
22617
+ const nativeBlocks = [...attempt?.blocks.values() ?? []];
22618
+ for (const [index, value] of message.content.slice(0, MAX_BLOCKS).entries()) {
22619
+ const content = object2(value);
22620
+ const kind = content?.type === "text" ? "answer" : content?.type === "reasoning" ? "reasoning" : void 0;
22621
+ if (kind !== void 0 && typeof content.text === "string") {
22622
+ const candidate = nativeBlocks[index];
22623
+ const key = candidate?.kind === kind ? candidate.key : `assistant:${event.seq}:${index}`;
22624
+ if (candidate?.kind === kind)
22625
+ candidate.text = bound2(content.text);
22626
+ deliver(publisher.onSnapshot(key, content.text, kind, void 0, data.interrupted === true ? "failed" : "completed"));
22627
+ }
22628
+ }
22629
+ } else if (event.type === "assistant/attempt" && integer2(data.turn) && integer2(data.step)) {
22630
+ const attempt = steps.get(`${data.turn}:${data.step}`);
22631
+ if (attempt !== void 0)
22632
+ settle2(attempt, "failed");
22633
+ } else if (event.type === "tool/call" && identifier(data.callId) && typeof data.name === "string" && typeof data.arguments === "string") {
22634
+ const tool = toolFor(data.callId, `tool:${event.seq}`);
22635
+ if (tool === void 0)
22636
+ return;
22637
+ tool.arguments = publicArguments(data.arguments);
22638
+ tool.title = data.name.slice(0, 256);
22639
+ deliver(publisher.onSnapshot(tool.key, `Arguments:
22640
+ ${tool.arguments}`, "tool", tool.title));
22641
+ } else if (event.type === "tool/result") {
22642
+ const message = object2(data.message);
22643
+ const content = Array.isArray(message?.content) ? message.content : [];
22644
+ const wrapped = content.map(object2).find((block) => block?.type === "tool-result");
22645
+ const id = wrapped?.toolCallId ?? message?.toolCallId;
22646
+ if (!identifier(id))
22647
+ return;
22648
+ const tool = tools.get(id);
22649
+ if (tool === void 0)
22650
+ return;
22651
+ const blocks = wrapped === void 0 ? content : wrapped.content;
22652
+ if (!Array.isArray(blocks))
22653
+ return;
22654
+ const text = blocks.slice(0, MAX_BLOCKS).flatMap((value) => {
22655
+ const block = object2(value);
22656
+ return block?.type === "text" && typeof block.text === "string" ? [bound2(block.text)] : [];
22657
+ }).join("");
22658
+ const failed = wrapped?.isError === true || message?.isError === true || data.error !== void 0;
22659
+ deliver(publisher.onSnapshot(tool.key, `Arguments:
22660
+ ${tool.arguments}
22661
+
22662
+ Result:
22663
+ ${bound2(text)}`, "tool", tool.title, failed ? "failed" : "completed"));
22664
+ } else if (event.type === "todo/write" && Array.isArray(data.todos) && data.todos.length <= 64) {
22665
+ const plan = [];
22666
+ for (const value of data.todos) {
22667
+ const item = object2(value);
22668
+ if (typeof item?.content !== "string" || !["pending", "in_progress", "completed"].includes(String(item.status)))
22669
+ return;
22670
+ plan.push({ step: item.content, status: item.status });
22671
+ }
22672
+ deliver(publisher.onPlan("plan", plan));
22673
+ }
22674
+ };
22675
+ return {
22676
+ onEvent(event) {
22677
+ if (event.kind === "assistant-stream")
22678
+ onFrame(event.frame);
22679
+ else
22680
+ onDurable(event.event);
22681
+ },
22682
+ async finish(success2 = true) {
22683
+ await publisher.finish(success2);
22684
+ }
22685
+ };
22686
+ }
22687
+ function parseDshAssistantStreamFrame(value) {
22688
+ const frame = object2(value);
22689
+ if (!identifier(frame?.attemptId) || !integer2(frame?.revision) || Number(frame.revision) < 1)
22690
+ return void 0;
22691
+ const shared = { attemptId: frame.attemptId, revision: Number(frame.revision) };
22692
+ if (frame.type === "start" && integer2(frame.turn) && integer2(frame.step)) {
22693
+ return { type: "start", ...shared, turn: Number(frame.turn), step: Number(frame.step) };
22694
+ }
22695
+ if (frame.type === "chunk" && integer2(frame.index) && integer2(frame.time) && object2(frame.chunk) !== void 0) {
22696
+ return { type: "chunk", ...shared, index: Number(frame.index), time: Number(frame.time), chunk: frame.chunk };
22697
+ }
22698
+ const outcome = object2(frame.outcome);
22699
+ if (frame.type === "end" && integer2(frame.index)) {
22700
+ if (outcome?.kind === "abandoned")
22701
+ return { type: "end", ...shared, index: Number(frame.index), outcome: { kind: "abandoned" } };
22702
+ if (outcome?.kind === "committed" && integer2(outcome.seq) && (outcome.eventType === "assistant/message" || outcome.eventType === "assistant/attempt")) {
22703
+ return { type: "end", ...shared, index: Number(frame.index), outcome: { kind: "committed", eventType: outcome.eventType, seq: Number(outcome.seq) } };
22704
+ }
22705
+ }
22706
+ return void 0;
22707
+ }
22708
+ function publicArguments(text) {
22709
+ return parsedArguments(text) ?? "[Unparseable tool arguments]";
22710
+ }
22711
+ function parsedArguments(text) {
22712
+ if (text.length > MAX_TEXT)
22713
+ return void 0;
22714
+ try {
22715
+ return JSON.stringify(redactValue(JSON.parse(text)));
22716
+ } catch {
22717
+ return void 0;
22718
+ }
22719
+ }
22720
+ function bound2(text) {
22721
+ return text.length > MAX_TEXT ? `${text.slice(0, MAX_TEXT)}
22722
+ [TRUNCATED]` : text;
22723
+ }
22724
+ function integer2(value) {
22725
+ return Number.isSafeInteger(value) && Number(value) >= 0;
22726
+ }
22727
+ function identifier(value) {
22728
+ return typeof value === "string" && value.length > 0 && value.length <= 512;
22729
+ }
22730
+ function object2(value) {
22731
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
22732
+ }
22733
+
21792
22734
  // dist/src/connector.js
21793
22735
  var INTERRUPTED_REQUEST_CONTINUATION = "Continue the interrupted GatherThread request using the DSH Session context already restored by the Host. Return only the public final answer.";
21794
22736
  var LIVE_PROGRESS_MIN_INTERVAL_MS = 6e4;
@@ -21816,6 +22758,7 @@ var DshHostConnector = class {
21816
22758
  #publicationPromise;
21817
22759
  #heartbeatOffline = false;
21818
22760
  #liveProgressPromise = Promise.resolve();
22761
+ #activeLiveOutput;
21819
22762
  #lastLiveProgressKey;
21820
22763
  #lastLiveProgressAt = 0;
21821
22764
  #stopPromise;
@@ -21826,6 +22769,8 @@ var DshHostConnector = class {
21826
22769
  #activeExecutionSelection;
21827
22770
  #summaryScanSequence = 0;
21828
22771
  #hasSummaryHistory = false;
22772
+ #revisionPollPromise;
22773
+ #revisionSupported = false;
21829
22774
  #liveEventSequences = /* @__PURE__ */ new Set();
21830
22775
  #session;
21831
22776
  #visibleState = "connecting";
@@ -21851,6 +22796,15 @@ var DshHostConnector = class {
21851
22796
  get stopped() {
21852
22797
  return this.#stopped;
21853
22798
  }
22799
+ /** Project refresh is authoritative for the mode of future DSH bubbles. */
22800
+ updateSessionSummary(session) {
22801
+ if (!this.#started || this.#stopped)
22802
+ throw new Error("DSH connector is not running");
22803
+ if (session.id !== this.#config.sessionId || session.projectId !== this.#config.projectId || session.state !== "active" || !isSessionWritableBy(session, this.#actorUserId)) {
22804
+ throw new Error("Refreshed GatherThread Session is not this writable binding");
22805
+ }
22806
+ this.#session = session;
22807
+ }
21854
22808
  /**
21855
22809
  * Adopt a refreshed execution-profile catalog on a running connection.
21856
22810
  *
@@ -21921,7 +22875,8 @@ var DshHostConnector = class {
21921
22875
  ...executionProfiles === void 0 ? {} : {
21922
22876
  executionProfiles: cloneExecutionProfiles(executionProfiles)
21923
22877
  },
21924
- purpose: "execution"
22878
+ purpose: "execution",
22879
+ ...this.#host.contextDeletionVersion === 1 ? { contextDeletionVersion: 1 } : {}
21925
22880
  };
21926
22881
  }
21927
22882
  get executionRuntimeId() {
@@ -21954,6 +22909,7 @@ var DshHostConnector = class {
21954
22909
  }
21955
22910
  uploadLocalTurns() {
21956
22911
  return this.#withLocalSyncControl(async () => {
22912
+ await this.#refreshContentRevision();
21957
22913
  const before = this.localSyncStatus();
21958
22914
  await this.#flushOutbox(true);
21959
22915
  await this.#captureLocalTurns(0);
@@ -21976,6 +22932,15 @@ var DshHostConnector = class {
21976
22932
  this.#started = true;
21977
22933
  this.#automaticPolling = options.schedule !== false;
21978
22934
  this.#notifyLifecycle("connecting");
22935
+ if (this.#host.onLiveOutput !== void 0) {
22936
+ this.#listenerDisposers.push(this.#host.onLiveOutput((event) => {
22937
+ const active = this.#state?.activeRequest;
22938
+ const output2 = this.#activeLiveOutput;
22939
+ if (this.#stopped || active === void 0 || output2 === void 0 || event.sourceSessionId !== output2.sourceSessionId || event.sourceSessionId !== (active.contextExecution?.sessionId ?? this.#host.sessionId))
22940
+ return;
22941
+ output2.mapper.onEvent(event);
22942
+ }));
22943
+ }
21979
22944
  this.#listenerDisposers.push(this.#host.onSessionEvent((event) => {
21980
22945
  const active = this.#state?.activeRequest;
21981
22946
  if (active?.contextExecution !== void 0 && event.sourceSessionId !== active.contextExecution.sessionId)
@@ -22021,6 +22986,7 @@ var DshHostConnector = class {
22021
22986
  }));
22022
22987
  try {
22023
22988
  const session = await this.#verifySessionBinding();
22989
+ this.#revisionSupported = session.contentRevision !== void 0;
22024
22990
  this.#session = session;
22025
22991
  this.#notifyLifecycle("connecting");
22026
22992
  const storedState = await this.#stateStore.load();
@@ -22028,8 +22994,16 @@ var DshHostConnector = class {
22028
22994
  throw new Error("GatherThread Session head precedes the persisted DSH cursor; refusing identity reuse");
22029
22995
  }
22030
22996
  const mode = await this.#host.open();
22997
+ if (storedState?.projectionSessionId && (storedState.contentRevision ?? 0) > 0) {
22998
+ if (!this.#host.resetCanonicalContext)
22999
+ throw new Error("DSH deletion-safe projection requires an updated native facade");
23000
+ const restored = await this.#host.resetCanonicalContext(storedState.contentRevision);
23001
+ if (restored.sessionId !== storedState.projectionSessionId)
23002
+ throw new Error("DSH restored another native projection");
23003
+ }
22031
23004
  this.#state = this.#reconcileState(storedState, mode);
22032
23005
  await this.#stateStore.save(this.#state);
23006
+ await this.#refreshContentRevision();
22033
23007
  this.#runtime = await this.#api.registerRuntime(this.#runtimeRegistration());
22034
23008
  this.#assertRuntime(this.#runtime);
22035
23009
  this.#notifyLifecycle("idle");
@@ -22101,6 +23075,8 @@ var DshHostConnector = class {
22101
23075
  stop() {
22102
23076
  this.#stopPromise ??= (async () => {
22103
23077
  this.#stopped = true;
23078
+ const liveOutput = this.#activeLiveOutput;
23079
+ this.#activeLiveOutput = void 0;
22104
23080
  this.#notifyLifecycle("stopped");
22105
23081
  this.#lifecycleAbort.abort(new Error("DSH connector stopped"));
22106
23082
  if (this.#timer !== void 0) {
@@ -22114,6 +23090,7 @@ var DshHostConnector = class {
22114
23090
  for (const dispose of this.#listenerDisposers.splice(0))
22115
23091
  dispose();
22116
23092
  await this.#host.dispose();
23093
+ void liveOutput?.mapper.finish(false).catch(() => void 0);
22117
23094
  try {
22118
23095
  await this.#pollPromise;
22119
23096
  } catch {
@@ -22126,6 +23103,7 @@ var DshHostConnector = class {
22126
23103
  return this.#stopPromise;
22127
23104
  }
22128
23105
  async #poll() {
23106
+ await this.#refreshContentRevision();
22129
23107
  const state = this.#requireState();
22130
23108
  if (state.activeRequest !== void 0) {
22131
23109
  await this.#withExecutionPermit(() => this.#recoverActiveRequest());
@@ -22142,6 +23120,12 @@ var DshHostConnector = class {
22142
23120
  let scanned = 0;
22143
23121
  while (!this.#stopped) {
22144
23122
  const page = await this.#api.readEvents(this.#config.sessionId, scanCursor, this.#config.pollLimit);
23123
+ if (page.contentRevision !== void 0)
23124
+ this.#revisionSupported = true;
23125
+ if ((page.contentRevision ?? 0) !== (state.contentRevision ?? 0)) {
23126
+ await this.#refreshContentRevision();
23127
+ return this.#poll();
23128
+ }
22145
23129
  this.#validatePage(page.events, scanCursor);
22146
23130
  const passive = [];
22147
23131
  for (const event of page.events) {
@@ -22175,6 +23159,39 @@ var DshHostConnector = class {
22175
23159
  }
22176
23160
  throw new Error("DSH connector stopped during event replay");
22177
23161
  }
23162
+ async #refreshContentRevision() {
23163
+ const state = this.#requireState();
23164
+ if (!this.#revisionSupported && (state.contentRevision ?? 0) === 0)
23165
+ return;
23166
+ const page = await this.#api.readEvents(this.#config.sessionId, 0, 1);
23167
+ const revision = page.contentRevision ?? 0;
23168
+ if (!Number.isSafeInteger(revision) || revision < (state.contentRevision ?? 0))
23169
+ throw new Error("Stale DSH shared context revision");
23170
+ if (revision === (state.contentRevision ?? 0)) {
23171
+ if (revision > 0 && state.projectionSessionId && this.#host.resetCanonicalContext) {
23172
+ const restored = await this.#host.resetCanonicalContext(revision);
23173
+ if (restored.sessionId !== state.projectionSessionId)
23174
+ throw new Error("DSH clean projection binding changed on reconnect");
23175
+ }
23176
+ return;
23177
+ }
23178
+ state.localOnlySessionIds = [.../* @__PURE__ */ new Set([...state.localOnlySessionIds ?? [], this.#config.dshSessionId, this.#host.sessionId])];
23179
+ state.outbox = [];
23180
+ delete state.activeRequest;
23181
+ this.#activeStatuses = [];
23182
+ this.#activeExecutionSelection = void 0;
23183
+ this.#summaryScanSequence = 0;
23184
+ this.#hasSummaryHistory = false;
23185
+ await this.#stateStore.save(state);
23186
+ if (this.#host.resetCanonicalContext) {
23187
+ const replacement = await this.#host.resetCanonicalContext(revision);
23188
+ state.projectionSessionId = replacement.sessionId;
23189
+ state.projectionCursor = 0;
23190
+ state.publishedDshSequence = this.#host.currentSequence();
23191
+ }
23192
+ state.contentRevision = revision;
23193
+ await this.#stateStore.save(state);
23194
+ }
22178
23195
  async #executeRequest(request, selection) {
22179
23196
  if (this.#stopped)
22180
23197
  throw new Error("DSH connector stopped before claiming an Agent request");
@@ -22193,6 +23210,8 @@ var DshHostConnector = class {
22193
23210
  await this.#projectCanonicalBatch([request], request.sequence);
22194
23211
  return { claimed: false, completed: false };
22195
23212
  }
23213
+ if ((claim2.contentRevision ?? state.contentRevision ?? 0) !== (state.contentRevision ?? 0))
23214
+ throw new Error("context_changed");
22196
23215
  const quotedEvent = request.replyTo ? (await this.#readThroughRequest(request.id, request.sequence)).find((event) => event.id === request.replyTo) : void 0;
22197
23216
  const prompt = buildDshRequestPrompt(request, quotedEvent);
22198
23217
  const context = await this.#contextForRequest(request);
@@ -22205,6 +23224,7 @@ var DshHostConnector = class {
22205
23224
  if (prepared !== void 0 && prepared.fromSequence !== baseline)
22206
23225
  throw new Error("DSH context preparation returned an inconsistent sequence");
22207
23226
  state.activeRequest = {
23227
+ contentRevision: state.contentRevision ?? 0,
22208
23228
  requestId: request.id,
22209
23229
  requestSequence: request.sequence,
22210
23230
  dshFromSequence: baseline,
@@ -22218,7 +23238,7 @@ var DshHostConnector = class {
22218
23238
  this.#activeExecutionSelection = selection;
22219
23239
  this.#liveEventSequences.clear();
22220
23240
  await this.#stateStore.save(state);
22221
- const result = await this.#host.prompt(prompt, selection, prepared?.sessionId);
23241
+ const result = await this.#promptWithLiveOutput(prompt, selection, prepared?.sessionId);
22222
23242
  if (result.fromSequence !== baseline || result.toSequence < result.fromSequence) {
22223
23243
  throw new Error("DSH Host prompt returned an inconsistent durable event range");
22224
23244
  }
@@ -22240,7 +23260,7 @@ var DshHostConnector = class {
22240
23260
  throw new Error("GatherThread history summary request has invalid source metadata");
22241
23261
  if (selectedOnly)
22242
23262
  this.#hasSummaryHistory = true;
22243
- if (!selectedOnly && !await this.#sessionHasSummaryBefore(request.sequence))
23263
+ if (!selectedOnly && (this.#requireState().contentRevision ?? 0) === 0 && !await this.#sessionHasSummaryBefore(request.sequence))
22244
23264
  return void 0;
22245
23265
  if (!selectedOnly && this.#api.readContext === void 0) {
22246
23266
  throw new Error("GatherThread summarized context is unavailable; update the connector before continuing");
@@ -22248,7 +23268,9 @@ var DshHostConnector = class {
22248
23268
  if (this.#host.prepareContextExecution === void 0) {
22249
23269
  throw new Error("DSH isolated context execution is unavailable; refusing to run a summary-aware request in native history");
22250
23270
  }
22251
- const received = selectedOnly ? { view: "original", through_sequence: request.sequence - 1, items: [] } : parseHistoryContext(await this.#api.readContext(this.#config.sessionId, void 0, request.sequence - 1), void 0, request.sequence - 1);
23271
+ const received = selectedOnly ? { view: "original", content_revision: this.#requireState().contentRevision ?? 0, through_sequence: request.sequence - 1, items: [] } : parseHistoryContext(await this.#api.readContext(this.#config.sessionId, void 0, request.sequence - 1), void 0, request.sequence - 1);
23272
+ if ((received.content_revision ?? 0) !== (this.#requireState().contentRevision ?? 0))
23273
+ throw new Error("context_changed");
22252
23274
  const historyContext = { ...received, items: received.items.map((item) => ({ ...item, content: redactText(item.content) })) };
22253
23275
  return { historyContext, selectedOnly };
22254
23276
  }
@@ -22346,6 +23368,10 @@ var DshHostConnector = class {
22346
23368
  throw new Error("Active GatherThread request no longer has a recoverable claim");
22347
23369
  }
22348
23370
  const claimAttempt = claim2.attemptCount ?? active.claimAttempt ?? 1;
23371
+ if ((active.contentRevision ?? 0) !== (state.contentRevision ?? 0) || (claim2.contentRevision ?? active.contentRevision ?? 0) !== (active.contentRevision ?? 0)) {
23372
+ await this.#retireFencedActiveRequest(state, active);
23373
+ return;
23374
+ }
22349
23375
  active.claimAttempt = claimAttempt;
22350
23376
  if (active.dshToSequence !== void 0) {
22351
23377
  state.outbox = state.outbox.map((operation) => {
@@ -22418,7 +23444,7 @@ var DshHostConnector = class {
22418
23444
  this.#activeStatuses = [];
22419
23445
  this.#liveEventSequences.clear();
22420
23446
  await this.#stateStore.save(state);
22421
- const result = await this.#host.prompt(continuation, selection, execution?.sessionId);
23447
+ const result = await this.#promptWithLiveOutput(continuation, selection, execution?.sessionId);
22422
23448
  if (result.fromSequence !== baseline || result.toSequence < result.fromSequence) {
22423
23449
  throw new Error("DSH Host recovery prompt returned an inconsistent durable event range");
22424
23450
  }
@@ -22447,6 +23473,94 @@ var DshHostConnector = class {
22447
23473
  await this.#flushOutbox();
22448
23474
  await this.#finalizeDeliveredRequest();
22449
23475
  }
23476
+ async #promptWithLiveOutput(text, selection, executionSessionId) {
23477
+ const active = this.#requireState().activeRequest;
23478
+ if (active === void 0)
23479
+ throw new Error("No claimed DSH request owns live output");
23480
+ const requestId = active.requestId;
23481
+ const claimAttempt = active.claimAttempt ?? 1;
23482
+ const fromSequence = active.dshFromSequence;
23483
+ const runtime = this.#requireRuntime();
23484
+ const sourceSessionId = executionSessionId ?? this.#host.sessionId;
23485
+ const publisher = createLiveOutputPublisher({
23486
+ publish: async (update) => {
23487
+ const publication = this.#liveProgressPromise.then(async () => {
23488
+ const current = this.#state?.activeRequest;
23489
+ if (this.#stopped || this.#activeLiveOutput?.publisher !== publisher || current?.requestId !== requestId || (current.claimAttempt ?? 1) !== claimAttempt || current.dshFromSequence !== fromSequence || (current.contextExecution?.sessionId ?? this.#host.sessionId) !== sourceSessionId || this.#runtime?.id !== runtime.id || this.#activeExecutionSelection !== selection)
23490
+ return false;
23491
+ await this.#api.appendAgentProgress(this.#config.sessionId, requestId, {
23492
+ runtimeId: runtime.id,
23493
+ claimAttempt,
23494
+ contentRevision: active.contentRevision ?? 0,
23495
+ idempotencyKey: `${this.#config.deviceId}:${digest(requestId).slice(0, 24)}:${claimAttempt}:live-${update.id}`,
23496
+ payload: { ...liveOutputPayload(update), capture_fidelity: "harness_transcript", source_harness: "deepseek-harness" },
23497
+ observedModel: selection.model,
23498
+ ...selection.reasoningEffort === void 0 ? {} : { observedReasoningEffort: selection.reasoningEffort }
23499
+ });
23500
+ return true;
23501
+ });
23502
+ this.#liveProgressPromise = publication.then(() => void 0).catch((error62) => {
23503
+ this.#onBackgroundError?.(publicError(error62));
23504
+ });
23505
+ return publication.catch(() => false);
23506
+ }
23507
+ });
23508
+ const output2 = { publisher, mapper: createDshLiveEventMapper(publisher), sourceSessionId };
23509
+ this.#activeLiveOutput = output2;
23510
+ const abort = new AbortController();
23511
+ const abortLifecycle = () => abort.abort(this.#lifecycleAbort.signal.reason);
23512
+ this.#lifecycleAbort.signal.addEventListener("abort", abortLifecycle, { once: true });
23513
+ const verifyRevision = async () => {
23514
+ if (!this.#revisionSupported && (active.contentRevision ?? 0) === 0)
23515
+ return;
23516
+ try {
23517
+ const page = await this.#api.readEvents(this.#config.sessionId, 0, 1);
23518
+ if ((page.contentRevision ?? 0) !== (active.contentRevision ?? 0))
23519
+ abort.abort(new Error("context_changed"));
23520
+ } catch (error62) {
23521
+ abort.abort(error62);
23522
+ }
23523
+ };
23524
+ const timer = setInterval(() => {
23525
+ if (this.#revisionPollPromise)
23526
+ return;
23527
+ const poll = verifyRevision();
23528
+ this.#revisionPollPromise = poll;
23529
+ void poll.finally(() => {
23530
+ if (this.#revisionPollPromise === poll)
23531
+ this.#revisionPollPromise = void 0;
23532
+ });
23533
+ }, 1e3);
23534
+ timer.unref();
23535
+ try {
23536
+ await verifyRevision();
23537
+ abort.signal.throwIfAborted();
23538
+ const result = await this.#host.prompt(text, selection, executionSessionId, abort.signal);
23539
+ await verifyRevision();
23540
+ abort.signal.throwIfAborted();
23541
+ await output2.mapper.finish();
23542
+ return result;
23543
+ } catch (error62) {
23544
+ if (abort.signal.aborted) {
23545
+ const state = this.#requireState();
23546
+ state.outbox = state.outbox.filter((operation) => !outboxBelongsToRequest(operation, requestId));
23547
+ delete state.activeRequest;
23548
+ this.#activeExecutionSelection = void 0;
23549
+ await this.#stateStore.save(state);
23550
+ }
23551
+ throw error62;
23552
+ } finally {
23553
+ clearInterval(timer);
23554
+ this.#lifecycleAbort.signal.removeEventListener("abort", abortLifecycle);
23555
+ await this.#revisionPollPromise;
23556
+ if (this.#activeLiveOutput === output2)
23557
+ this.#activeLiveOutput = void 0;
23558
+ if (this.#stopped)
23559
+ void output2.mapper.finish(false).catch(() => void 0);
23560
+ else
23561
+ await output2.mapper.finish(false);
23562
+ }
23563
+ }
22450
23564
  #queueLiveProgress(idSuffix, payload, throttle = true) {
22451
23565
  const active = this.#state?.activeRequest;
22452
23566
  const runtime = this.#runtime;
@@ -22456,6 +23570,9 @@ var DshHostConnector = class {
22456
23570
  const claimAttempt = active.claimAttempt ?? 1;
22457
23571
  const progressKey = `${requestId}:${String(claimAttempt)}`;
22458
23572
  const now = Date.now();
23573
+ const streamedAt = this.#activeLiveOutput?.publisher.lastPublishedAt();
23574
+ if (throttle && streamedAt !== void 0 && now - streamedAt < LIVE_PROGRESS_MIN_INTERVAL_MS)
23575
+ return;
22459
23576
  if (throttle && this.#lastLiveProgressKey === progressKey && now - this.#lastLiveProgressAt < LIVE_PROGRESS_MIN_INTERVAL_MS) {
22460
23577
  return;
22461
23578
  }
@@ -22466,7 +23583,7 @@ var DshHostConnector = class {
22466
23583
  const idempotencyKey = `${this.#config.deviceId}:${digest(requestId).slice(0, 24)}:${String(claimAttempt)}:${idSuffix}`;
22467
23584
  this.#liveProgressPromise = this.#liveProgressPromise.then(async () => {
22468
23585
  const current = this.#state?.activeRequest;
22469
- if (current?.requestId !== requestId || (current.claimAttempt ?? 1) !== claimAttempt)
23586
+ if (this.#stopped || current?.requestId !== requestId || (current.claimAttempt ?? 1) !== claimAttempt || this.#runtime?.id !== runtime.id)
22470
23587
  return;
22471
23588
  const selection = this.#activeExecutionSelection;
22472
23589
  if (selection === void 0)
@@ -22474,6 +23591,7 @@ var DshHostConnector = class {
22474
23591
  await this.#api.appendAgentProgress(this.#config.sessionId, requestId, {
22475
23592
  runtimeId: runtime.id,
22476
23593
  claimAttempt,
23594
+ contentRevision: active.contentRevision ?? 0,
22477
23595
  idempotencyKey,
22478
23596
  payload,
22479
23597
  observedModel: selection.model,
@@ -22491,11 +23609,15 @@ var DshHostConnector = class {
22491
23609
  }
22492
23610
  async #projectCanonicalBatch(events, throughSequence) {
22493
23611
  const state = this.#requireState();
23612
+ if (state.localOnlySessionIds?.includes(this.#host.sessionId))
23613
+ return;
22494
23614
  if (throughSequence <= state.projectionCursor)
22495
23615
  return;
22496
23616
  const runtime = this.#requireRuntime();
22497
23617
  const projections = [];
22498
23618
  for (const event of events) {
23619
+ if (event.deleted)
23620
+ continue;
22499
23621
  if (event.type === "agent_request" && asObject3(event.payload)?.history_summary !== void 0) {
22500
23622
  this.#hasSummaryHistory = true;
22501
23623
  continue;
@@ -22512,7 +23634,7 @@ var DshHostConnector = class {
22512
23634
  role: "user",
22513
23635
  content,
22514
23636
  occurredAt: event.timestamp,
22515
- ...event.actorDisplayName === void 0 ? {} : {
23637
+ ...this.#session?.mode !== "multi" || event.actorDisplayName === void 0 ? {} : {
22516
23638
  actorDisplayName: event.actorDisplayName
22517
23639
  }
22518
23640
  });
@@ -22540,6 +23662,8 @@ var DshHostConnector = class {
22540
23662
  }
22541
23663
  async #captureLocalTurns(basedOnSequence) {
22542
23664
  const state = this.#requireState();
23665
+ if (state.localOnlySessionIds?.includes(this.#host.sessionId))
23666
+ return;
22543
23667
  if (state.activeRequest !== void 0 || state.outbox.length > 0)
22544
23668
  return;
22545
23669
  const current = this.#host.currentSequence();
@@ -22556,6 +23680,7 @@ var DshHostConnector = class {
22556
23680
  input: {
22557
23681
  localTurnId: turn.localTurnId,
22558
23682
  runtimeId: runtime.id,
23683
+ contentRevision: state.contentRevision ?? 0,
22559
23684
  basedOnSequence: basedOnSequence ?? state.serverCursor,
22560
23685
  occurredAt: turn.occurredAt,
22561
23686
  observedModel: this.#config.model,
@@ -22669,7 +23794,10 @@ var DshHostConnector = class {
22669
23794
  }
22670
23795
  }
22671
23796
  });
22672
- return operations;
23797
+ return operations.map((operation) => ({
23798
+ ...operation,
23799
+ input: { ...operation.input, contentRevision: this.#requireState().activeRequest?.contentRevision ?? 0 }
23800
+ }));
22673
23801
  }
22674
23802
  async #flushOutbox(includeLocalTurns = true) {
22675
23803
  const state = this.#requireState();
@@ -22678,6 +23806,11 @@ var DshHostConnector = class {
22678
23806
  const operation = state.outbox[0];
22679
23807
  if (operation === void 0)
22680
23808
  break;
23809
+ if ((operation.input.contentRevision ?? 0) !== (state.contentRevision ?? 0) || operation.kind === "local_turn" && state.localOnlySessionIds?.includes(this.#host.sessionId)) {
23810
+ state.outbox.shift();
23811
+ await this.#stateStore.save(state);
23812
+ continue;
23813
+ }
22681
23814
  if (operation.kind === "local_turn" && !includeLocalTurns)
22682
23815
  break;
22683
23816
  if (operation.input.runtimeId !== runtime.id) {
@@ -23079,16 +24212,16 @@ function asObject3(value) {
23079
24212
  }
23080
24213
 
23081
24214
  // dist/src/dsh-compat.js
23082
- import { createHash as createHash4 } from "node:crypto";
24215
+ import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
23083
24216
  var DSH_COMPATIBILITY = Object.freeze({
23084
- tag: "dsh-v0.1.3-alpha.1",
23085
- version: "0.1.3-alpha.1",
23086
- commit: "d347e703908d0406b7a7ef80e3a0e594d86b2215",
24217
+ tag: "dsh-v0.1.7-rc.2",
24218
+ version: "0.1.7-rc.2",
24219
+ commit: "477b4f420553e8a52c2fbccc464d7561b239c443",
23087
24220
  profile: "headless"
23088
24221
  });
23089
24222
  var DSH_NPM_COMPATIBILITY = Object.freeze({
23090
24223
  package: "@deepseek-ai/dsh",
23091
- version: "0.1.2-rc.1",
24224
+ version: "0.1.7-rc.2",
23092
24225
  profile: "web",
23093
24226
  persistenceProbe: "list"
23094
24227
  });
@@ -23118,16 +24251,19 @@ function createDshHostFacade(options) {
23118
24251
  const sessionTitle = options.sessionTitle === void 0 ? void 0 : requireService(context, "sessionTitle", ["rename"]);
23119
24252
  const workspaceRegistry = options.workspaceTitle === void 0 ? void 0 : requireService(context, "workspaceRegistry", ["create"]);
23120
24253
  const eventSubscribers = /* @__PURE__ */ new Set();
24254
+ const liveSubscribers = /* @__PURE__ */ new Set();
23121
24255
  const statusSubscribers = /* @__PURE__ */ new Set();
23122
24256
  const listenerDisposers = [];
23123
24257
  const lifecycleAbort = new AbortController();
23124
24258
  let handle;
23125
24259
  let executionHandle;
23126
- let contextPreparationPromise;
24260
+ let nativeSessionId = options.sessionId;
24261
+ let contentRevision = 0;
24262
+ let contextOperationPromise;
23127
24263
  const executionBinding = JSON.stringify({ nativeSessionId: options.sessionId, ...options.contextBinding });
23128
- const executionSessionId = `gatherthread-execution-${createHash4("sha256").update(executionBinding).digest("hex").slice(0, 32)}`;
23129
- const executionOwnerId = `gatherthread-execution-owner:${createHash4("sha256").update(executionBinding).digest("hex")}`;
23130
- const executionOwnerText = JSON.stringify({
24264
+ let executionSessionId = `gatherthread-execution-${createHash4("sha256").update(executionBinding).digest("hex").slice(0, 32)}`;
24265
+ let executionOwnerId = `gatherthread-execution-owner:${createHash4("sha256").update(executionBinding).digest("hex")}`;
24266
+ let executionOwnerText = JSON.stringify({
23131
24267
  version: 1,
23132
24268
  owner: "gatherthread",
23133
24269
  native_session_id: options.sessionId,
@@ -23140,19 +24276,76 @@ function createDshHostFacade(options) {
23140
24276
  let knownProjectionMessageIds;
23141
24277
  let disposePromise;
23142
24278
  let disposed = false;
24279
+ let livePrompt;
24280
+ const emitLive = (owner, event) => {
24281
+ if (disposed || livePrompt !== owner || owner.closed)
24282
+ return;
24283
+ for (const subscriber of liveSubscribers)
24284
+ subscriber(event);
24285
+ };
23143
24286
  listenerDisposers.push(context.on("session/event", (...args) => {
23144
24287
  const session = asSession(args[0]);
23145
24288
  const event = asSessionEvent(args[1]);
23146
- if (session === void 0 || session.id !== options.sessionId && session.id !== executionHandle?.agent.session.id || event === void 0)
24289
+ if (session === void 0 || session.id !== nativeSessionId && session.id !== executionHandle?.agent.session.id || event === void 0)
23147
24290
  return;
23148
24291
  for (const subscriber of eventSubscribers)
23149
24292
  subscriber({ ...event, sourceSessionId: session.id });
24293
+ const owner = livePrompt;
24294
+ if (owner === void 0 || owner.closed || session !== owner.agent.session)
24295
+ return;
24296
+ const data = asObject4(event.data);
24297
+ if (event.type === "turn/start" && owner.turn === void 0 && Number.isSafeInteger(data?.turn)) {
24298
+ owner.turn = Number(data.turn);
24299
+ }
24300
+ if (owner.turn === void 0 || data?.turn !== void 0 && data.turn !== owner.turn)
24301
+ return;
24302
+ if (event.type === "step/start" && Number.isSafeInteger(data?.step))
24303
+ owner.step = Number(data.step);
24304
+ if (["assistant/message", "assistant/attempt", "tool/call", "tool/result", "todo/write"].includes(event.type)) {
24305
+ emitLive(owner, { kind: "session-event", sourceSessionId: session.id, event });
24306
+ }
24307
+ if (event.type === "turn/end")
24308
+ owner.closed = true;
24309
+ }, { global: true }));
24310
+ listenerDisposers.push(context.on("agent/assistant-stream", (...args) => {
24311
+ const owner = livePrompt;
24312
+ const payload = asObject4(args[0]);
24313
+ if (owner === void 0 || !owner.nativeFrames || owner.turn === void 0 || payload?.agent !== owner.agent)
24314
+ return;
24315
+ const frame = parseDshAssistantStreamFrame(payload.frame);
24316
+ if (frame === void 0 || frame.type === "start" && frame.turn !== owner.turn)
24317
+ return;
24318
+ emitLive(owner, { kind: "assistant-stream", sourceSessionId: owner.agent.session.id, frame });
24319
+ }, { global: true }));
24320
+ listenerDisposers.push(context.on("llm/stream", (...args) => {
24321
+ const request = asObject4(args[0]);
24322
+ const next = args[1];
24323
+ if (typeof next !== "function")
24324
+ return;
24325
+ const stream = next();
24326
+ const owner = livePrompt;
24327
+ if (owner === void 0 || owner.nativeFrames || owner.closed || owner.turn === void 0 || owner.step === void 0 || owner.isLoopRequest === void 0 || request === void 0 || !Object.isFrozen(args[0]) || request.sessionId !== owner.agent.session.id || request.provider !== owner.provider || request.model !== owner.model || typeof agents.get !== "function" || agents.get(owner.agent.session.id) !== owner.agent || !owner.isLoopRequest(args[0]))
24328
+ return stream;
24329
+ const attemptId = randomUUID2();
24330
+ const publish = (frame) => emitLive(owner, {
24331
+ kind: "assistant-stream",
24332
+ sourceSessionId: owner.agent.session.id,
24333
+ frame
24334
+ });
24335
+ return (async function* () {
24336
+ let index = 0;
24337
+ publish({ type: "start", attemptId, revision: ++owner.revision, turn: owner.turn, step: owner.step });
24338
+ for await (const chunk of stream) {
24339
+ publish({ type: "chunk", attemptId, revision: ++owner.revision, index: index++, time: Date.now(), chunk });
24340
+ yield chunk;
24341
+ }
24342
+ })();
23150
24343
  }, { global: true }));
23151
24344
  listenerDisposers.push(context.on("agent/status", (...args) => {
23152
24345
  const payload = asObject4(args[0]);
23153
24346
  const agent = payload ? asAgent(payload.agent) : void 0;
23154
24347
  const status = payload?.status;
23155
- if (agent === void 0 || agent.session.id !== options.sessionId && agent.session.id !== executionHandle?.agent.session.id || status !== "running" && status !== "idle")
24348
+ if (agent === void 0 || agent.session.id !== nativeSessionId && agent.session.id !== executionHandle?.agent.session.id || status !== "running" && status !== "idle")
23156
24349
  return;
23157
24350
  for (const subscriber of statusSubscribers)
23158
24351
  subscriber(status, agent.session.id);
@@ -23164,7 +24357,7 @@ function createDshHostFacade(options) {
23164
24357
  await releaseHandle();
23165
24358
  throw new Error("DSH host facade was disposed during open");
23166
24359
  }
23167
- if (acquired.agent.session.id !== options.sessionId) {
24360
+ if (acquired.agent.session.id !== nativeSessionId) {
23168
24361
  await releaseHandle();
23169
24362
  throw new Error("DSH Host returned an agent for an unexpected Session identity");
23170
24363
  }
@@ -23191,13 +24384,13 @@ function createDshHostFacade(options) {
23191
24384
  const parent = requireAgent(handle);
23192
24385
  if (parent.status !== "idle")
23193
24386
  throw new Error("Native DSH Agent must be idle before isolated context execution");
23194
- if (parent.session.header?.cwd !== options.workspacePath || agents.get?.(options.sessionId) !== parent) {
24387
+ if (parent.session.header?.cwd !== options.workspacePath || agents.get?.(nativeSessionId) !== parent) {
23195
24388
  throw new Error("Native DSH workspace or live owner does not match the isolated context binding");
23196
24389
  }
23197
24390
  };
23198
24391
  const assertExecutionOwnership = (agent) => {
23199
24392
  const session = agent.session;
23200
- if (session.id !== executionSessionId || session.header?.cwd !== options.workspacePath || session.header.parentSession !== options.sessionId || session.header.origin !== "subagent") {
24393
+ if (session.id !== executionSessionId || session.header?.cwd !== options.workspacePath || session.header.parentSession !== nativeSessionId || session.header.origin !== "subagent") {
23201
24394
  throw new Error("DSH isolated execution Session ownership does not match this native binding");
23202
24395
  }
23203
24396
  if (agents.get !== void 0 && agents.get(executionSessionId) !== agent) {
@@ -23218,6 +24411,118 @@ function createDshHostFacade(options) {
23218
24411
  throw new Error("DSH isolated execution Session contains local manual input; refusing to replace or execute it");
23219
24412
  }
23220
24413
  };
24414
+ const recordedRevision = (session) => session.snapshotEvents(0).reduce((highest, value) => {
24415
+ const event = asObject4(value), data = asObject4(event?.data);
24416
+ const id = data?.id;
24417
+ if (event?.type !== "user/message" || typeof id !== "string" || !/^gatherthread-retired:[0-9]+$/.test(id) || asObject4(data?.source)?.kind !== "plugin" || asObject4(data?.source)?.plugin !== "gatherthread")
24418
+ return highest;
24419
+ const revision = Number(id.slice("gatherthread-retired:".length));
24420
+ return Number.isSafeInteger(revision) ? Math.max(highest, revision) : highest;
24421
+ }, 0);
24422
+ const resetCanonicalContext = async (revision) => {
24423
+ if (!Number.isSafeInteger(revision) || revision < 1 || revision < contentRevision)
24424
+ throw new Error("Stale DSH content revision");
24425
+ if (options.contextBinding === void 0 || Object.values(options.contextBinding).some((value) => !value) || typeof agents.get !== "function")
24426
+ throw new Error("DSH context reset requires an explicit owned GatherThread binding");
24427
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24428
+ await open3();
24429
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24430
+ if (promptActive || projectionActive)
24431
+ throw new Error("Wait for the active DSH turn before replacing its projection");
24432
+ const parent = requireAgent(handle);
24433
+ if (revision < recordedRevision(parent.session))
24434
+ throw new Error("Retired DSH revision cannot resume");
24435
+ assertExecutionParentIdle();
24436
+ const targetId = `gatherthread-projection-${createHash4("sha256").update(`${executionBinding}:${revision}`).digest("hex").slice(0, 32)}`;
24437
+ if (nativeSessionId === targetId && contentRevision === revision)
24438
+ return { sessionId: targetId };
24439
+ const ownerId = `gatherthread-projection-owner:${createHash4("sha256").update(`${executionBinding}:${revision}`).digest("hex")}`;
24440
+ const ownerText = JSON.stringify({ version: 1, binding: options.contextBinding, native_session_id: options.sessionId, content_revision: revision });
24441
+ projectionActive = true;
24442
+ let candidate;
24443
+ try {
24444
+ const retired = await createIsolatedMessage(`gatherthread-retired:${revision}`, "GatherThread retired this context. Continue here locally only.", options);
24445
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24446
+ if (recordedRevision(parent.session) < revision) {
24447
+ parent.session.append("user/message", retired, { surfaceOp: "append" });
24448
+ await sessions.flush(parent.session);
24449
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24450
+ }
24451
+ if (agents.get?.(targetId) !== void 0)
24452
+ throw new Error("DSH clean projection already has another live owner");
24453
+ const stored = await hasPersistedSession(persistence, targetId, lifecycleAbort.signal);
24454
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24455
+ const presets = asObject4(context.get("agentPresets"));
24456
+ const setup = (ctx) => {
24457
+ if (presets !== void 0) {
24458
+ if (typeof presets.composeFrom !== "function" || typeof presets.composedPreset !== "function")
24459
+ throw new Error("Native DSH tool inheritance unavailable");
24460
+ const expected = presets.composedPreset(parent.ctx);
24461
+ if (presets.composeFrom(ctx, parent.ctx) !== expected)
24462
+ throw new Error("DSH clean projection did not inherit native tools");
24463
+ }
24464
+ };
24465
+ candidate = await (stored ? agents.resume({
24466
+ resumeSessionId: targetId,
24467
+ agentOptions: { provider: options.provider, model: options.model },
24468
+ signal: lifecycleAbort.signal,
24469
+ setup
24470
+ }) : agents.create({
24471
+ sessionId: targetId,
24472
+ meta: { cwd: options.workspacePath, parentSession: options.sessionId, origin: "subagent" },
24473
+ agentOptions: { provider: options.provider, model: options.model },
24474
+ signal: lifecycleAbort.signal,
24475
+ setup
24476
+ }));
24477
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24478
+ const agent = candidate.agent;
24479
+ if (agent.session.id !== targetId || agent.session.header?.cwd !== options.workspacePath || agent.status !== "idle" || agent.session.header.parentSession !== options.sessionId || agent.session.header.origin !== "subagent" || agents.get?.(targetId) !== agent)
24480
+ throw new Error("DSH clean projection ownership is invalid");
24481
+ if (!stored) {
24482
+ if (agent.session.seq !== 0)
24483
+ throw new Error("DSH clean projection is not fresh");
24484
+ const owner = await createIsolatedMessage(ownerId, ownerText, options);
24485
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24486
+ agent.session.append("user/message", owner, { surfaceOp: "append" });
24487
+ }
24488
+ const events = agent.session.snapshotEvents(0).map(asObject4);
24489
+ if (!events.some((event) => {
24490
+ const data = asObject4(event?.data), source = asObject4(data?.source);
24491
+ return event?.type === "user/message" && data?.id === ownerId && source?.kind === "plugin" && source.plugin === "gatherthread" && Array.isArray(data?.content) && data.content.length === 1 && asObject4(data.content[0])?.text === ownerText;
24492
+ })) {
24493
+ throw new Error("DSH clean projection is missing its durable owner marker");
24494
+ }
24495
+ await sessions.flush(agent.session);
24496
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24497
+ if (sessionTitle && options.sessionTitle) {
24498
+ await sessionTitle.rename(agent.session, options.sessionTitle);
24499
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24500
+ }
24501
+ if (workspaceRegistry && options.workspaceTitle) {
24502
+ const workspace = await workspaceRegistry.create(options.workspacePath, options.workspaceTitle);
24503
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24504
+ await workspace.attachSession(targetId);
24505
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24506
+ }
24507
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24508
+ await releaseExecutionHandle();
24509
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24510
+ await releaseHandle();
24511
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24512
+ handle = candidate;
24513
+ candidate = void 0;
24514
+ nativeSessionId = targetId;
24515
+ contentRevision = revision;
24516
+ knownProjectionMessageIds = void 0;
24517
+ return { sessionId: targetId };
24518
+ } finally {
24519
+ try {
24520
+ await candidate?.dispose();
24521
+ } finally {
24522
+ projectionActive = false;
24523
+ }
24524
+ }
24525
+ };
23221
24526
  const prepareContextExecution = async (input2) => {
23222
24527
  if (disposed)
23223
24528
  throw new Error("DSH host facade is disposed");
@@ -23238,6 +24543,30 @@ function createDshHostFacade(options) {
23238
24543
  if (disposed || promptActive || projectionActive)
23239
24544
  throw new Error("DSH host facade permits only one active write");
23240
24545
  const parent = requireAgent(handle);
24546
+ const revision = historyContext.content_revision ?? 0;
24547
+ if (revision < Math.max(contentRevision, recordedRevision(parent.session)))
24548
+ throw new Error("Stale retired DSH context revision");
24549
+ if (revision !== contentRevision || revision > 0 && !executionSessionId.endsWith(createHash4("sha256").update(`${executionBinding}:${revision}`).digest("hex").slice(0, 32))) {
24550
+ await releaseExecutionHandle();
24551
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24552
+ contentRevision = revision;
24553
+ const binding = `${executionBinding}:${revision}`;
24554
+ executionSessionId = `gatherthread-execution-${createHash4("sha256").update(binding).digest("hex").slice(0, 32)}`;
24555
+ executionOwnerId = `gatherthread-execution-owner:${createHash4("sha256").update(binding).digest("hex")}`;
24556
+ executionOwnerText = JSON.stringify({
24557
+ version: 1,
24558
+ owner: "gatherthread",
24559
+ native_session_id: options.sessionId,
24560
+ execution_session_id: executionSessionId,
24561
+ binding: options.contextBinding,
24562
+ content_revision: revision
24563
+ });
24564
+ const marker = await createIsolatedMessage(`gatherthread-retired:${revision}`, "GatherThread previous execution context is local only.", options);
24565
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24566
+ parent.session.append("user/message", marker, { surfaceOp: "append" });
24567
+ await sessions.flush(parent.session);
24568
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
24569
+ }
23241
24570
  assertExecutionParentIdle();
23242
24571
  const presets = asObject4(context.get("agentPresets"));
23243
24572
  let parentPreset;
@@ -23246,7 +24575,8 @@ function createDshHostFacade(options) {
23246
24575
  throw new Error("Pinned DSH public preset inheritance API is unavailable; refusing an isolated Agent without native tools");
23247
24576
  }
23248
24577
  parentPreset = presets.composedPreset(parent.ctx);
23249
- if (parentPreset === void 0 && (!Array.isArray(presets.roots) || presets.roots.length > 0)) {
24578
+ const roots = Array.isArray(presets.roots) ? presets.roots : void 0;
24579
+ if (parentPreset === void 0 && roots !== void 0 && roots.length > 0) {
23250
24580
  throw new Error("Native DSH Agent has no composed preset; restore its tool composition before using summarized context");
23251
24581
  }
23252
24582
  }
@@ -23280,7 +24610,7 @@ function createDshHostFacade(options) {
23280
24610
  sessionId: executionSessionId,
23281
24611
  meta: {
23282
24612
  cwd: options.workspacePath,
23283
- parentSession: options.sessionId,
24613
+ parentSession: nativeSessionId,
23284
24614
  origin: "subagent",
23285
24615
  ...parentPreset === void 0 ? {} : { agentPreset: parentPreset }
23286
24616
  },
@@ -23294,7 +24624,7 @@ function createDshHostFacade(options) {
23294
24624
  }
23295
24625
  const agent2 = operationAgent(executionSessionId);
23296
24626
  if (!stored) {
23297
- if (agent2.session.id !== executionSessionId || agent2.session.seq !== 0 || agent2.session.header?.parentSession !== options.sessionId || agent2.session.header.origin !== "subagent" || agent2.session.header.cwd !== options.workspacePath || agent2.status !== "idle") {
24627
+ if (agent2.session.id !== executionSessionId || agent2.session.seq !== 0 || agent2.session.header?.parentSession !== nativeSessionId || agent2.session.header.origin !== "subagent" || agent2.session.header.cwd !== options.workspacePath || agent2.status !== "idle") {
23298
24628
  throw new Error("DSH did not create a fresh, owned isolated execution Session");
23299
24629
  }
23300
24630
  const ownerMessage = await createIsolatedMessage(executionOwnerId, executionOwnerText, options);
@@ -23330,7 +24660,7 @@ ${JSON.stringify(historyContext.items)}`;
23330
24660
  const nodes = agent.session.surface?.nodes;
23331
24661
  if (!Array.isArray(nodes) || nodes.some((seq) => !Number.isSafeInteger(seq) || seq < 0 || seq >= agent.session.seq) || new Set(nodes).size !== nodes.length)
23332
24662
  throw new Error("Pinned DSH public Session surface API is unavailable or invalid");
23333
- agent.session.append("user/message", message, nodes.length === 0 ? { surfaceOp: "append" } : { surfaceOp: { op: "replace", start: nodes[0], end: nodes.at(-1) }, sourceEventSeqs: [...nodes] });
24663
+ agent.session.append("user/message", message, nodes.length === 0 ? { surfaceOp: "append" } : { surfaceOp: { op: "replace", startSeq: nodes[0], endSeq: nodes.at(-1) }, sourceEventSeqs: [...nodes] });
23334
24664
  }
23335
24665
  await sessions.flush(agent.session);
23336
24666
  throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
@@ -23339,11 +24669,11 @@ ${JSON.stringify(historyContext.items)}`;
23339
24669
  projectionActive = false;
23340
24670
  }
23341
24671
  };
23342
- const setupNativeAgent = async (agentContext) => {
24672
+ const setupNativeAgent = async (agentContext, agentValue) => {
23343
24673
  const presets = asObject4(context.get("agentPresets"));
23344
24674
  if (presets === void 0 || Array.isArray(presets.roots) && presets.roots.length === 0)
23345
24675
  return;
23346
- const agent = asAgent(asObject4(agentContext)?.agent);
24676
+ const agent = asAgent(agentValue);
23347
24677
  const projections = asObject4(context.get("sessionProjections"));
23348
24678
  if (agent === void 0 || typeof presets.mount !== "function" || typeof projections?.stateOf !== "function") {
23349
24679
  throw new Error("Pinned DSH public native preset composition API is unavailable");
@@ -23446,7 +24776,8 @@ ${JSON.stringify(historyContext.items)}`;
23446
24776
  return parsed;
23447
24777
  });
23448
24778
  };
23449
- const prompt = async (text, requestedSelection, requestedExecutionId) => {
24779
+ const prompt = async (text, requestedSelection, requestedExecutionId, signal) => {
24780
+ signal?.throwIfAborted();
23450
24781
  if (disposed)
23451
24782
  throw new Error("DSH host facade is disposed");
23452
24783
  if (!text.trim())
@@ -23461,11 +24792,15 @@ ${JSON.stringify(historyContext.items)}`;
23461
24792
  promptActive = true;
23462
24793
  let disposeSelection;
23463
24794
  let selectionRef;
24795
+ let abortPrompt;
23464
24796
  try {
23465
24797
  if (requestedExecutionId === void 0)
23466
24798
  await open3();
23467
24799
  throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
23468
24800
  const agent = operationAgent(requestedExecutionId);
24801
+ signal?.throwIfAborted();
24802
+ if (signal && typeof agent.cancel !== "function")
24803
+ throw new Error("DSH public cancel API is required for deletion-safe execution");
23469
24804
  if (requestedExecutionId !== void 0) {
23470
24805
  assertExecutionParentIdle();
23471
24806
  assertExecutionOwnership(agent);
@@ -23491,8 +24826,41 @@ ${JSON.stringify(historyContext.items)}`;
23491
24826
  assertExecutionParentIdle();
23492
24827
  assertExecutionOwnership(agent);
23493
24828
  }
24829
+ if (liveSubscribers.size > 0) {
24830
+ let imported;
24831
+ try {
24832
+ imported = asObject4(await (options.moduleImporter ?? importDshModule)(USER_MESSAGE_MODULE));
24833
+ } catch {
24834
+ }
24835
+ throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
24836
+ if (agent.status !== "idle" || agent.session.seq !== fromSequence)
24837
+ throw new Error("DSH Agent changed while preparing live output");
24838
+ livePrompt = {
24839
+ agent,
24840
+ closed: false,
24841
+ revision: 0,
24842
+ nativeFrames: typeof imported?.expandAssistantStream === "function",
24843
+ ...typeof imported?.isAgentLoopRequest === "function" ? { isLoopRequest: imported.isAgentLoopRequest } : {},
24844
+ provider: requestedSelection?.provider ?? options.provider,
24845
+ model: requestedSelection?.model ?? options.model
24846
+ };
24847
+ }
24848
+ signal?.throwIfAborted();
23494
24849
  agent.followup(message);
24850
+ abortPrompt = () => {
24851
+ livePrompt = void 0;
24852
+ if (typeof agent.cancel === "function")
24853
+ agent.cancel({ kind: "user" });
24854
+ else if (requestedExecutionId !== void 0)
24855
+ void releaseExecutionHandle();
24856
+ else
24857
+ void releaseHandle();
24858
+ };
24859
+ signal?.addEventListener("abort", abortPrompt, { once: true });
24860
+ if (signal?.aborted)
24861
+ abortPrompt();
23495
24862
  await agent.whenIdle();
24863
+ signal?.throwIfAborted();
23496
24864
  throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
23497
24865
  await sessions.flush(agent.session);
23498
24866
  throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
@@ -23503,11 +24871,14 @@ ${JSON.stringify(historyContext.items)}`;
23503
24871
  events: snapshotFrom(fromSequence, requestedExecutionId)
23504
24872
  };
23505
24873
  } finally {
24874
+ if (abortPrompt)
24875
+ signal?.removeEventListener("abort", abortPrompt);
23506
24876
  if (selectionRef !== void 0) {
23507
24877
  selectionRef.current = void 0;
23508
24878
  selectionRef.assembled = void 0;
23509
24879
  }
23510
24880
  disposeSelection?.();
24881
+ livePrompt = void 0;
23511
24882
  promptActive = false;
23512
24883
  }
23513
24884
  };
@@ -23571,7 +24942,7 @@ ${JSON.stringify(historyContext.items)}`;
23571
24942
  } catch {
23572
24943
  }
23573
24944
  try {
23574
- await contextPreparationPromise;
24945
+ await contextOperationPromise;
23575
24946
  } catch {
23576
24947
  }
23577
24948
  try {
@@ -23586,20 +24957,33 @@ ${JSON.stringify(historyContext.items)}`;
23586
24957
  return disposePromise;
23587
24958
  };
23588
24959
  return {
23589
- sessionId: options.sessionId,
24960
+ get sessionId() {
24961
+ return nativeSessionId;
24962
+ },
24963
+ ...options.contextBinding === void 0 ? {} : { contextDeletionVersion: 1 },
24964
+ resetCanonicalContext(revision) {
24965
+ if (contextOperationPromise !== void 0)
24966
+ return Promise.reject(new Error("DSH host facade permits only one active context operation"));
24967
+ const operation = resetCanonicalContext(revision);
24968
+ contextOperationPromise = operation;
24969
+ return operation.finally(() => {
24970
+ if (contextOperationPromise === operation)
24971
+ contextOperationPromise = void 0;
24972
+ });
24973
+ },
23590
24974
  open: open3,
23591
24975
  currentSequence(requestedExecutionId) {
23592
24976
  return operationAgent(requestedExecutionId).session.seq;
23593
24977
  },
23594
24978
  snapshotFrom,
23595
24979
  prepareContextExecution(input2) {
23596
- if (contextPreparationPromise !== void 0)
24980
+ if (contextOperationPromise !== void 0)
23597
24981
  return Promise.reject(new Error("DSH host facade permits only one active context preparation"));
23598
24982
  const operation = prepareContextExecution(input2);
23599
- contextPreparationPromise = operation;
24983
+ contextOperationPromise = operation;
23600
24984
  return operation.finally(() => {
23601
- if (contextPreparationPromise === operation)
23602
- contextPreparationPromise = void 0;
24985
+ if (contextOperationPromise === operation)
24986
+ contextOperationPromise = void 0;
23603
24987
  });
23604
24988
  },
23605
24989
  projectCanonicalEvents,
@@ -23611,6 +24995,12 @@ ${JSON.stringify(historyContext.items)}`;
23611
24995
  eventSubscribers.add(listener);
23612
24996
  return () => eventSubscribers.delete(listener);
23613
24997
  },
24998
+ onLiveOutput(listener) {
24999
+ if (disposed)
25000
+ throw new Error("DSH host facade is disposed");
25001
+ liveSubscribers.add(listener);
25002
+ return () => liveSubscribers.delete(listener);
25003
+ },
23614
25004
  onStatus(listener) {
23615
25005
  if (disposed)
23616
25006
  throw new Error("DSH host facade is disposed");
@@ -23660,8 +25050,11 @@ async function createProjectionMessage(projection, options) {
23660
25050
  });
23661
25051
  }
23662
25052
  function formatProjectionText(projection) {
23663
- if (projection.role === "user")
23664
- return projection.content;
25053
+ if (projection.role === "user") {
25054
+ const sender = projection.actorDisplayName?.replace(/[\p{Cc}\p{Cf}【】]+/gu, " ").replace(/\s+/gu, " ").trim();
25055
+ return sender ? `\u3010${sender} \xB7 GatherThread\u3011
25056
+ ${projection.content}` : projection.content;
25057
+ }
23665
25058
  const route = [projection.provider, projection.model].filter(Boolean).join(" / ");
23666
25059
  const attribution = [projection.actorDisplayName, route].filter(Boolean).join(" \xB7 ");
23667
25060
  return `[GatherThread remote Agent reply${attribution ? ` \xB7 ${attribution}` : ""}]
@@ -23826,7 +25219,7 @@ function asObject4(value) {
23826
25219
  }
23827
25220
 
23828
25221
  // dist/src/state-store.js
23829
- import { randomUUID } from "node:crypto";
25222
+ import { randomUUID as randomUUID3 } from "node:crypto";
23830
25223
  import { constants } from "node:fs";
23831
25224
  import { lstat as lstat3, mkdir, open as open2, rename, unlink } from "node:fs/promises";
23832
25225
  import path3 from "node:path";
@@ -23881,7 +25274,7 @@ var FileConnectorStateStore = class {
23881
25274
  const targetBefore = await optionalLstat(this.#path);
23882
25275
  if (targetBefore !== void 0)
23883
25276
  assertPrivateRegularFile(targetBefore, "DSH connector state");
23884
- const temporaryPath = `${this.#path}.tmp-${process.pid}-${randomUUID()}`;
25277
+ const temporaryPath = `${this.#path}.tmp-${process.pid}-${randomUUID3()}`;
23885
25278
  const handle = await open2(temporaryPath, "wx", 384);
23886
25279
  try {
23887
25280
  await handle.writeFile(`${JSON.stringify(validated, null, 2)}
@@ -23921,7 +25314,10 @@ function validateConnectorState(value) {
23921
25314
  "publishedDshSequence",
23922
25315
  ...legacyUploadPolicy ? [] : ["automaticUpload"],
23923
25316
  "activeRequest",
23924
- "outbox"
25317
+ "outbox",
25318
+ "contentRevision",
25319
+ "projectionSessionId",
25320
+ "localOnlySessionIds"
23925
25321
  ]), "state");
23926
25322
  if (state.version !== 1 && state.version !== 2 && state.version !== 3) {
23927
25323
  throw new Error("Unsupported DSH connector state version");
@@ -23936,6 +25332,9 @@ function validateConnectorState(value) {
23936
25332
  throw new Error("state.outbox must be an array");
23937
25333
  const outbox = state.outbox.map(parseOutboxOperation);
23938
25334
  const validated = {
25335
+ ...state.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(state.contentRevision, "state.contentRevision") },
25336
+ ...state.projectionSessionId === void 0 ? {} : { projectionSessionId: safeString(state.projectionSessionId, "state.projectionSessionId", 128) },
25337
+ ...state.localOnlySessionIds === void 0 ? {} : { localOnlySessionIds: parseRetiredSessionIds(state.localOnlySessionIds) },
23939
25338
  version: 3,
23940
25339
  binding: {
23941
25340
  projectId: safeString(binding.projectId, "state.binding.projectId", 128),
@@ -23954,8 +25353,9 @@ function validateConnectorState(value) {
23954
25353
  }
23955
25354
  function parseActiveRequest(value) {
23956
25355
  const active = requiredObject3(value, "state.activeRequest");
23957
- exactKeys(active, /* @__PURE__ */ new Set(["requestId", "requestSequence", "dshFromSequence", "dshToSequence", "promptDigest", "claimAttempt", "contextExecution"]), "state.activeRequest");
25356
+ exactKeys(active, /* @__PURE__ */ new Set(["requestId", "requestSequence", "dshFromSequence", "dshToSequence", "promptDigest", "claimAttempt", "contextExecution", "contentRevision"]), "state.activeRequest");
23958
25357
  const parsed = {
25358
+ ...active.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(active.contentRevision, "state.activeRequest.contentRevision") },
23959
25359
  requestId: safeString(active.requestId, "state.activeRequest.requestId", 128),
23960
25360
  requestSequence: positiveInteger(active.requestSequence, "state.activeRequest.requestSequence"),
23961
25361
  dshFromSequence: nonNegativeInteger(active.dshFromSequence, "state.activeRequest.dshFromSequence"),
@@ -24031,7 +25431,8 @@ function parseLocalTurnInput(value, label) {
24031
25431
  "observedReasoningEffort",
24032
25432
  "requestPayload",
24033
25433
  "responsePayload",
24034
- "toolEvents"
25434
+ "toolEvents",
25435
+ "contentRevision"
24035
25436
  ]), label);
24036
25437
  const occurredAt = safeString(input2.occurredAt, `${label}.occurredAt`, 64);
24037
25438
  if (!Number.isFinite(Date.parse(occurredAt)))
@@ -24041,6 +25442,7 @@ function parseLocalTurnInput(value, label) {
24041
25442
  }
24042
25443
  return {
24043
25444
  localTurnId: safeString(input2.localTurnId, `${label}.localTurnId`, 200),
25445
+ ...input2.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(input2.contentRevision, `${label}.contentRevision`) },
24044
25446
  runtimeId: safeString(input2.runtimeId, `${label}.runtimeId`, 128),
24045
25447
  basedOnSequence: nonNegativeInteger(input2.basedOnSequence, `${label}.basedOnSequence`),
24046
25448
  occurredAt,
@@ -24068,13 +25470,15 @@ function parseAppendInput(value, label) {
24068
25470
  "runtimeId",
24069
25471
  "claimAttempt",
24070
25472
  "observedModel",
24071
- "observedReasoningEffort"
25473
+ "observedReasoningEffort",
25474
+ "contentRevision"
24072
25475
  ]), label);
24073
25476
  if (input2.type !== "tool_call" && input2.type !== "tool_result") {
24074
25477
  throw new Error(`${label}.type must be tool_call or tool_result`);
24075
25478
  }
24076
25479
  return {
24077
25480
  type: input2.type,
25481
+ ...input2.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(input2.contentRevision, `${label}.contentRevision`) },
24078
25482
  idempotencyKey: safeString(input2.idempotencyKey, `${label}.idempotencyKey`, 200),
24079
25483
  payload: jsonValue(input2.payload, `${label}.payload`),
24080
25484
  ...input2.replyTo === void 0 ? {} : { replyTo: safeString(input2.replyTo, `${label}.replyTo`, 128) },
@@ -24091,9 +25495,10 @@ function parseAppendInput(value, label) {
24091
25495
  }
24092
25496
  function parseCompletionInput(value, label) {
24093
25497
  const input2 = requiredObject3(value, label);
24094
- exactKeys(input2, /* @__PURE__ */ new Set(["runtimeId", "claimAttempt", "idempotencyKey", "payload", "observedModel", "observedReasoningEffort"]), label);
25498
+ exactKeys(input2, /* @__PURE__ */ new Set(["runtimeId", "claimAttempt", "idempotencyKey", "payload", "observedModel", "observedReasoningEffort", "contentRevision"]), label);
24095
25499
  return {
24096
25500
  runtimeId: safeString(input2.runtimeId, `${label}.runtimeId`, 128),
25501
+ ...input2.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(input2.contentRevision, `${label}.contentRevision`) },
24097
25502
  ...input2.claimAttempt === void 0 ? {} : {
24098
25503
  claimAttempt: positiveInteger(input2.claimAttempt, `${label}.claimAttempt`)
24099
25504
  },
@@ -24105,6 +25510,11 @@ function parseCompletionInput(value, label) {
24105
25510
  }
24106
25511
  };
24107
25512
  }
25513
+ function parseRetiredSessionIds(value) {
25514
+ if (!Array.isArray(value) || value.length > 4096 || new Set(value).size !== value.length)
25515
+ throw new Error("Invalid DSH retired Session identities");
25516
+ return value.map((id, index) => safeString(id, `state.localOnlySessionIds[${index}]`, 128));
25517
+ }
24108
25518
  function assertAlreadyRedacted(state) {
24109
25519
  const encoded = JSON.stringify(state);
24110
25520
  const redacted = JSON.stringify(redactValue(state));
@@ -24477,6 +25887,27 @@ var DshProjectManager = class {
24477
25887
  for (const error62 of permissions.errors)
24478
25888
  this.#reportError(error62);
24479
25889
  const eligibleSessions = [...permissions.eligibleSessions];
25890
+ const sessionUpdateErrors = [];
25891
+ for (const session of eligibleSessions) {
25892
+ const binding = this.#managed.get(session.id);
25893
+ if (binding?.phase === "active" && !binding.connector.stopped) {
25894
+ try {
25895
+ binding.connector.updateSessionSummary(session);
25896
+ } catch (error62) {
25897
+ this.#managed.delete(session.id);
25898
+ try {
25899
+ await binding.connector.stop();
25900
+ } catch (stopError) {
25901
+ this.#reportError(publicError2(stopError, "DSH Session connector cleanup failed"));
25902
+ }
25903
+ if (!this.#stopped)
25904
+ this.#recordFailure(session.id);
25905
+ const failure2 = publicError2(error62, `DSH Session ${session.id} mode refresh failed`);
25906
+ sessionUpdateErrors.push(failure2);
25907
+ this.#reportError(failure2);
25908
+ }
25909
+ }
25910
+ }
24480
25911
  if (this.#discoverLocalSessions !== void 0) {
24481
25912
  try {
24482
25913
  const candidates2 = await this.#discoverLocalSessions();
@@ -24520,7 +25951,7 @@ var DshProjectManager = class {
24520
25951
  status: "updated",
24521
25952
  eligibleSessionIds: [...eligibleIds].sort(),
24522
25953
  activeSessionIds: this.activeSessionIds(),
24523
- errors: [...permissions.errors, ...attachErrors]
25954
+ errors: [...permissions.errors, ...sessionUpdateErrors, ...attachErrors]
24524
25955
  };
24525
25956
  this.#notifyStatus({
24526
25957
  state: "connected",
@@ -25030,6 +26461,7 @@ function createManagedConnector(options) {
25030
26461
  get stopped() {
25031
26462
  return connector.stopped;
25032
26463
  },
26464
+ updateSessionSummary: (session) => connector.updateSessionSummary(session),
25033
26465
  async start() {
25034
26466
  try {
25035
26467
  await connector.start();