@gatherthread/dsh-host 0.1.0-beta.1 → 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.
@@ -729,9 +729,9 @@ function floatSafeRemainder(val, step) {
729
729
  return ratio - roundedRatio;
730
730
  }
731
731
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
732
- function defineLazy(object2, key, getter) {
732
+ function defineLazy(object3, key, getter) {
733
733
  let value = void 0;
734
- Object.defineProperty(object2, key, {
734
+ Object.defineProperty(object3, key, {
735
735
  get() {
736
736
  if (value === EVALUATING) {
737
737
  return void 0;
@@ -743,7 +743,7 @@ function defineLazy(object2, key, getter) {
743
743
  return value;
744
744
  },
745
745
  set(v) {
746
- Object.defineProperty(object2, key, {
746
+ Object.defineProperty(object3, key, {
747
747
  value: v
748
748
  // configurable: true,
749
749
  });
@@ -15810,8 +15810,8 @@ function foldObjects(members2) {
15810
15810
  }
15811
15811
  const properties = {};
15812
15812
  const required2 = /* @__PURE__ */ new Set();
15813
- for (const object2 of objects) {
15814
- for (const key in object2.properties) {
15813
+ for (const object3 of objects) {
15814
+ for (const key in object3.properties) {
15815
15815
  if (Object.prototype.hasOwnProperty.call(properties, key))
15816
15816
  continue;
15817
15817
  const parts = [];
@@ -15825,18 +15825,18 @@ function foldObjects(members2) {
15825
15825
  const merged = parts.length === 1 ? parts[0] : foldObjects(parts) ?? { allOf: parts };
15826
15826
  assignProp(properties, key, merged);
15827
15827
  }
15828
- for (const key of object2.required ?? [])
15828
+ for (const key of object3.required ?? [])
15829
15829
  required2.add(key);
15830
15830
  }
15831
15831
  const folded = { type: "object", properties };
15832
15832
  if (required2.size)
15833
15833
  folded.required = [...required2];
15834
- if (objects.every((object2) => object2.additionalProperties === false)) {
15834
+ if (objects.every((object3) => object3.additionalProperties === false)) {
15835
15835
  folded.additionalProperties = false;
15836
15836
  } else {
15837
15837
  const constraints = [];
15838
- for (const object2 of objects) {
15839
- const constraint = undeclaredConstraint(object2);
15838
+ for (const object3 of objects) {
15839
+ const constraint = undeclaredConstraint(object3);
15840
15840
  if (constraint && !constraints.some((seen) => JSON.stringify(seen) === JSON.stringify(constraint)))
15841
15841
  constraints.push(constraint);
15842
15842
  }
@@ -19675,6 +19675,28 @@ function date4(params) {
19675
19675
  return _coercedDate(ZodDate, params);
19676
19676
  }
19677
19677
 
19678
+ // ../protocol/dist/src/live-output.js
19679
+ var utf8 = (maximum) => external_exports.string().refine((value) => new TextEncoder().encode(value).length <= maximum, "Live output is too large");
19680
+ var LiveOutputPayloadSchema = external_exports.object({
19681
+ content: utf8(24 * 1024),
19682
+ phase: external_exports.literal("stream"),
19683
+ stream_id: external_exports.string().uuid(),
19684
+ stream_mode: external_exports.literal("snapshot"),
19685
+ stream_kind: external_exports.enum(["answer", "reasoning", "tool", "plan"]),
19686
+ stream_revision: external_exports.number().int().min(1).max(1200),
19687
+ stream_state: external_exports.enum(["running", "completed", "failed"]),
19688
+ title: utf8(256).optional(),
19689
+ plan: external_exports.array(external_exports.object({ step: utf8(512), status: external_exports.enum(["pending", "in_progress", "completed"]) }).strict()).max(64).optional(),
19690
+ status: external_exports.enum(["thinking", "running"]).optional(),
19691
+ occurred_at: external_exports.string().datetime().optional(),
19692
+ capture_fidelity: external_exports.literal("harness_transcript").optional(),
19693
+ source_harness: external_exports.string().min(1).max(80).optional()
19694
+ }).strict().superRefine((value, context) => {
19695
+ if (value.stream_kind === "plan" !== (value.plan !== void 0)) {
19696
+ context.addIssue({ code: "custom", message: "Only plan snapshots carry plan steps" });
19697
+ }
19698
+ });
19699
+
19678
19700
  // ../protocol/dist/src/code-sync.js
19679
19701
  var CODE_SYNC_MAX_FILES = 1e3;
19680
19702
  var CODE_SYNC_MAX_FILE_BYTES = 2 * 1024 * 1024;
@@ -19852,6 +19874,118 @@ var githubCodeSyncRequestKinds = [
19852
19874
  "github_code_update"
19853
19875
  ];
19854
19876
 
19877
+ // ../protocol/dist/src/registration.js
19878
+ 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));
19879
+ var Label = external_exports.string().regex(/^[^\u0000-\u001f\u007f-\u009f]*$/u).trim().min(1).max(120);
19880
+ var SendRegistrationInputSchema = external_exports.object({
19881
+ email: RegistrationEmailSchema,
19882
+ challenge_token: external_exports.string().min(1).max(2048),
19883
+ idempotency_key: external_exports.string().uuid(),
19884
+ locale: external_exports.enum(["en", "zh-CN"])
19885
+ }).strict();
19886
+ var AccountPasswordSchema = external_exports.string().min(8).max(128).refine((value) => new TextEncoder().encode(value).byteLength <= 512);
19887
+ var EmailLoginInputSchema = external_exports.object({
19888
+ email: RegistrationEmailSchema,
19889
+ password: AccountPasswordSchema,
19890
+ device_name: Label,
19891
+ remember_device: external_exports.boolean().default(false)
19892
+ }).strict();
19893
+ 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));
19894
+ var CreateCodexLauncherAuthorizationInputSchema = external_exports.object({
19895
+ project_id: LauncherProjectId,
19896
+ email: RegistrationEmailSchema
19897
+ }).strict();
19898
+ var ClaimCodexLauncherAuthorizationInputSchema = external_exports.object({
19899
+ authorization_id: external_exports.string().uuid().toLowerCase(),
19900
+ project_id: LauncherProjectId,
19901
+ email: RegistrationEmailSchema,
19902
+ password: AccountPasswordSchema,
19903
+ device_name: Label
19904
+ }).strict();
19905
+ var VerifyRegistrationInputSchema = external_exports.object({
19906
+ registration_id: external_exports.string().uuid(),
19907
+ code: external_exports.string().regex(/^\d{8}$/),
19908
+ display_name: Label,
19909
+ device_name: Label,
19910
+ remember_device: external_exports.boolean().default(false),
19911
+ privacy_acknowledged: external_exports.literal(true),
19912
+ password: AccountPasswordSchema
19913
+ }).strict();
19914
+ var RegistrationStatusSchema = external_exports.object({
19915
+ enabled: external_exports.boolean(),
19916
+ site_key: external_exports.string().nullable(),
19917
+ challenge_binding: external_exports.string().nullable()
19918
+ }).strict();
19919
+ var RegistrationSentSchema = external_exports.object({
19920
+ registration_id: external_exports.string().uuid(),
19921
+ expires_in_seconds: external_exports.literal(600),
19922
+ resend_after_seconds: external_exports.literal(60)
19923
+ }).strict();
19924
+ var PasswordResetSentSchema = external_exports.object({
19925
+ reset_id: external_exports.string().uuid(),
19926
+ expires_in_seconds: external_exports.literal(600),
19927
+ resend_after_seconds: external_exports.literal(60)
19928
+ }).strict();
19929
+ var VerifyPasswordResetInputSchema = external_exports.object({
19930
+ reset_id: external_exports.string().uuid(),
19931
+ email: RegistrationEmailSchema,
19932
+ code: external_exports.string().regex(/^\d{8}$/),
19933
+ password: AccountPasswordSchema,
19934
+ password_confirmation: AccountPasswordSchema,
19935
+ locale: external_exports.enum(["en", "zh-CN"])
19936
+ }).strict().refine((value) => value.password === value.password_confirmation);
19937
+ var EmailAccountSessionSchema = external_exports.object({
19938
+ 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(),
19939
+ expires_at: external_exports.string().datetime()
19940
+ }).strict();
19941
+
19942
+ // ../protocol/dist/src/cloud-api.js
19943
+ var CloudApiProviderIdSchema = external_exports.enum(["openai", "anthropic", "deepseek", "siliconflow-cn", "siliconflow-global", "openrouter", "qwen", "glm", "doubao"]);
19944
+ var CloudApiModelSchema = external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u0020\u007f-\u009f]+$/u);
19945
+ var Label2 = external_exports.string().trim().min(1).max(80).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u);
19946
+ var CloudApiPutInputSchema = external_exports.object({
19947
+ expected_revision: external_exports.string().uuid().nullable(),
19948
+ provider_id: CloudApiProviderIdSchema,
19949
+ label: Label2,
19950
+ model: CloudApiModelSchema,
19951
+ enabled: external_exports.boolean(),
19952
+ api_key: external_exports.string().min(8).max(4096).regex(/^[\x21-\x7e]+$/u).optional()
19953
+ }).strict();
19954
+ var CloudApiDeleteInputSchema = external_exports.object({ expected_revision: external_exports.string().uuid() }).strict();
19955
+ var CloudApiConfigurationSchema = external_exports.object({
19956
+ id: external_exports.string().uuid(),
19957
+ revision: external_exports.string().uuid(),
19958
+ provider_id: CloudApiProviderIdSchema,
19959
+ profile_id: external_exports.string().regex(/^api-[0-9a-f-]{36}$/u),
19960
+ label: Label2,
19961
+ model: CloudApiModelSchema,
19962
+ enabled: external_exports.boolean(),
19963
+ has_key: external_exports.literal(true),
19964
+ updated_at: external_exports.string().datetime()
19965
+ }).strict();
19966
+ var CloudApiProviderSchema = external_exports.object({
19967
+ id: CloudApiProviderIdSchema,
19968
+ label: external_exports.string().max(80),
19969
+ transport: external_exports.enum(["openai-chat", "anthropic-messages"]),
19970
+ base_url: external_exports.string().url().max(200),
19971
+ docs_url: external_exports.string().url().max(300),
19972
+ default_model: CloudApiModelSchema.optional()
19973
+ }).strict();
19974
+ var CloudApiStatusSchema = external_exports.object({
19975
+ enabled: external_exports.boolean(),
19976
+ providers: external_exports.array(CloudApiProviderSchema).max(16),
19977
+ configurations: external_exports.array(CloudApiConfigurationSchema).max(8)
19978
+ }).strict();
19979
+ var CloudApiSavedSchema = external_exports.object({ configuration: CloudApiConfigurationSchema }).strict();
19980
+ var PersonalCloudRevisionSchema = external_exports.string().uuid().optional();
19981
+ function hasValidPersonalCloudRevision(value) {
19982
+ 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;
19983
+ }
19984
+ var HostedAgentSelectionSchema = external_exports.object({
19985
+ profile_id: external_exports.string().min(1).max(64),
19986
+ api_config_revision: PersonalCloudRevisionSchema
19987
+ }).strict().refine(hasValidPersonalCloudRevision, "Personal Cloud Agent selection requires its exact revision");
19988
+
19855
19989
  // ../protocol/dist/src/history-summary.js
19856
19990
  var HISTORY_SUMMARY_MAX_SOURCE_BYTES = 20 * 1024;
19857
19991
  var HISTORY_SUMMARY_MAX_PROMPT_BYTES = 30 * 1024;
@@ -19867,7 +20001,7 @@ function record2(value) {
19867
20001
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
19868
20002
  }
19869
20003
  function historySummaryMarker(event) {
19870
- if (event.type !== "agent_request")
20004
+ if (event.deleted || event.type !== "agent_request")
19871
20005
  return void 0;
19872
20006
  const marker = record2(record2(event.payload)?.history_summary);
19873
20007
  const ids = marker?.source_event_ids;
@@ -19897,8 +20031,10 @@ var HostedGithubTaskInputSchema = external_exports.object({
19897
20031
  profile_id: external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/u),
19898
20032
  idempotency_key: Key2,
19899
20033
  continue_task_id: external_exports.string().regex(/^gh-task-[a-f0-9]{32}$/u).optional(),
19900
- reply_to_event_id: external_exports.string().min(1).max(128).nullable().optional()
19901
- }).strict();
20034
+ reply_to_event_id: external_exports.string().min(1).max(128).nullable().optional(),
20035
+ api_config_revision: PersonalCloudRevisionSchema,
20036
+ content_revision: external_exports.number().int().nonnegative().optional()
20037
+ }).strict().refine(hasValidPersonalCloudRevision, { message: "Personal cloud profiles require their exact configuration revision" });
19902
20038
  var HostedGithubCompleteInputSchema = external_exports.object({
19903
20039
  state: external_exports.string().regex(/^[A-Za-z0-9_-]{43}$/u),
19904
20040
  code: external_exports.string().min(1).max(500)
@@ -19946,7 +20082,8 @@ var HostedGithubTaskSummarySchema = external_exports.object({
19946
20082
  revision: Revision,
19947
20083
  error_code: external_exports.string().regex(/^[a-z][a-z0-9_]{0,63}$/u).nullable(),
19948
20084
  pull_request_url: PullUrl,
19949
- expires_at: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER)
20085
+ expires_at: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER),
20086
+ api_config_revision: external_exports.string().uuid().optional()
19950
20087
  }).strict();
19951
20088
  var bytes = (value) => value.length / 4 * 3 - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
19952
20089
  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();
@@ -19972,59 +20109,6 @@ var HostedGithubTaskSchema = HostedGithubTaskSummarySchema.extend({
19972
20109
  });
19973
20110
  var HostedGithubTaskListSchema = external_exports.object({ tasks: external_exports.array(HostedGithubTaskSummarySchema).max(10) }).strict();
19974
20111
 
19975
- // ../protocol/dist/src/registration.js
19976
- 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));
19977
- var Label = external_exports.string().regex(/^[^\u0000-\u001f\u007f-\u009f]*$/u).trim().min(1).max(120);
19978
- var SendRegistrationInputSchema = external_exports.object({
19979
- email: RegistrationEmailSchema,
19980
- challenge_token: external_exports.string().min(1).max(2048),
19981
- idempotency_key: external_exports.string().uuid(),
19982
- locale: external_exports.enum(["en", "zh-CN"])
19983
- }).strict();
19984
- var AccountPasswordSchema = external_exports.string().min(12).max(128).refine((value) => new TextEncoder().encode(value).byteLength <= 512);
19985
- var EmailLoginInputSchema = external_exports.object({
19986
- email: RegistrationEmailSchema,
19987
- password: AccountPasswordSchema,
19988
- device_name: Label,
19989
- remember_device: external_exports.boolean().default(false)
19990
- }).strict();
19991
- var VerifyRegistrationInputSchema = external_exports.object({
19992
- registration_id: external_exports.string().uuid(),
19993
- code: external_exports.string().regex(/^\d{8}$/),
19994
- display_name: Label,
19995
- device_name: Label,
19996
- remember_device: external_exports.boolean().default(false),
19997
- privacy_acknowledged: external_exports.literal(true),
19998
- password: AccountPasswordSchema
19999
- }).strict();
20000
- var RegistrationStatusSchema = external_exports.object({
20001
- enabled: external_exports.boolean(),
20002
- site_key: external_exports.string().nullable(),
20003
- challenge_binding: external_exports.string().nullable()
20004
- }).strict();
20005
- var RegistrationSentSchema = external_exports.object({
20006
- registration_id: external_exports.string().uuid(),
20007
- expires_in_seconds: external_exports.literal(600),
20008
- resend_after_seconds: external_exports.literal(60)
20009
- }).strict();
20010
- var PasswordResetSentSchema = external_exports.object({
20011
- reset_id: external_exports.string().uuid(),
20012
- expires_in_seconds: external_exports.literal(600),
20013
- resend_after_seconds: external_exports.literal(60)
20014
- }).strict();
20015
- var VerifyPasswordResetInputSchema = external_exports.object({
20016
- reset_id: external_exports.string().uuid(),
20017
- email: RegistrationEmailSchema,
20018
- code: external_exports.string().regex(/^\d{8}$/),
20019
- password: AccountPasswordSchema,
20020
- password_confirmation: AccountPasswordSchema,
20021
- locale: external_exports.enum(["en", "zh-CN"])
20022
- }).strict().refine((value) => value.password === value.password_confirmation);
20023
- var EmailAccountSessionSchema = external_exports.object({
20024
- 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(),
20025
- expires_at: external_exports.string().datetime()
20026
- }).strict();
20027
-
20028
20112
  // ../protocol/dist/src/index.js
20029
20113
  var sessionModes = ["solo", "multi"];
20030
20114
  var membershipRoles = ["owner", "participant", "viewer"];
@@ -20039,7 +20123,8 @@ var eventTypes = [
20039
20123
  "attachment",
20040
20124
  "context_snapshot",
20041
20125
  "membership_change",
20042
- "session_state_change"
20126
+ "session_state_change",
20127
+ "message_deleted"
20043
20128
  ];
20044
20129
  var eventVisibilities = ["session", "owner_only"];
20045
20130
  var captureFidelities = [
@@ -20136,8 +20221,18 @@ var CanonicalEventSchema = external_exports.object({
20136
20221
  visibility: EventVisibilitySchema,
20137
20222
  reply_to_event_id: IdSchema.nullable(),
20138
20223
  payload: JsonValueSchema,
20139
- runtime_provenance: RuntimeProvenanceSchema.nullable()
20224
+ runtime_provenance: RuntimeProvenanceSchema.nullable(),
20225
+ content_revision: external_exports.number().int().nonnegative().optional(),
20226
+ deleted: external_exports.object({ deleted_at: external_exports.string().datetime(), reason: external_exports.enum(["author", "request", "summary_invalidated"]) }).strict().optional()
20140
20227
  });
20228
+ var DeleteMessageInputSchema = external_exports.object({ idempotency_key: IdempotencyKeySchema }).strict();
20229
+ var DeleteMessageResultSchema = external_exports.object({
20230
+ event: CanonicalEventSchema,
20231
+ target_event_id: IdSchema,
20232
+ content_revision: external_exports.number().int().nonnegative(),
20233
+ affected_event_ids: external_exports.array(IdSchema).max(256),
20234
+ affected_truncated: external_exports.boolean()
20235
+ }).strict();
20141
20236
  var MessageMentionsSchema = external_exports.array(external_exports.object({
20142
20237
  user_id: IdSchema,
20143
20238
  start: external_exports.number().int().nonnegative().max(1e6),
@@ -20166,6 +20261,7 @@ var AppendEventInputSchema = external_exports.object({
20166
20261
  payload: JsonValueSchema,
20167
20262
  runtime_id: IdSchema.optional(),
20168
20263
  claim_attempt: external_exports.number().int().positive().optional(),
20264
+ content_revision: external_exports.number().int().nonnegative().optional(),
20169
20265
  observed_model: external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
20170
20266
  observed_reasoning_effort: external_exports.string().trim().min(1).max(80).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional()
20171
20267
  });
@@ -20175,7 +20271,28 @@ var HostedAgentRequestInputSchema = external_exports.object({
20175
20271
  include_code: external_exports.boolean().default(false),
20176
20272
  idempotency_key: IdempotencyKeySchema,
20177
20273
  reply_to_event_id: IdSchema.nullable().optional(),
20178
- github_task_id: external_exports.string().regex(/^gh-task-[a-f0-9]{32}$/u).optional()
20274
+ github_task_id: external_exports.string().regex(/^gh-task-[a-f0-9]{32}$/u).optional(),
20275
+ continue_from_event_id: IdSchema.optional(),
20276
+ api_config_revision: PersonalCloudRevisionSchema,
20277
+ content_revision: external_exports.number().int().nonnegative().optional()
20278
+ }).strict().refine(hasValidPersonalCloudRevision, { message: "Personal cloud profiles require their exact configuration revision" });
20279
+ var HostedAgentFailurePayloadSchema = external_exports.object({
20280
+ content: external_exports.string().min(1).max(512),
20281
+ status: external_exports.literal("failed"),
20282
+ outcome: external_exports.enum(["timed_out", "failed"]),
20283
+ error: external_exports.object({
20284
+ code: external_exports.string().regex(/^[a-z][a-z0-9_]{0,63}$/u),
20285
+ provider_attempts: external_exports.number().int().min(0).max(64).optional()
20286
+ }).strict()
20287
+ }).strict();
20288
+ 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" });
20289
+ var HostedAgentAcceptedSchema = external_exports.object({
20290
+ request_event: CanonicalEventSchema,
20291
+ replayed: external_exports.boolean()
20292
+ }).strict();
20293
+ var HostedAgentPausedSchema = external_exports.object({
20294
+ request_event_id: IdSchema,
20295
+ status: external_exports.literal("paused")
20179
20296
  }).strict();
20180
20297
  var HostedAgentStatusSchema = external_exports.discriminatedUnion("enabled", [
20181
20298
  external_exports.object({ enabled: external_exports.literal(false) }).strict(),
@@ -20200,7 +20317,9 @@ var HostedAgentStatusSchema = external_exports.discriminatedUnion("enabled", [
20200
20317
  model: external_exports.string(),
20201
20318
  available: external_exports.boolean(),
20202
20319
  capacity: external_exports.number().int().nonnegative(),
20203
- status: external_exports.enum(["available", "busy", "daily_limit", "cooldown", "user_busy", "rate_limit"])
20320
+ status: external_exports.enum(["available", "busy", "daily_limit", "cooldown", "user_busy", "rate_limit"]),
20321
+ source: external_exports.enum(["service", "personal"]).optional(),
20322
+ api_config_revision: external_exports.string().uuid().optional()
20204
20323
  }).strict()),
20205
20324
  capabilities: external_exports.array(external_exports.string()),
20206
20325
  privacy: external_exports.string()
@@ -20312,6 +20431,17 @@ var ClaimInvitationInputSchema = external_exports.object({
20312
20431
  var AcceptInvitationInputSchema = external_exports.object({
20313
20432
  invite_token: external_exports.string().min(32).max(512)
20314
20433
  });
20434
+ var PreviewProjectInvitationInputSchema = external_exports.object({
20435
+ invite_token: external_exports.string().regex(/^gti_[A-Za-z0-9_-]{32,508}$/)
20436
+ }).strict();
20437
+ var ProjectInvitationPreviewSchema = external_exports.object({
20438
+ project: external_exports.object({ id: IdSchema, title: external_exports.string().min(1).max(200) }).strict(),
20439
+ inviter_display_name: external_exports.string().min(1).max(120),
20440
+ role: InvitationRoleSchema,
20441
+ created_at: external_exports.string().datetime(),
20442
+ expires_at: external_exports.string().datetime(),
20443
+ already_member: external_exports.boolean()
20444
+ }).strict();
20315
20445
  var InvitationRecordSchema = external_exports.object({
20316
20446
  id: IdSchema,
20317
20447
  session_id: IdSchema,
@@ -20386,6 +20516,10 @@ var DeviceAuthorizationRecordSchema = external_exports.object({
20386
20516
  claimed_at: external_exports.string().datetime().nullable(),
20387
20517
  claimed_by_device_id: IdSchema.nullable()
20388
20518
  });
20519
+ var CodexLauncherAuthorizationSchema = external_exports.object({
20520
+ authorization: DeviceAuthorizationRecordSchema.strict(),
20521
+ email: RegistrationEmailSchema
20522
+ }).strict();
20389
20523
  var RotateDeviceTokenInputSchema = external_exports.object({
20390
20524
  expires_at: external_exports.string().datetime().nullable().optional()
20391
20525
  });
@@ -20420,6 +20554,7 @@ var RegisterRuntimeInputSchema = external_exports.object({
20420
20554
  provider: external_exports.string().trim().min(1).max(80),
20421
20555
  model: external_exports.string().trim().min(1).max(160),
20422
20556
  execution_profiles: RuntimeExecutionProfilesSchema.optional(),
20557
+ context_deletion_version: external_exports.literal(1).optional(),
20423
20558
  local_session_id: external_exports.string().trim().min(1).max(512),
20424
20559
  capture_fidelity: CaptureFidelitySchema
20425
20560
  });
@@ -20433,11 +20568,13 @@ var AgentRequestClaimSchema = external_exports.object({
20433
20568
  // `paused` is a decision by the requester, not a claim a runtime can execute.
20434
20569
  // It is reported so a connector can skip the request without advancing past it.
20435
20570
  status: external_exports.enum(["claimed", "completed", "paused"]),
20436
- attempt_count: external_exports.number().int().positive().optional()
20571
+ attempt_count: external_exports.number().int().positive().optional(),
20572
+ content_revision: external_exports.number().int().nonnegative().optional()
20437
20573
  }).strict();
20438
20574
  var CompleteAgentRequestInputSchema = external_exports.object({
20439
20575
  runtime_id: IdSchema,
20440
20576
  claim_attempt: external_exports.number().int().positive().optional(),
20577
+ content_revision: external_exports.number().int().nonnegative().optional(),
20441
20578
  idempotency_key: IdempotencyKeySchema,
20442
20579
  payload: JsonValueSchema,
20443
20580
  observed_model: external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
@@ -20452,6 +20589,7 @@ var CommitLocalTurnInputSchema = external_exports.object({
20452
20589
  local_turn_id: IdSchema,
20453
20590
  runtime_id: IdSchema,
20454
20591
  based_on_sequence: external_exports.number().int().nonnegative(),
20592
+ content_revision: external_exports.number().int().nonnegative().optional(),
20455
20593
  occurred_at: external_exports.string().datetime(),
20456
20594
  observed_model: external_exports.string().trim().min(1).max(160).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
20457
20595
  observed_reasoning_effort: external_exports.string().trim().min(1).max(80).regex(/^[^\u0000-\u001f\u007f-\u009f]+$/u).optional(),
@@ -20505,6 +20643,7 @@ var SnapshotRequestRecordSchema = external_exports.object({
20505
20643
  kind: SnapshotRequestKindSchema,
20506
20644
  through_sequence: external_exports.number().int().nonnegative(),
20507
20645
  status: SnapshotRequestStatusSchema,
20646
+ content_revision: external_exports.number().int().nonnegative().optional(),
20508
20647
  target_runtime_id: IdSchema.nullable(),
20509
20648
  claimed_by_runtime_id: IdSchema.nullable(),
20510
20649
  created_at: external_exports.string().datetime(),
@@ -20530,7 +20669,8 @@ var SubscribeMessageSchema = external_exports.object({
20530
20669
  var ReplayResponseSchema = external_exports.object({
20531
20670
  events: external_exports.array(CanonicalEventSchema),
20532
20671
  cursor: external_exports.number().int().nonnegative(),
20533
- has_more: external_exports.boolean()
20672
+ has_more: external_exports.boolean(),
20673
+ content_revision: external_exports.number().int().nonnegative().optional()
20534
20674
  });
20535
20675
  var SessionListItemSchema = external_exports.object({
20536
20676
  id: IdSchema,
@@ -20541,6 +20681,7 @@ var SessionListItemSchema = external_exports.object({
20541
20681
  state: external_exports.enum(["active", "archived"]),
20542
20682
  role: MembershipRoleSchema,
20543
20683
  current_sequence: external_exports.number().int().nonnegative(),
20684
+ content_revision: external_exports.number().int().nonnegative().optional(),
20544
20685
  member_count: external_exports.number().int().nonnegative().optional(),
20545
20686
  updated_at: external_exports.string().datetime()
20546
20687
  });
@@ -20644,7 +20785,8 @@ var HttpCollaborationClient = class {
20644
20785
  return {
20645
20786
  events,
20646
20787
  nextSequence: requiredNumber(body.cursor, "cursor"),
20647
- hasMore: body.has_more === true
20788
+ hasMore: body.has_more === true,
20789
+ ...body.content_revision === void 0 ? {} : { contentRevision: requiredRevision(body.content_revision, "events.content_revision") }
20648
20790
  };
20649
20791
  }
20650
20792
  async readContext(sessionId, view, throughSequence) {
@@ -20702,7 +20844,8 @@ var HttpCollaborationClient = class {
20702
20844
  status,
20703
20845
  requestId: requiredString(body.request_event_id, "claim.request_event_id"),
20704
20846
  runtimeId: requiredString(body.runtime_id, "claim.runtime_id"),
20705
- attemptCount
20847
+ attemptCount,
20848
+ ...body.content_revision === void 0 ? {} : { contentRevision: requiredRevision(body.content_revision, "claim.content_revision") }
20706
20849
  };
20707
20850
  }
20708
20851
  async completeAgentRequest(sessionId, requestId, input2) {
@@ -20711,6 +20854,7 @@ var HttpCollaborationClient = class {
20711
20854
  body: JSON.stringify({
20712
20855
  runtime_id: input2.runtimeId,
20713
20856
  ...input2.claimAttempt === void 0 ? {} : { claim_attempt: input2.claimAttempt },
20857
+ ...input2.contentRevision === void 0 ? {} : { content_revision: input2.contentRevision },
20714
20858
  idempotency_key: input2.idempotencyKey,
20715
20859
  payload: truncateJsonValue(input2.payload, 160 * 1024),
20716
20860
  ...input2.observedModel === void 0 ? {} : { observed_model: input2.observedModel },
@@ -20725,6 +20869,7 @@ var HttpCollaborationClient = class {
20725
20869
  body: JSON.stringify({
20726
20870
  runtime_id: input2.runtimeId,
20727
20871
  ...input2.claimAttempt === void 0 ? {} : { claim_attempt: input2.claimAttempt },
20872
+ ...input2.contentRevision === void 0 ? {} : { content_revision: input2.contentRevision },
20728
20873
  idempotency_key: input2.idempotencyKey,
20729
20874
  payload: truncateJsonValue(input2.payload, 32 * 1024),
20730
20875
  ...input2.observedModel === void 0 ? {} : { observed_model: input2.observedModel },
@@ -20741,6 +20886,7 @@ var HttpCollaborationClient = class {
20741
20886
  local_turn_id: input2.localTurnId,
20742
20887
  runtime_id: input2.runtimeId,
20743
20888
  based_on_sequence: input2.basedOnSequence,
20889
+ ...input2.contentRevision === void 0 ? {} : { content_revision: input2.contentRevision },
20744
20890
  occurred_at: input2.occurredAt,
20745
20891
  ...input2.observedModel === void 0 ? {} : { observed_model: input2.observedModel },
20746
20892
  ...input2.observedReasoningEffort === void 0 ? {} : { observed_reasoning_effort: input2.observedReasoningEffort },
@@ -20847,6 +20993,7 @@ function toWireEvent(event) {
20847
20993
  visibility: event.visibility ?? "session",
20848
20994
  runtime_id: event.runtimeId ?? event.runtime?.runtimeId,
20849
20995
  claim_attempt: event.claimAttempt,
20996
+ ...event.contentRevision === void 0 ? {} : { content_revision: event.contentRevision },
20850
20997
  observed_model: event.observedModel,
20851
20998
  observed_reasoning_effort: event.observedReasoningEffort
20852
20999
  };
@@ -20872,7 +21019,8 @@ function toWireRuntimeRegistration(runtime) {
20872
21019
  local_session_id: runtime.localSessionId,
20873
21020
  capture_fidelity: runtime.captureFidelity,
20874
21021
  ...runtime.capabilities === void 0 ? {} : { capabilities: [...runtime.capabilities] },
20875
- ...runtime.purpose === void 0 ? {} : { purpose: runtime.purpose }
21022
+ ...runtime.purpose === void 0 ? {} : { purpose: runtime.purpose },
21023
+ ...runtime.contextDeletionVersion === void 0 ? {} : { context_deletion_version: runtime.contextDeletionVersion }
20876
21024
  };
20877
21025
  }
20878
21026
  function validateContextReadInput(sessionId, view, throughSequence) {
@@ -20933,7 +21081,17 @@ function parseHistoryContext(value, expectedView, throughSequence) {
20933
21081
  if (items.some((item) => sourceIds.has(item.event_id))) {
20934
21082
  throw new Error("Collaboration API context repeats summarized sources");
20935
21083
  }
20936
- return { view: value.view, through_sequence: Number(value.through_sequence), items };
21084
+ return {
21085
+ view: value.view,
21086
+ through_sequence: Number(value.through_sequence),
21087
+ items,
21088
+ ...value.content_revision === void 0 ? {} : { content_revision: requiredRevision(value.content_revision, "context.content_revision") }
21089
+ };
21090
+ }
21091
+ function requiredRevision(value, label) {
21092
+ if (!Number.isSafeInteger(value) || Number(value) < 0)
21093
+ throw new Error(`Collaboration API returned invalid ${label}`);
21094
+ return Number(value);
20937
21095
  }
20938
21096
  function isContextId(value) {
20939
21097
  return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value);
@@ -20952,9 +21110,17 @@ function fromWireEvent(value) {
20952
21110
  ...typeof input2.reply_to_event_id === "string" ? { replyTo: input2.reply_to_event_id } : {},
20953
21111
  timestamp: requiredString(input2.created_at, "event.created_at"),
20954
21112
  payload: input2.payload,
21113
+ ...input2.content_revision === void 0 ? {} : { contentRevision: requiredRevision(input2.content_revision, "event.content_revision") },
21114
+ ...input2.deleted === void 0 ? {} : { deleted: fromWireDeletion(input2.deleted) },
20955
21115
  ...runtime === void 0 ? {} : { runtime }
20956
21116
  };
20957
21117
  }
21118
+ function fromWireDeletion(value) {
21119
+ const input2 = requiredObject(value);
21120
+ if (input2.reason !== "author" && input2.reason !== "request" && input2.reason !== "summary_invalidated")
21121
+ throw new Error("Collaboration API returned invalid event.deleted reason");
21122
+ return { deletedAt: requiredString(input2.deleted_at, "event.deleted.deleted_at"), reason: input2.reason };
21123
+ }
20958
21124
  function fromWireSnapshotRequest(value) {
20959
21125
  const input2 = requiredObject(value);
20960
21126
  const status = requiredString(input2.status, "snapshot_request.status");
@@ -20990,6 +21156,7 @@ function fromWireSnapshotRequest(value) {
20990
21156
  kind,
20991
21157
  ...typeof input2.target_runtime_id === "string" ? { targetRuntimeId: input2.target_runtime_id } : {},
20992
21158
  throughSequence: requiredNumber(input2.through_sequence, "snapshot_request.through_sequence"),
21159
+ ...input2.content_revision === void 0 ? {} : { contentRevision: requiredRevision(input2.content_revision, "snapshot_request.content_revision") },
20993
21160
  status,
20994
21161
  ...createdAt === void 0 ? {} : { createdAt },
20995
21162
  ..."result" in input2 ? { result: input2.result } : {},
@@ -21009,7 +21176,8 @@ function fromWireSession(value) {
21009
21176
  ...input2.state === "active" || input2.state === "archived" ? { state: input2.state } : {},
21010
21177
  ...name2 === void 0 ? {} : { name: name2 },
21011
21178
  ...role === void 0 ? {} : { role },
21012
- ...latestSequence === void 0 ? {} : { latestSequence }
21179
+ ...latestSequence === void 0 ? {} : { latestSequence },
21180
+ ...input2.content_revision === void 0 ? {} : { contentRevision: requiredRevision(input2.content_revision, "session.content_revision") }
21013
21181
  };
21014
21182
  }
21015
21183
  function fromWireProject(value) {
@@ -21056,7 +21224,8 @@ function fromWireRuntime(value) {
21056
21224
  ...input2.execution_profiles === void 0 || input2.execution_profiles === null ? {} : { executionProfiles: fromWireExecutionProfiles(input2.execution_profiles) },
21057
21225
  localSessionId: requiredString(input2.local_session_id, "runtime.local_session_id"),
21058
21226
  captureFidelity: requiredString(input2.capture_fidelity, "runtime.capture_fidelity"),
21059
- purpose
21227
+ purpose,
21228
+ ...input2.context_deletion_version === 1 ? { contextDeletionVersion: 1 } : {}
21060
21229
  };
21061
21230
  }
21062
21231
  function fromWireExecutionProfiles(value) {
@@ -21187,8 +21356,8 @@ function isObject2(value) {
21187
21356
 
21188
21357
  // ../adapters/dist/src/redaction.js
21189
21358
  var REDACTED = "[REDACTED]";
21359
+ var PRIVATE_KEY_PATTERN = /-----BEGIN (?:ENCRYPTED |RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\s\S]*?(?:-----END (?:ENCRYPTED |RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----|$)/g;
21190
21360
  var DEFAULT_SECRET_PATTERNS = [
21191
- /-----BEGIN (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----/g,
21192
21361
  /\bAKIA[0-9A-Z]{16}\b/g,
21193
21362
  /\b(?:ghp|github_pat|glpat|sk|xox[baprs])[-_][A-Za-z0-9_-]{16,}\b/g,
21194
21363
  /\bBearer\s+[A-Za-z0-9._~+/=-]{8,}\b/gi,
@@ -21201,6 +21370,8 @@ var SENSITIVE_KEY_NAMES = /* @__PURE__ */ new Set([
21201
21370
  "accesstoken",
21202
21371
  "authtoken",
21203
21372
  "authorization",
21373
+ "cookie",
21374
+ "setcookie",
21204
21375
  "bearer",
21205
21376
  "clientsecret",
21206
21377
  "password",
@@ -21217,7 +21388,83 @@ var SENSITIVE_KEY_NAMES = /* @__PURE__ */ new Set([
21217
21388
  ]);
21218
21389
  function redactText(value, options = {}) {
21219
21390
  const replacement = options.replacement ?? REDACTED;
21220
- 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);
21391
+ return [...DEFAULT_SECRET_PATTERNS, ...options.extraPatterns ?? []].reduce(
21392
+ (redacted, pattern) => redacted.replace(cloneGlobal(pattern), (match, prefix) => typeof prefix === "string" && prefix.length < match.length ? `${prefix}${replacement}` : replacement),
21393
+ // Mask PEM first: scanning `private_key: -----BEGIN ...` as an ordinary
21394
+ // assignment must not break its header and leave the following body public.
21395
+ redactSensitiveFields(value.replace(cloneGlobal(PRIVATE_KEY_PATTERN), () => replacement), replacement)
21396
+ );
21397
+ }
21398
+ function redactSensitiveFields(text, replacement) {
21399
+ const fields = /("(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'|\b[A-Za-z_][A-Za-z0-9_.-]*)(\s*[:=]\s*)/gu;
21400
+ const parts = [];
21401
+ let retainedFrom = 0;
21402
+ let match;
21403
+ while ((match = fields.exec(text)) !== null) {
21404
+ const encodedKey = match[1];
21405
+ let key = encodedKey;
21406
+ if (encodedKey.startsWith('"')) {
21407
+ try {
21408
+ key = JSON.parse(encodedKey);
21409
+ } catch {
21410
+ continue;
21411
+ }
21412
+ } else if (encodedKey.startsWith("'"))
21413
+ key = encodedKey.slice(1, -1);
21414
+ if (!isSensitiveKey(key))
21415
+ continue;
21416
+ const start = fields.lastIndex;
21417
+ const end = sensitiveValueEnd(text, start, encodedKey[0] !== '"' && encodedKey[0] !== "'" && /^(?:authorization|cookie|set-cookie)$/iu.test(key));
21418
+ const quote = text[start];
21419
+ const masked = quote === "'" ? `'${replacement.replace(/\\/gu, "\\\\").replace(/'/gu, "\\'")}'` : quote === '"' || encodedKey.startsWith('"') ? JSON.stringify(replacement) : replacement;
21420
+ parts.push(text.slice(retainedFrom, start), masked);
21421
+ retainedFrom = end;
21422
+ fields.lastIndex = end;
21423
+ }
21424
+ return parts.length === 0 ? text : parts.join("") + text.slice(retainedFrom);
21425
+ }
21426
+ function sensitiveValueEnd(text, start, header) {
21427
+ if (header) {
21428
+ const end = text.indexOf("\n", start);
21429
+ return end < 0 ? text.length : end;
21430
+ }
21431
+ const first = text[start];
21432
+ if (first === '"' || first === "'") {
21433
+ for (let index2 = start + 1; index2 < text.length; index2++) {
21434
+ if (text[index2] === "\\")
21435
+ index2++;
21436
+ else if (text[index2] === first)
21437
+ return index2 + 1;
21438
+ }
21439
+ return text.length;
21440
+ }
21441
+ if (first === "{" || first === "[") {
21442
+ const closing = [first === "{" ? "}" : "]"];
21443
+ let quote;
21444
+ for (let index2 = start + 1; index2 < text.length; index2++) {
21445
+ const character = text[index2];
21446
+ if (quote !== void 0) {
21447
+ if (character === "\\")
21448
+ index2++;
21449
+ else if (character === quote)
21450
+ quote = void 0;
21451
+ } else if (character === '"' || character === "'")
21452
+ quote = character;
21453
+ else if (character === "{" || character === "[")
21454
+ closing.push(character === "{" ? "}" : "]");
21455
+ else if (character === "}" || character === "]") {
21456
+ if (character !== closing.pop())
21457
+ return text.length;
21458
+ if (closing.length === 0)
21459
+ return index2 + 1;
21460
+ }
21461
+ }
21462
+ return text.length;
21463
+ }
21464
+ let index = start;
21465
+ while (index < text.length && !/[\s,;}\]]/u.test(text[index]))
21466
+ index++;
21467
+ return index;
21221
21468
  }
21222
21469
  function redactValue(value, options = {}) {
21223
21470
  if (typeof value === "string")
@@ -21239,6 +21486,208 @@ function cloneGlobal(pattern) {
21239
21486
  return new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`);
21240
21487
  }
21241
21488
 
21489
+ // ../adapters/dist/src/live-output.js
21490
+ import { randomUUID } from "node:crypto";
21491
+ var MAX_ITEMS = 128;
21492
+ var MAX_INPUT_BYTES = 96 * 1024;
21493
+ var MAX_PUBLIC_BYTES = 24 * 1024;
21494
+ var MAX_PUBLICATIONS = 1200;
21495
+ function createLiveOutputPublisher(options) {
21496
+ const items = /* @__PURE__ */ new Map();
21497
+ const now = options.now ?? Date.now;
21498
+ const intervalMs = options.intervalMs ?? 1500;
21499
+ let lastPublished, publications = 0, closed = false;
21500
+ let timer;
21501
+ let queue = Promise.resolve();
21502
+ let lastVisited;
21503
+ const serial = (operation) => {
21504
+ queue = queue.then(operation, operation);
21505
+ return queue;
21506
+ };
21507
+ const itemFor = (key, kind, title) => {
21508
+ let item = items.get(key);
21509
+ if (!item && items.size < MAX_ITEMS) {
21510
+ item = {
21511
+ streamId: randomUUID(),
21512
+ raw: "",
21513
+ kind,
21514
+ state: "running",
21515
+ revision: 0,
21516
+ acknowledged: "",
21517
+ dirty: true,
21518
+ truncated: false
21519
+ };
21520
+ items.set(key, item);
21521
+ }
21522
+ if (item && title !== void 0)
21523
+ item.title = bound(redactText(title, options.redaction), 256);
21524
+ return item;
21525
+ };
21526
+ const safe = (item) => {
21527
+ let content = item.raw;
21528
+ if (item.state === "running") {
21529
+ content = content.replace(/(?:\bBearer\s+|\b(?:api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|password|passwd|secret|token)["']?\s*[=:]\s*["']?)[^\n,;]*$/giu, "");
21530
+ let end = content.length;
21531
+ while (end > 0 && /[A-Za-z0-9_./~+=:@%\-]/u.test(content[end - 1]))
21532
+ end--;
21533
+ content = content.slice(0, end);
21534
+ }
21535
+ content = redactText(content, options.redaction);
21536
+ return bound(content, MAX_PUBLIC_BYTES, item.truncated);
21537
+ };
21538
+ const signatureFor = (item) => JSON.stringify([safe(item), item.state, item.title, item.plan]);
21539
+ const schedule = () => {
21540
+ if (closed || options.schedule === false || timer || ![...items.values()].some((x) => x.dirty))
21541
+ return;
21542
+ timer = setTimeout(() => {
21543
+ timer = void 0;
21544
+ void flush().catch(() => void 0);
21545
+ }, intervalMs);
21546
+ timer.unref();
21547
+ };
21548
+ const publishOne = async (item) => {
21549
+ if (!item.dirty || publications >= MAX_PUBLICATIONS)
21550
+ return;
21551
+ const content = safe(item);
21552
+ const signature = JSON.stringify([content, item.state, item.title, item.plan]);
21553
+ if (!item.pending && signature === item.acknowledged) {
21554
+ item.dirty = false;
21555
+ return;
21556
+ }
21557
+ if (!item.pending && !content.trim() && item.plan === void 0)
21558
+ return;
21559
+ const revision = item.revision + 1;
21560
+ const update = {
21561
+ id: `${item.streamId}:${revision}`,
21562
+ content,
21563
+ phase: "stream",
21564
+ streamId: item.streamId,
21565
+ streamMode: "snapshot",
21566
+ streamKind: item.kind,
21567
+ streamRevision: revision,
21568
+ streamState: item.state,
21569
+ ...item.title === void 0 ? {} : { title: item.title },
21570
+ ...item.plan === void 0 ? {} : { plan: item.plan }
21571
+ };
21572
+ item.pending ??= { update, signature };
21573
+ const pending = item.pending;
21574
+ try {
21575
+ if (await options.publish(pending.update) === false)
21576
+ return;
21577
+ item.revision = pending.update.streamRevision;
21578
+ item.acknowledged = pending.signature;
21579
+ delete item.pending;
21580
+ item.dirty = signatureFor(item) !== item.acknowledged;
21581
+ lastPublished = now();
21582
+ publications++;
21583
+ } catch {
21584
+ }
21585
+ };
21586
+ const flush = () => serial(async () => {
21587
+ if (closed || lastPublished !== void 0 && now() - lastPublished < intervalMs) {
21588
+ schedule();
21589
+ return;
21590
+ }
21591
+ const ordered = [...items.values()];
21592
+ const start = lastVisited === void 0 ? 0 : (ordered.indexOf(lastVisited) + 1) % ordered.length;
21593
+ for (let offset = 0; offset < ordered.length; offset++) {
21594
+ const item = ordered[(start + offset) % ordered.length];
21595
+ if (!item.dirty)
21596
+ continue;
21597
+ lastVisited = item;
21598
+ await publishOne(item);
21599
+ if (lastPublished !== void 0 && now() - lastPublished < intervalMs)
21600
+ break;
21601
+ }
21602
+ schedule();
21603
+ });
21604
+ return {
21605
+ async onDelta(key, delta, kind = "answer", title) {
21606
+ if (closed || !delta)
21607
+ return;
21608
+ const item = itemFor(key, kind, title);
21609
+ if (!item || item.state !== "running" || item.truncated)
21610
+ return;
21611
+ const raw = item.raw + delta;
21612
+ item.raw = bound(raw, MAX_INPUT_BYTES);
21613
+ item.truncated = Buffer.byteLength(raw) > MAX_INPUT_BYTES;
21614
+ item.dirty = true;
21615
+ await flush();
21616
+ },
21617
+ async onSnapshot(key, text, kind = "answer", title, state = "running") {
21618
+ if (closed)
21619
+ return;
21620
+ const item = itemFor(key, kind, title);
21621
+ if (!item)
21622
+ return;
21623
+ item.raw = bound(text, MAX_INPUT_BYTES);
21624
+ item.truncated = Buffer.byteLength(text) > MAX_INPUT_BYTES;
21625
+ item.state = state;
21626
+ item.dirty = true;
21627
+ await flush();
21628
+ },
21629
+ async onPlan(key, steps) {
21630
+ if (closed)
21631
+ return;
21632
+ const item = itemFor(key, "plan");
21633
+ if (!item)
21634
+ return;
21635
+ item.plan = steps.slice(0, 64).map((step) => ({ step: bound(redactText(step.step, options.redaction), 512), status: step.status }));
21636
+ item.raw = item.plan.map((step) => `${step.status}: ${step.step}`).join("\n");
21637
+ item.dirty = true;
21638
+ await flush();
21639
+ },
21640
+ flush,
21641
+ async finish(success2 = true) {
21642
+ if (timer) {
21643
+ clearTimeout(timer);
21644
+ timer = void 0;
21645
+ }
21646
+ await serial(async () => {
21647
+ if (closed)
21648
+ return;
21649
+ for (const item of [...items.values()].slice(0, 64)) {
21650
+ if (item.state === "running") {
21651
+ item.state = success2 ? "completed" : "failed";
21652
+ item.dirty = true;
21653
+ }
21654
+ await publishOne(item);
21655
+ if (item.dirty && !item.pending)
21656
+ await publishOne(item);
21657
+ }
21658
+ closed = true;
21659
+ items.clear();
21660
+ });
21661
+ },
21662
+ lastPublishedAt: () => lastPublished
21663
+ };
21664
+ }
21665
+ function liveOutputPayload(update) {
21666
+ return {
21667
+ content: update.content,
21668
+ phase: update.phase,
21669
+ stream_id: update.streamId,
21670
+ stream_mode: update.streamMode,
21671
+ stream_kind: update.streamKind,
21672
+ stream_revision: update.streamRevision,
21673
+ stream_state: update.streamState,
21674
+ ...update.title === void 0 ? {} : { title: update.title },
21675
+ ...update.plan === void 0 ? {} : { plan: update.plan.map((step) => ({ step: step.step, status: step.status })) }
21676
+ };
21677
+ }
21678
+ function bound(text, maxBytes, alreadyTruncated = false) {
21679
+ if (!alreadyTruncated && Buffer.byteLength(text) <= maxBytes)
21680
+ return text;
21681
+ const suffix = "\n[TRUNCATED]";
21682
+ const bytes2 = Buffer.from(text).subarray(0, maxBytes - Buffer.byteLength(suffix));
21683
+ let end = bytes2.length;
21684
+ while (end > 0 && (bytes2[end - 1] & 192) === 128)
21685
+ end--;
21686
+ if (end < bytes2.length || (bytes2[end - 1] & 128) !== 0)
21687
+ end = Math.max(0, end - 1);
21688
+ return bytes2.subarray(0, end).toString("utf8") + suffix;
21689
+ }
21690
+
21242
21691
  // ../adapters/dist/src/jsonl.js
21243
21692
  var DEFAULT_MAX_READ_BYTES = 4 * 1024 * 1024;
21244
21693
 
@@ -21445,7 +21894,7 @@ function isNodeError(error62) {
21445
21894
  var MAX_FRAME_BYTES = 1024 * 1024;
21446
21895
 
21447
21896
  // ../bridge/dist/src/code-sync.js
21448
- import { createHash as createHash2, randomUUID } from "node:crypto";
21897
+ import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
21449
21898
  import { execFile } from "node:child_process";
21450
21899
  import { constants } from "node:fs";
21451
21900
  import { chmod as chmod2, lstat as lstat2, mkdir as mkdir2, open as open3, readFile as readFile2, realpath, rename, unlink } from "node:fs/promises";
@@ -21635,7 +22084,7 @@ var ProjectCodeSync = class _ProjectCodeSync {
21635
22084
  if (!sameHashes(current.hashes, binding.baseline))
21636
22085
  throw new CodeSyncError("code_sync_dirty", "Local files have unuploaded changes. Upload first, or recover cloud code into a new folder.");
21637
22086
  await applySnapshot(this.#root, snapshot.files, binding.baseline, {
21638
- backupRoot: path2.join(this.#stateRoot, "download-backups", randomUUID()),
22087
+ backupRoot: path2.join(this.#stateRoot, "download-backups", randomUUID2()),
21639
22088
  beforeWrite: async () => {
21640
22089
  binding.interrupted_download = true;
21641
22090
  await this.#save(binding);
@@ -21679,7 +22128,7 @@ var ProjectCodeSync = class _ProjectCodeSync {
21679
22128
  const recoveryStem = [...path2.basename(this.#root)];
21680
22129
  while (Buffer.byteLength(recoveryStem.join("")) > 180)
21681
22130
  recoveryStem.pop();
21682
- const recoveryName = `${recoveryStem.join("")}-recovered-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/gu, "").slice(0, 14)}-${randomUUID().slice(0, 8)}`;
22131
+ const recoveryName = `${recoveryStem.join("")}-recovered-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/gu, "").slice(0, 14)}-${randomUUID2().slice(0, 8)}`;
21683
22132
  const recoveryPath = path2.join(path2.dirname(this.#root), recoveryName);
21684
22133
  await mkdir2(recoveryPath, { mode: 448 });
21685
22134
  await applySnapshot(recoveryPath, snapshot.files, {}, void 0, this.#limits);
@@ -22126,7 +22575,7 @@ async function git(args, cwd, maxBuffer = 2 * 1024 * 1024) {
22126
22575
  }
22127
22576
  }
22128
22577
  async function writePrivate(filename, content) {
22129
- const temporary = `${filename}.${randomUUID()}.tmp`;
22578
+ const temporary = `${filename}.${randomUUID2()}.tmp`;
22130
22579
  const handle = await open3(temporary, "wx", 384);
22131
22580
  try {
22132
22581
  await handle.writeFile(content);
@@ -22222,7 +22671,7 @@ async function applySnapshot(root, files, baseline, options, limits = CLOUD_CODE
22222
22671
  if (!await safeAncestors(root, file2.path, true) || await fileHash(root, file2.path, options?.baselineExecutables?.has(file2.path), limits.maxFileBytes) !== baseline[file2.path])
22223
22672
  throw new CodeSyncError("code_sync_busy", "Local files changed during download. No further files were applied.");
22224
22673
  const filename = path2.join(root, ...file2.path.split("/"));
22225
- const temporary = path2.join(path2.dirname(filename), `.gatherthread-${randomUUID()}.tmp`);
22674
+ const temporary = path2.join(path2.dirname(filename), `.gatherthread-${randomUUID2()}.tmp`);
22226
22675
  const handle = await open3(temporary, "wx", file2.executable ? 448 : 384);
22227
22676
  try {
22228
22677
  await handle.writeFile(Buffer.from(file2.content_base64, "base64"));
@@ -22246,7 +22695,7 @@ async function applySnapshot(root, files, baseline, options, limits = CLOUD_CODE
22246
22695
  }
22247
22696
 
22248
22697
  // ../bridge/dist/src/github-code-sync.js
22249
- import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
22698
+ import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
22250
22699
  import { spawn } from "node:child_process";
22251
22700
  import { constants as constants2 } from "node:fs";
22252
22701
  import { lstat as lstat3, mkdir as mkdir3, open as open4, unlink as unlink2 } from "node:fs/promises";
@@ -22443,7 +22892,7 @@ var GitHubCodeStorage = class {
22443
22892
  async #tree(files) {
22444
22893
  if (!filesSchema.safeParse(files).success)
22445
22894
  throw new CodeSyncError("code_sync_limit", "Source tree exceeds GitHub checkpoint limits.");
22446
- const index = path3.join(this.#directory, `index-${randomUUID2()}`);
22895
+ const index = path3.join(this.#directory, `index-${randomUUID3()}`);
22447
22896
  try {
22448
22897
  await this.#git(["read-tree", "--empty"], void 0, index);
22449
22898
  const records = [];
@@ -22639,7 +23088,7 @@ import path10 from "node:path";
22639
23088
  // dist/src/code-sync-controller.js
22640
23089
  import { constants as constants3 } from "node:fs";
22641
23090
  import { lstat as lstat5, mkdir as mkdir4, open as open5, rename as rename2, unlink as unlink3 } from "node:fs/promises";
22642
- import { randomUUID as randomUUID3 } from "node:crypto";
23091
+ import { randomUUID as randomUUID4 } from "node:crypto";
22643
23092
  import path5 from "node:path";
22644
23093
 
22645
23094
  // dist/src/path-security.js
@@ -22902,7 +23351,7 @@ async function saveConsent(file2, binding, enabled) {
22902
23351
  await mkdir4(path5.dirname(file2), { recursive: true, mode: 448 });
22903
23352
  const ancestors = await secureDirectoryChain(path5.dirname(file2));
22904
23353
  await loadConsent(file2, binding);
22905
- const temporary = `${file2}.${randomUUID3()}.tmp`;
23354
+ const temporary = `${file2}.${randomUUID4()}.tmp`;
22906
23355
  const handle = await open5(temporary, "wx", 384);
22907
23356
  try {
22908
23357
  await handle.writeFile(JSON.stringify({ version: 1, binding, enabled }));
@@ -23677,6 +24126,255 @@ function asObject2(value) {
23677
24126
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
23678
24127
  }
23679
24128
 
24129
+ // dist/src/live-event-mapper.js
24130
+ var MAX_ATTEMPTS = 64;
24131
+ var MAX_BLOCKS = 128;
24132
+ var MAX_TEXT = 96 * 1024;
24133
+ function createDshLiveEventMapper(publisher) {
24134
+ const attempts = /* @__PURE__ */ new Map();
24135
+ const steps = /* @__PURE__ */ new Map();
24136
+ const tools = /* @__PURE__ */ new Map();
24137
+ let revision = 0;
24138
+ const deliver = (operation) => {
24139
+ void operation.catch(() => void 0);
24140
+ };
24141
+ const snapshot = (block, state) => deliver(publisher.onSnapshot(block.key, block.text, block.kind, block.title, state));
24142
+ const toolFor = (id, fallbackKey) => {
24143
+ let tool = tools.get(id);
24144
+ if (tool === void 0 && tools.size < MAX_BLOCKS) {
24145
+ tool = { key: fallbackKey, arguments: "" };
24146
+ tools.set(id, tool);
24147
+ }
24148
+ return tool;
24149
+ };
24150
+ const settle2 = (attempt, state) => {
24151
+ if (state === "failed")
24152
+ attempt.failed = true;
24153
+ for (const block of attempt.blocks.values()) {
24154
+ if (block.kind !== "tool")
24155
+ snapshot(block, state);
24156
+ else if (state === "failed") {
24157
+ const argumentsText = block.callId === void 0 ? void 0 : tools.get(block.callId)?.arguments;
24158
+ deliver(publisher.onSnapshot(block.key, `Arguments:
24159
+ ${argumentsText || "[Unparseable tool arguments]"}`, "tool", block.title, state));
24160
+ }
24161
+ }
24162
+ };
24163
+ const onFrame = (frame) => {
24164
+ if (frame.revision <= revision)
24165
+ return;
24166
+ const identity = frame.attemptId;
24167
+ if (frame.type === "start") {
24168
+ if (attempts.has(identity) || attempts.size >= MAX_ATTEMPTS)
24169
+ return;
24170
+ revision = frame.revision;
24171
+ const attempt2 = { turn: frame.turn, step: frame.step, nextIndex: 0, closed: false, failed: false, blocks: /* @__PURE__ */ new Map() };
24172
+ attempts.set(identity, attempt2);
24173
+ steps.set(`${frame.turn}:${frame.step}`, attempt2);
24174
+ return;
24175
+ }
24176
+ const attempt = attempts.get(identity);
24177
+ if (attempt === void 0 || attempt.closed || frame.index !== attempt.nextIndex)
24178
+ return;
24179
+ revision = frame.revision;
24180
+ if (frame.type === "end") {
24181
+ attempt.closed = true;
24182
+ settle2(attempt, attempt.failed || frame.outcome.kind === "abandoned" || frame.outcome.eventType === "assistant/attempt" ? "failed" : "completed");
24183
+ return;
24184
+ }
24185
+ attempt.nextIndex++;
24186
+ const chunk = object2(frame.chunk);
24187
+ if (chunk?.type === "finish") {
24188
+ const reason = object2(chunk.reason)?.kind ?? chunk.reason;
24189
+ if (reason === "error" || reason === "aborted")
24190
+ settle2(attempt, "failed");
24191
+ return;
24192
+ }
24193
+ if (!integer2(chunk?.index) || Number(chunk.index) >= MAX_BLOCKS)
24194
+ return;
24195
+ const index = Number(chunk.index);
24196
+ if (chunk.type === "block-start") {
24197
+ const kind = chunk.blockType === "text" ? "answer" : chunk.blockType === "reasoning" ? "reasoning" : chunk.blockType === "tool-call" ? "tool" : void 0;
24198
+ if (kind !== void 0 && !attempt.blocks.has(index)) {
24199
+ attempt.blocks.set(index, { key: `${identity}:${index}`, kind, text: "" });
24200
+ }
24201
+ return;
24202
+ }
24203
+ const block = attempt.blocks.get(index);
24204
+ if (block === void 0)
24205
+ return;
24206
+ if (chunk.type === "text-delta" && block.kind === "answer" || chunk.type === "reasoning-delta" && block.kind === "reasoning") {
24207
+ if (typeof chunk.text !== "string")
24208
+ return;
24209
+ block.text = bound2(block.text + chunk.text);
24210
+ deliver(publisher.onDelta(block.key, chunk.text, block.kind));
24211
+ } else if (chunk.type === "tool-call-delta" && block.kind === "tool") {
24212
+ if (!identifier(chunk.id) || typeof chunk.argumentsDelta !== "string" || block.callId !== void 0 && block.callId !== chunk.id)
24213
+ return;
24214
+ block.callId = chunk.id;
24215
+ if (typeof chunk.name === "string")
24216
+ block.title = bound2(chunk.name).slice(0, 256);
24217
+ const tool = toolFor(block.callId, block.key);
24218
+ if (tool === void 0)
24219
+ return;
24220
+ block.key = tool.key;
24221
+ block.text = bound2(block.text + chunk.argumentsDelta);
24222
+ if (block.title !== void 0)
24223
+ tool.title = block.title;
24224
+ const argumentsText = parsedArguments(block.text);
24225
+ if (argumentsText !== void 0)
24226
+ tool.arguments = argumentsText;
24227
+ deliver(publisher.onSnapshot(block.key, argumentsText === void 0 ? "Preparing tool arguments.\n" : `Arguments:
24228
+ ${argumentsText}`, "tool", block.title));
24229
+ } else if (chunk.type === "block-end") {
24230
+ const content = object2(chunk.block);
24231
+ if ((content?.type === "text" && block.kind === "answer" || content?.type === "reasoning" && block.kind === "reasoning") && typeof content.text === "string") {
24232
+ block.text = bound2(content.text);
24233
+ snapshot(block, "completed");
24234
+ } else if (content?.type === "tool-call" && block.kind === "tool" && identifier(content.id) && typeof content.arguments === "string" && (block.callId === void 0 || content.id === block.callId)) {
24235
+ const tool = toolFor(content.id, block.key);
24236
+ if (tool === void 0)
24237
+ return;
24238
+ block.callId = content.id;
24239
+ block.key = tool.key;
24240
+ block.text = publicArguments(content.arguments);
24241
+ if (typeof content.name === "string")
24242
+ block.title = content.name.slice(0, 256);
24243
+ tool.arguments = block.text;
24244
+ if (block.title !== void 0)
24245
+ tool.title = block.title;
24246
+ snapshot(block, "running");
24247
+ }
24248
+ }
24249
+ };
24250
+ const onDurable = (event) => {
24251
+ const data = object2(event.data);
24252
+ if (data === void 0)
24253
+ return;
24254
+ if (event.type === "assistant/message" && integer2(data.turn) && integer2(data.step)) {
24255
+ const attempt = steps.get(`${data.turn}:${data.step}`);
24256
+ if (attempt !== void 0 && data.interrupted === true)
24257
+ attempt.failed = true;
24258
+ const message = object2(data.message);
24259
+ if (!Array.isArray(message?.content))
24260
+ return;
24261
+ const nativeBlocks = [...attempt?.blocks.values() ?? []];
24262
+ for (const [index, value] of message.content.slice(0, MAX_BLOCKS).entries()) {
24263
+ const content = object2(value);
24264
+ const kind = content?.type === "text" ? "answer" : content?.type === "reasoning" ? "reasoning" : void 0;
24265
+ if (kind !== void 0 && typeof content.text === "string") {
24266
+ const candidate = nativeBlocks[index];
24267
+ const key = candidate?.kind === kind ? candidate.key : `assistant:${event.seq}:${index}`;
24268
+ if (candidate?.kind === kind)
24269
+ candidate.text = bound2(content.text);
24270
+ deliver(publisher.onSnapshot(key, content.text, kind, void 0, data.interrupted === true ? "failed" : "completed"));
24271
+ }
24272
+ }
24273
+ } else if (event.type === "assistant/attempt" && integer2(data.turn) && integer2(data.step)) {
24274
+ const attempt = steps.get(`${data.turn}:${data.step}`);
24275
+ if (attempt !== void 0)
24276
+ settle2(attempt, "failed");
24277
+ } else if (event.type === "tool/call" && identifier(data.callId) && typeof data.name === "string" && typeof data.arguments === "string") {
24278
+ const tool = toolFor(data.callId, `tool:${event.seq}`);
24279
+ if (tool === void 0)
24280
+ return;
24281
+ tool.arguments = publicArguments(data.arguments);
24282
+ tool.title = data.name.slice(0, 256);
24283
+ deliver(publisher.onSnapshot(tool.key, `Arguments:
24284
+ ${tool.arguments}`, "tool", tool.title));
24285
+ } else if (event.type === "tool/result") {
24286
+ const message = object2(data.message);
24287
+ const content = Array.isArray(message?.content) ? message.content : [];
24288
+ const wrapped = content.map(object2).find((block) => block?.type === "tool-result");
24289
+ const id = wrapped?.toolCallId ?? message?.toolCallId;
24290
+ if (!identifier(id))
24291
+ return;
24292
+ const tool = tools.get(id);
24293
+ if (tool === void 0)
24294
+ return;
24295
+ const blocks = wrapped === void 0 ? content : wrapped.content;
24296
+ if (!Array.isArray(blocks))
24297
+ return;
24298
+ const text = blocks.slice(0, MAX_BLOCKS).flatMap((value) => {
24299
+ const block = object2(value);
24300
+ return block?.type === "text" && typeof block.text === "string" ? [bound2(block.text)] : [];
24301
+ }).join("");
24302
+ const failed = wrapped?.isError === true || message?.isError === true || data.error !== void 0;
24303
+ deliver(publisher.onSnapshot(tool.key, `Arguments:
24304
+ ${tool.arguments}
24305
+
24306
+ Result:
24307
+ ${bound2(text)}`, "tool", tool.title, failed ? "failed" : "completed"));
24308
+ } else if (event.type === "todo/write" && Array.isArray(data.todos) && data.todos.length <= 64) {
24309
+ const plan = [];
24310
+ for (const value of data.todos) {
24311
+ const item = object2(value);
24312
+ if (typeof item?.content !== "string" || !["pending", "in_progress", "completed"].includes(String(item.status)))
24313
+ return;
24314
+ plan.push({ step: item.content, status: item.status });
24315
+ }
24316
+ deliver(publisher.onPlan("plan", plan));
24317
+ }
24318
+ };
24319
+ return {
24320
+ onEvent(event) {
24321
+ if (event.kind === "assistant-stream")
24322
+ onFrame(event.frame);
24323
+ else
24324
+ onDurable(event.event);
24325
+ },
24326
+ async finish(success2 = true) {
24327
+ await publisher.finish(success2);
24328
+ }
24329
+ };
24330
+ }
24331
+ function parseDshAssistantStreamFrame(value) {
24332
+ const frame = object2(value);
24333
+ if (!identifier(frame?.attemptId) || !integer2(frame?.revision) || Number(frame.revision) < 1)
24334
+ return void 0;
24335
+ const shared = { attemptId: frame.attemptId, revision: Number(frame.revision) };
24336
+ if (frame.type === "start" && integer2(frame.turn) && integer2(frame.step)) {
24337
+ return { type: "start", ...shared, turn: Number(frame.turn), step: Number(frame.step) };
24338
+ }
24339
+ if (frame.type === "chunk" && integer2(frame.index) && integer2(frame.time) && object2(frame.chunk) !== void 0) {
24340
+ return { type: "chunk", ...shared, index: Number(frame.index), time: Number(frame.time), chunk: frame.chunk };
24341
+ }
24342
+ const outcome = object2(frame.outcome);
24343
+ if (frame.type === "end" && integer2(frame.index)) {
24344
+ if (outcome?.kind === "abandoned")
24345
+ return { type: "end", ...shared, index: Number(frame.index), outcome: { kind: "abandoned" } };
24346
+ if (outcome?.kind === "committed" && integer2(outcome.seq) && (outcome.eventType === "assistant/message" || outcome.eventType === "assistant/attempt")) {
24347
+ return { type: "end", ...shared, index: Number(frame.index), outcome: { kind: "committed", eventType: outcome.eventType, seq: Number(outcome.seq) } };
24348
+ }
24349
+ }
24350
+ return void 0;
24351
+ }
24352
+ function publicArguments(text) {
24353
+ return parsedArguments(text) ?? "[Unparseable tool arguments]";
24354
+ }
24355
+ function parsedArguments(text) {
24356
+ if (text.length > MAX_TEXT)
24357
+ return void 0;
24358
+ try {
24359
+ return JSON.stringify(redactValue(JSON.parse(text)));
24360
+ } catch {
24361
+ return void 0;
24362
+ }
24363
+ }
24364
+ function bound2(text) {
24365
+ return text.length > MAX_TEXT ? `${text.slice(0, MAX_TEXT)}
24366
+ [TRUNCATED]` : text;
24367
+ }
24368
+ function integer2(value) {
24369
+ return Number.isSafeInteger(value) && Number(value) >= 0;
24370
+ }
24371
+ function identifier(value) {
24372
+ return typeof value === "string" && value.length > 0 && value.length <= 512;
24373
+ }
24374
+ function object2(value) {
24375
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
24376
+ }
24377
+
23680
24378
  // dist/src/connector.js
23681
24379
  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.";
23682
24380
  var LIVE_PROGRESS_MIN_INTERVAL_MS = 6e4;
@@ -23704,6 +24402,7 @@ var DshHostConnector = class {
23704
24402
  #publicationPromise;
23705
24403
  #heartbeatOffline = false;
23706
24404
  #liveProgressPromise = Promise.resolve();
24405
+ #activeLiveOutput;
23707
24406
  #lastLiveProgressKey;
23708
24407
  #lastLiveProgressAt = 0;
23709
24408
  #stopPromise;
@@ -23714,6 +24413,8 @@ var DshHostConnector = class {
23714
24413
  #activeExecutionSelection;
23715
24414
  #summaryScanSequence = 0;
23716
24415
  #hasSummaryHistory = false;
24416
+ #revisionPollPromise;
24417
+ #revisionSupported = false;
23717
24418
  #liveEventSequences = /* @__PURE__ */ new Set();
23718
24419
  #session;
23719
24420
  #visibleState = "connecting";
@@ -23818,7 +24519,8 @@ var DshHostConnector = class {
23818
24519
  ...executionProfiles === void 0 ? {} : {
23819
24520
  executionProfiles: cloneExecutionProfiles(executionProfiles)
23820
24521
  },
23821
- purpose: "execution"
24522
+ purpose: "execution",
24523
+ ...this.#host.contextDeletionVersion === 1 ? { contextDeletionVersion: 1 } : {}
23822
24524
  };
23823
24525
  }
23824
24526
  get executionRuntimeId() {
@@ -23851,6 +24553,7 @@ var DshHostConnector = class {
23851
24553
  }
23852
24554
  uploadLocalTurns() {
23853
24555
  return this.#withLocalSyncControl(async () => {
24556
+ await this.#refreshContentRevision();
23854
24557
  const before = this.localSyncStatus();
23855
24558
  await this.#flushOutbox(true);
23856
24559
  await this.#captureLocalTurns(0);
@@ -23873,6 +24576,15 @@ var DshHostConnector = class {
23873
24576
  this.#started = true;
23874
24577
  this.#automaticPolling = options.schedule !== false;
23875
24578
  this.#notifyLifecycle("connecting");
24579
+ if (this.#host.onLiveOutput !== void 0) {
24580
+ this.#listenerDisposers.push(this.#host.onLiveOutput((event) => {
24581
+ const active = this.#state?.activeRequest;
24582
+ const output2 = this.#activeLiveOutput;
24583
+ if (this.#stopped || active === void 0 || output2 === void 0 || event.sourceSessionId !== output2.sourceSessionId || event.sourceSessionId !== (active.contextExecution?.sessionId ?? this.#host.sessionId))
24584
+ return;
24585
+ output2.mapper.onEvent(event);
24586
+ }));
24587
+ }
23876
24588
  this.#listenerDisposers.push(this.#host.onSessionEvent((event) => {
23877
24589
  const active = this.#state?.activeRequest;
23878
24590
  if (active?.contextExecution !== void 0 && event.sourceSessionId !== active.contextExecution.sessionId)
@@ -23918,6 +24630,7 @@ var DshHostConnector = class {
23918
24630
  }));
23919
24631
  try {
23920
24632
  const session = await this.#verifySessionBinding();
24633
+ this.#revisionSupported = session.contentRevision !== void 0;
23921
24634
  this.#session = session;
23922
24635
  this.#notifyLifecycle("connecting");
23923
24636
  const storedState = await this.#stateStore.load();
@@ -23925,8 +24638,16 @@ var DshHostConnector = class {
23925
24638
  throw new Error("GatherThread Session head precedes the persisted DSH cursor; refusing identity reuse");
23926
24639
  }
23927
24640
  const mode = await this.#host.open();
24641
+ if (storedState?.projectionSessionId && (storedState.contentRevision ?? 0) > 0) {
24642
+ if (!this.#host.resetCanonicalContext)
24643
+ throw new Error("DSH deletion-safe projection requires an updated native facade");
24644
+ const restored = await this.#host.resetCanonicalContext(storedState.contentRevision);
24645
+ if (restored.sessionId !== storedState.projectionSessionId)
24646
+ throw new Error("DSH restored another native projection");
24647
+ }
23928
24648
  this.#state = this.#reconcileState(storedState, mode);
23929
24649
  await this.#stateStore.save(this.#state);
24650
+ await this.#refreshContentRevision();
23930
24651
  this.#runtime = await this.#api.registerRuntime(this.#runtimeRegistration());
23931
24652
  this.#assertRuntime(this.#runtime);
23932
24653
  this.#notifyLifecycle("idle");
@@ -23998,6 +24719,8 @@ var DshHostConnector = class {
23998
24719
  stop() {
23999
24720
  this.#stopPromise ??= (async () => {
24000
24721
  this.#stopped = true;
24722
+ const liveOutput = this.#activeLiveOutput;
24723
+ this.#activeLiveOutput = void 0;
24001
24724
  this.#notifyLifecycle("stopped");
24002
24725
  this.#lifecycleAbort.abort(new Error("DSH connector stopped"));
24003
24726
  if (this.#timer !== void 0) {
@@ -24011,6 +24734,7 @@ var DshHostConnector = class {
24011
24734
  for (const dispose of this.#listenerDisposers.splice(0))
24012
24735
  dispose();
24013
24736
  await this.#host.dispose();
24737
+ void liveOutput?.mapper.finish(false).catch(() => void 0);
24014
24738
  try {
24015
24739
  await this.#pollPromise;
24016
24740
  } catch {
@@ -24023,6 +24747,7 @@ var DshHostConnector = class {
24023
24747
  return this.#stopPromise;
24024
24748
  }
24025
24749
  async #poll() {
24750
+ await this.#refreshContentRevision();
24026
24751
  const state = this.#requireState();
24027
24752
  if (state.activeRequest !== void 0) {
24028
24753
  await this.#withExecutionPermit(() => this.#recoverActiveRequest());
@@ -24039,6 +24764,12 @@ var DshHostConnector = class {
24039
24764
  let scanned = 0;
24040
24765
  while (!this.#stopped) {
24041
24766
  const page = await this.#api.readEvents(this.#config.sessionId, scanCursor, this.#config.pollLimit);
24767
+ if (page.contentRevision !== void 0)
24768
+ this.#revisionSupported = true;
24769
+ if ((page.contentRevision ?? 0) !== (state.contentRevision ?? 0)) {
24770
+ await this.#refreshContentRevision();
24771
+ return this.#poll();
24772
+ }
24042
24773
  this.#validatePage(page.events, scanCursor);
24043
24774
  const passive = [];
24044
24775
  for (const event of page.events) {
@@ -24072,6 +24803,39 @@ var DshHostConnector = class {
24072
24803
  }
24073
24804
  throw new Error("DSH connector stopped during event replay");
24074
24805
  }
24806
+ async #refreshContentRevision() {
24807
+ const state = this.#requireState();
24808
+ if (!this.#revisionSupported && (state.contentRevision ?? 0) === 0)
24809
+ return;
24810
+ const page = await this.#api.readEvents(this.#config.sessionId, 0, 1);
24811
+ const revision = page.contentRevision ?? 0;
24812
+ if (!Number.isSafeInteger(revision) || revision < (state.contentRevision ?? 0))
24813
+ throw new Error("Stale DSH shared context revision");
24814
+ if (revision === (state.contentRevision ?? 0)) {
24815
+ if (revision > 0 && state.projectionSessionId && this.#host.resetCanonicalContext) {
24816
+ const restored = await this.#host.resetCanonicalContext(revision);
24817
+ if (restored.sessionId !== state.projectionSessionId)
24818
+ throw new Error("DSH clean projection binding changed on reconnect");
24819
+ }
24820
+ return;
24821
+ }
24822
+ state.localOnlySessionIds = [.../* @__PURE__ */ new Set([...state.localOnlySessionIds ?? [], this.#config.dshSessionId, this.#host.sessionId])];
24823
+ state.outbox = [];
24824
+ delete state.activeRequest;
24825
+ this.#activeStatuses = [];
24826
+ this.#activeExecutionSelection = void 0;
24827
+ this.#summaryScanSequence = 0;
24828
+ this.#hasSummaryHistory = false;
24829
+ await this.#stateStore.save(state);
24830
+ if (this.#host.resetCanonicalContext) {
24831
+ const replacement = await this.#host.resetCanonicalContext(revision);
24832
+ state.projectionSessionId = replacement.sessionId;
24833
+ state.projectionCursor = 0;
24834
+ state.publishedDshSequence = this.#host.currentSequence();
24835
+ }
24836
+ state.contentRevision = revision;
24837
+ await this.#stateStore.save(state);
24838
+ }
24075
24839
  async #executeRequest(request, selection) {
24076
24840
  if (this.#stopped)
24077
24841
  throw new Error("DSH connector stopped before claiming an Agent request");
@@ -24090,6 +24854,8 @@ var DshHostConnector = class {
24090
24854
  await this.#projectCanonicalBatch([request], request.sequence);
24091
24855
  return { claimed: false, completed: false };
24092
24856
  }
24857
+ if ((claim2.contentRevision ?? state.contentRevision ?? 0) !== (state.contentRevision ?? 0))
24858
+ throw new Error("context_changed");
24093
24859
  const quotedEvent = request.replyTo ? (await this.#readThroughRequest(request.id, request.sequence)).find((event) => event.id === request.replyTo) : void 0;
24094
24860
  const prompt = buildDshRequestPrompt(request, quotedEvent);
24095
24861
  const context = await this.#contextForRequest(request);
@@ -24102,6 +24868,7 @@ var DshHostConnector = class {
24102
24868
  if (prepared !== void 0 && prepared.fromSequence !== baseline)
24103
24869
  throw new Error("DSH context preparation returned an inconsistent sequence");
24104
24870
  state.activeRequest = {
24871
+ contentRevision: state.contentRevision ?? 0,
24105
24872
  requestId: request.id,
24106
24873
  requestSequence: request.sequence,
24107
24874
  dshFromSequence: baseline,
@@ -24115,7 +24882,7 @@ var DshHostConnector = class {
24115
24882
  this.#activeExecutionSelection = selection;
24116
24883
  this.#liveEventSequences.clear();
24117
24884
  await this.#stateStore.save(state);
24118
- const result = await this.#host.prompt(prompt, selection, prepared?.sessionId);
24885
+ const result = await this.#promptWithLiveOutput(prompt, selection, prepared?.sessionId);
24119
24886
  if (result.fromSequence !== baseline || result.toSequence < result.fromSequence) {
24120
24887
  throw new Error("DSH Host prompt returned an inconsistent durable event range");
24121
24888
  }
@@ -24137,7 +24904,7 @@ var DshHostConnector = class {
24137
24904
  throw new Error("GatherThread history summary request has invalid source metadata");
24138
24905
  if (selectedOnly)
24139
24906
  this.#hasSummaryHistory = true;
24140
- if (!selectedOnly && !await this.#sessionHasSummaryBefore(request.sequence))
24907
+ if (!selectedOnly && (this.#requireState().contentRevision ?? 0) === 0 && !await this.#sessionHasSummaryBefore(request.sequence))
24141
24908
  return void 0;
24142
24909
  if (!selectedOnly && this.#api.readContext === void 0) {
24143
24910
  throw new Error("GatherThread summarized context is unavailable; update the connector before continuing");
@@ -24145,7 +24912,9 @@ var DshHostConnector = class {
24145
24912
  if (this.#host.prepareContextExecution === void 0) {
24146
24913
  throw new Error("DSH isolated context execution is unavailable; refusing to run a summary-aware request in native history");
24147
24914
  }
24148
- 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);
24915
+ 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);
24916
+ if ((received.content_revision ?? 0) !== (this.#requireState().contentRevision ?? 0))
24917
+ throw new Error("context_changed");
24149
24918
  const historyContext = { ...received, items: received.items.map((item) => ({ ...item, content: redactText(item.content) })) };
24150
24919
  return { historyContext, selectedOnly };
24151
24920
  }
@@ -24243,6 +25012,10 @@ var DshHostConnector = class {
24243
25012
  throw new Error("Active GatherThread request no longer has a recoverable claim");
24244
25013
  }
24245
25014
  const claimAttempt = claim2.attemptCount ?? active.claimAttempt ?? 1;
25015
+ if ((active.contentRevision ?? 0) !== (state.contentRevision ?? 0) || (claim2.contentRevision ?? active.contentRevision ?? 0) !== (active.contentRevision ?? 0)) {
25016
+ await this.#retireFencedActiveRequest(state, active);
25017
+ return;
25018
+ }
24246
25019
  active.claimAttempt = claimAttempt;
24247
25020
  if (active.dshToSequence !== void 0) {
24248
25021
  state.outbox = state.outbox.map((operation) => {
@@ -24315,7 +25088,7 @@ var DshHostConnector = class {
24315
25088
  this.#activeStatuses = [];
24316
25089
  this.#liveEventSequences.clear();
24317
25090
  await this.#stateStore.save(state);
24318
- const result = await this.#host.prompt(continuation, selection, execution?.sessionId);
25091
+ const result = await this.#promptWithLiveOutput(continuation, selection, execution?.sessionId);
24319
25092
  if (result.fromSequence !== baseline || result.toSequence < result.fromSequence) {
24320
25093
  throw new Error("DSH Host recovery prompt returned an inconsistent durable event range");
24321
25094
  }
@@ -24344,6 +25117,94 @@ var DshHostConnector = class {
24344
25117
  await this.#flushOutbox();
24345
25118
  await this.#finalizeDeliveredRequest();
24346
25119
  }
25120
+ async #promptWithLiveOutput(text, selection, executionSessionId) {
25121
+ const active = this.#requireState().activeRequest;
25122
+ if (active === void 0)
25123
+ throw new Error("No claimed DSH request owns live output");
25124
+ const requestId = active.requestId;
25125
+ const claimAttempt = active.claimAttempt ?? 1;
25126
+ const fromSequence = active.dshFromSequence;
25127
+ const runtime = this.#requireRuntime();
25128
+ const sourceSessionId = executionSessionId ?? this.#host.sessionId;
25129
+ const publisher = createLiveOutputPublisher({
25130
+ publish: async (update) => {
25131
+ const publication = this.#liveProgressPromise.then(async () => {
25132
+ const current = this.#state?.activeRequest;
25133
+ 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)
25134
+ return false;
25135
+ await this.#api.appendAgentProgress(this.#config.sessionId, requestId, {
25136
+ runtimeId: runtime.id,
25137
+ claimAttempt,
25138
+ contentRevision: active.contentRevision ?? 0,
25139
+ idempotencyKey: `${this.#config.deviceId}:${digest2(requestId).slice(0, 24)}:${claimAttempt}:live-${update.id}`,
25140
+ payload: { ...liveOutputPayload(update), capture_fidelity: "harness_transcript", source_harness: "deepseek-harness" },
25141
+ observedModel: selection.model,
25142
+ ...selection.reasoningEffort === void 0 ? {} : { observedReasoningEffort: selection.reasoningEffort }
25143
+ });
25144
+ return true;
25145
+ });
25146
+ this.#liveProgressPromise = publication.then(() => void 0).catch((error62) => {
25147
+ this.#onBackgroundError?.(publicError(error62));
25148
+ });
25149
+ return publication.catch(() => false);
25150
+ }
25151
+ });
25152
+ const output2 = { publisher, mapper: createDshLiveEventMapper(publisher), sourceSessionId };
25153
+ this.#activeLiveOutput = output2;
25154
+ const abort = new AbortController();
25155
+ const abortLifecycle = () => abort.abort(this.#lifecycleAbort.signal.reason);
25156
+ this.#lifecycleAbort.signal.addEventListener("abort", abortLifecycle, { once: true });
25157
+ const verifyRevision = async () => {
25158
+ if (!this.#revisionSupported && (active.contentRevision ?? 0) === 0)
25159
+ return;
25160
+ try {
25161
+ const page = await this.#api.readEvents(this.#config.sessionId, 0, 1);
25162
+ if ((page.contentRevision ?? 0) !== (active.contentRevision ?? 0))
25163
+ abort.abort(new Error("context_changed"));
25164
+ } catch (error62) {
25165
+ abort.abort(error62);
25166
+ }
25167
+ };
25168
+ const timer = setInterval(() => {
25169
+ if (this.#revisionPollPromise)
25170
+ return;
25171
+ const poll = verifyRevision();
25172
+ this.#revisionPollPromise = poll;
25173
+ void poll.finally(() => {
25174
+ if (this.#revisionPollPromise === poll)
25175
+ this.#revisionPollPromise = void 0;
25176
+ });
25177
+ }, 1e3);
25178
+ timer.unref();
25179
+ try {
25180
+ await verifyRevision();
25181
+ abort.signal.throwIfAborted();
25182
+ const result = await this.#host.prompt(text, selection, executionSessionId, abort.signal);
25183
+ await verifyRevision();
25184
+ abort.signal.throwIfAborted();
25185
+ await output2.mapper.finish();
25186
+ return result;
25187
+ } catch (error62) {
25188
+ if (abort.signal.aborted) {
25189
+ const state = this.#requireState();
25190
+ state.outbox = state.outbox.filter((operation) => !outboxBelongsToRequest(operation, requestId));
25191
+ delete state.activeRequest;
25192
+ this.#activeExecutionSelection = void 0;
25193
+ await this.#stateStore.save(state);
25194
+ }
25195
+ throw error62;
25196
+ } finally {
25197
+ clearInterval(timer);
25198
+ this.#lifecycleAbort.signal.removeEventListener("abort", abortLifecycle);
25199
+ await this.#revisionPollPromise;
25200
+ if (this.#activeLiveOutput === output2)
25201
+ this.#activeLiveOutput = void 0;
25202
+ if (this.#stopped)
25203
+ void output2.mapper.finish(false).catch(() => void 0);
25204
+ else
25205
+ await output2.mapper.finish(false);
25206
+ }
25207
+ }
24347
25208
  #queueLiveProgress(idSuffix, payload, throttle = true) {
24348
25209
  const active = this.#state?.activeRequest;
24349
25210
  const runtime = this.#runtime;
@@ -24353,6 +25214,9 @@ var DshHostConnector = class {
24353
25214
  const claimAttempt = active.claimAttempt ?? 1;
24354
25215
  const progressKey = `${requestId}:${String(claimAttempt)}`;
24355
25216
  const now = Date.now();
25217
+ const streamedAt = this.#activeLiveOutput?.publisher.lastPublishedAt();
25218
+ if (throttle && streamedAt !== void 0 && now - streamedAt < LIVE_PROGRESS_MIN_INTERVAL_MS)
25219
+ return;
24356
25220
  if (throttle && this.#lastLiveProgressKey === progressKey && now - this.#lastLiveProgressAt < LIVE_PROGRESS_MIN_INTERVAL_MS) {
24357
25221
  return;
24358
25222
  }
@@ -24363,7 +25227,7 @@ var DshHostConnector = class {
24363
25227
  const idempotencyKey = `${this.#config.deviceId}:${digest2(requestId).slice(0, 24)}:${String(claimAttempt)}:${idSuffix}`;
24364
25228
  this.#liveProgressPromise = this.#liveProgressPromise.then(async () => {
24365
25229
  const current = this.#state?.activeRequest;
24366
- if (current?.requestId !== requestId || (current.claimAttempt ?? 1) !== claimAttempt)
25230
+ if (this.#stopped || current?.requestId !== requestId || (current.claimAttempt ?? 1) !== claimAttempt || this.#runtime?.id !== runtime.id)
24367
25231
  return;
24368
25232
  const selection = this.#activeExecutionSelection;
24369
25233
  if (selection === void 0)
@@ -24371,6 +25235,7 @@ var DshHostConnector = class {
24371
25235
  await this.#api.appendAgentProgress(this.#config.sessionId, requestId, {
24372
25236
  runtimeId: runtime.id,
24373
25237
  claimAttempt,
25238
+ contentRevision: active.contentRevision ?? 0,
24374
25239
  idempotencyKey,
24375
25240
  payload,
24376
25241
  observedModel: selection.model,
@@ -24388,11 +25253,15 @@ var DshHostConnector = class {
24388
25253
  }
24389
25254
  async #projectCanonicalBatch(events, throughSequence) {
24390
25255
  const state = this.#requireState();
25256
+ if (state.localOnlySessionIds?.includes(this.#host.sessionId))
25257
+ return;
24391
25258
  if (throughSequence <= state.projectionCursor)
24392
25259
  return;
24393
25260
  const runtime = this.#requireRuntime();
24394
25261
  const projections = [];
24395
25262
  for (const event of events) {
25263
+ if (event.deleted)
25264
+ continue;
24396
25265
  if (event.type === "agent_request" && asObject3(event.payload)?.history_summary !== void 0) {
24397
25266
  this.#hasSummaryHistory = true;
24398
25267
  continue;
@@ -24437,6 +25306,8 @@ var DshHostConnector = class {
24437
25306
  }
24438
25307
  async #captureLocalTurns(basedOnSequence) {
24439
25308
  const state = this.#requireState();
25309
+ if (state.localOnlySessionIds?.includes(this.#host.sessionId))
25310
+ return;
24440
25311
  if (state.activeRequest !== void 0 || state.outbox.length > 0)
24441
25312
  return;
24442
25313
  const current = this.#host.currentSequence();
@@ -24453,6 +25324,7 @@ var DshHostConnector = class {
24453
25324
  input: {
24454
25325
  localTurnId: turn.localTurnId,
24455
25326
  runtimeId: runtime.id,
25327
+ contentRevision: state.contentRevision ?? 0,
24456
25328
  basedOnSequence: basedOnSequence ?? state.serverCursor,
24457
25329
  occurredAt: turn.occurredAt,
24458
25330
  observedModel: this.#config.model,
@@ -24566,7 +25438,10 @@ var DshHostConnector = class {
24566
25438
  }
24567
25439
  }
24568
25440
  });
24569
- return operations;
25441
+ return operations.map((operation) => ({
25442
+ ...operation,
25443
+ input: { ...operation.input, contentRevision: this.#requireState().activeRequest?.contentRevision ?? 0 }
25444
+ }));
24570
25445
  }
24571
25446
  async #flushOutbox(includeLocalTurns = true) {
24572
25447
  const state = this.#requireState();
@@ -24575,6 +25450,11 @@ var DshHostConnector = class {
24575
25450
  const operation = state.outbox[0];
24576
25451
  if (operation === void 0)
24577
25452
  break;
25453
+ if ((operation.input.contentRevision ?? 0) !== (state.contentRevision ?? 0) || operation.kind === "local_turn" && state.localOnlySessionIds?.includes(this.#host.sessionId)) {
25454
+ state.outbox.shift();
25455
+ await this.#stateStore.save(state);
25456
+ continue;
25457
+ }
24578
25458
  if (operation.kind === "local_turn" && !includeLocalTurns)
24579
25459
  break;
24580
25460
  if (operation.input.runtimeId !== runtime.id) {
@@ -24909,6 +25789,8 @@ function captureCompletedLocalTurns(events, fromSequence, dshSessionId) {
24909
25789
  return { turns, safeThroughSequence };
24910
25790
  }
24911
25791
  function hasCompletedDshLocalTurn(events, dshSessionId) {
25792
+ if (events.some((event) => event.type === "user/message" && /^gatherthread-retired:[0-9]+$/.test(String(asObject3(event.data)?.id)) && asObject3(asObject3(event.data)?.source)?.plugin === "gatherthread"))
25793
+ return false;
24912
25794
  return captureCompletedLocalTurns(events, 0, dshSessionId).turns.length > 0;
24913
25795
  }
24914
25796
  function isDirectLocalUserMessage(event) {
@@ -24979,16 +25861,16 @@ function asObject3(value) {
24979
25861
  }
24980
25862
 
24981
25863
  // dist/src/dsh-compat.js
24982
- import { createHash as createHash7 } from "node:crypto";
25864
+ import { createHash as createHash7, randomUUID as randomUUID5 } from "node:crypto";
24983
25865
  var DSH_COMPATIBILITY = Object.freeze({
24984
- tag: "dsh-v0.1.3-alpha.1",
24985
- version: "0.1.3-alpha.1",
24986
- commit: "d347e703908d0406b7a7ef80e3a0e594d86b2215",
25866
+ tag: "dsh-v0.1.7-rc.2",
25867
+ version: "0.1.7-rc.2",
25868
+ commit: "477b4f420553e8a52c2fbccc464d7561b239c443",
24987
25869
  profile: "headless"
24988
25870
  });
24989
25871
  var DSH_NPM_COMPATIBILITY = Object.freeze({
24990
25872
  package: "@deepseek-ai/dsh",
24991
- version: "0.1.2-rc.1",
25873
+ version: "0.1.7-rc.2",
24992
25874
  profile: "web",
24993
25875
  persistenceProbe: "list"
24994
25876
  });
@@ -25018,16 +25900,19 @@ function createDshHostFacade(options) {
25018
25900
  const sessionTitle = options.sessionTitle === void 0 ? void 0 : requireService(context, "sessionTitle", ["rename"]);
25019
25901
  const workspaceRegistry = options.workspaceTitle === void 0 ? void 0 : requireService(context, "workspaceRegistry", ["create"]);
25020
25902
  const eventSubscribers = /* @__PURE__ */ new Set();
25903
+ const liveSubscribers = /* @__PURE__ */ new Set();
25021
25904
  const statusSubscribers = /* @__PURE__ */ new Set();
25022
25905
  const listenerDisposers = [];
25023
25906
  const lifecycleAbort = new AbortController();
25024
25907
  let handle;
25025
25908
  let executionHandle;
25026
- let contextPreparationPromise;
25909
+ let nativeSessionId = options.sessionId;
25910
+ let contentRevision = 0;
25911
+ let contextOperationPromise;
25027
25912
  const executionBinding = JSON.stringify({ nativeSessionId: options.sessionId, ...options.contextBinding });
25028
- const executionSessionId = `gatherthread-execution-${createHash7("sha256").update(executionBinding).digest("hex").slice(0, 32)}`;
25029
- const executionOwnerId = `gatherthread-execution-owner:${createHash7("sha256").update(executionBinding).digest("hex")}`;
25030
- const executionOwnerText = JSON.stringify({
25913
+ let executionSessionId = `gatherthread-execution-${createHash7("sha256").update(executionBinding).digest("hex").slice(0, 32)}`;
25914
+ let executionOwnerId = `gatherthread-execution-owner:${createHash7("sha256").update(executionBinding).digest("hex")}`;
25915
+ let executionOwnerText = JSON.stringify({
25031
25916
  version: 1,
25032
25917
  owner: "gatherthread",
25033
25918
  native_session_id: options.sessionId,
@@ -25040,19 +25925,76 @@ function createDshHostFacade(options) {
25040
25925
  let knownProjectionMessageIds;
25041
25926
  let disposePromise;
25042
25927
  let disposed = false;
25928
+ let livePrompt;
25929
+ const emitLive = (owner, event) => {
25930
+ if (disposed || livePrompt !== owner || owner.closed)
25931
+ return;
25932
+ for (const subscriber of liveSubscribers)
25933
+ subscriber(event);
25934
+ };
25043
25935
  listenerDisposers.push(context.on("session/event", (...args) => {
25044
25936
  const session = asSession(args[0]);
25045
25937
  const event = asSessionEvent(args[1]);
25046
- if (session === void 0 || session.id !== options.sessionId && session.id !== executionHandle?.agent.session.id || event === void 0)
25938
+ if (session === void 0 || session.id !== nativeSessionId && session.id !== executionHandle?.agent.session.id || event === void 0)
25047
25939
  return;
25048
25940
  for (const subscriber of eventSubscribers)
25049
25941
  subscriber({ ...event, sourceSessionId: session.id });
25942
+ const owner = livePrompt;
25943
+ if (owner === void 0 || owner.closed || session !== owner.agent.session)
25944
+ return;
25945
+ const data = asObject4(event.data);
25946
+ if (event.type === "turn/start" && owner.turn === void 0 && Number.isSafeInteger(data?.turn)) {
25947
+ owner.turn = Number(data.turn);
25948
+ }
25949
+ if (owner.turn === void 0 || data?.turn !== void 0 && data.turn !== owner.turn)
25950
+ return;
25951
+ if (event.type === "step/start" && Number.isSafeInteger(data?.step))
25952
+ owner.step = Number(data.step);
25953
+ if (["assistant/message", "assistant/attempt", "tool/call", "tool/result", "todo/write"].includes(event.type)) {
25954
+ emitLive(owner, { kind: "session-event", sourceSessionId: session.id, event });
25955
+ }
25956
+ if (event.type === "turn/end")
25957
+ owner.closed = true;
25958
+ }, { global: true }));
25959
+ listenerDisposers.push(context.on("agent/assistant-stream", (...args) => {
25960
+ const owner = livePrompt;
25961
+ const payload = asObject4(args[0]);
25962
+ if (owner === void 0 || !owner.nativeFrames || owner.turn === void 0 || payload?.agent !== owner.agent)
25963
+ return;
25964
+ const frame = parseDshAssistantStreamFrame(payload.frame);
25965
+ if (frame === void 0 || frame.type === "start" && frame.turn !== owner.turn)
25966
+ return;
25967
+ emitLive(owner, { kind: "assistant-stream", sourceSessionId: owner.agent.session.id, frame });
25968
+ }, { global: true }));
25969
+ listenerDisposers.push(context.on("llm/stream", (...args) => {
25970
+ const request = asObject4(args[0]);
25971
+ const next = args[1];
25972
+ if (typeof next !== "function")
25973
+ return;
25974
+ const stream = next();
25975
+ const owner = livePrompt;
25976
+ 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]))
25977
+ return stream;
25978
+ const attemptId = randomUUID5();
25979
+ const publish = (frame) => emitLive(owner, {
25980
+ kind: "assistant-stream",
25981
+ sourceSessionId: owner.agent.session.id,
25982
+ frame
25983
+ });
25984
+ return (async function* () {
25985
+ let index = 0;
25986
+ publish({ type: "start", attemptId, revision: ++owner.revision, turn: owner.turn, step: owner.step });
25987
+ for await (const chunk of stream) {
25988
+ publish({ type: "chunk", attemptId, revision: ++owner.revision, index: index++, time: Date.now(), chunk });
25989
+ yield chunk;
25990
+ }
25991
+ })();
25050
25992
  }, { global: true }));
25051
25993
  listenerDisposers.push(context.on("agent/status", (...args) => {
25052
25994
  const payload = asObject4(args[0]);
25053
25995
  const agent = payload ? asAgent(payload.agent) : void 0;
25054
25996
  const status = payload?.status;
25055
- if (agent === void 0 || agent.session.id !== options.sessionId && agent.session.id !== executionHandle?.agent.session.id || status !== "running" && status !== "idle")
25997
+ if (agent === void 0 || agent.session.id !== nativeSessionId && agent.session.id !== executionHandle?.agent.session.id || status !== "running" && status !== "idle")
25056
25998
  return;
25057
25999
  for (const subscriber of statusSubscribers)
25058
26000
  subscriber(status, agent.session.id);
@@ -25064,7 +26006,7 @@ function createDshHostFacade(options) {
25064
26006
  await releaseHandle();
25065
26007
  throw new Error("DSH host facade was disposed during open");
25066
26008
  }
25067
- if (acquired.agent.session.id !== options.sessionId) {
26009
+ if (acquired.agent.session.id !== nativeSessionId) {
25068
26010
  await releaseHandle();
25069
26011
  throw new Error("DSH Host returned an agent for an unexpected Session identity");
25070
26012
  }
@@ -25091,13 +26033,13 @@ function createDshHostFacade(options) {
25091
26033
  const parent = requireAgent(handle);
25092
26034
  if (parent.status !== "idle")
25093
26035
  throw new Error("Native DSH Agent must be idle before isolated context execution");
25094
- if (parent.session.header?.cwd !== options.workspacePath || agents.get?.(options.sessionId) !== parent) {
26036
+ if (parent.session.header?.cwd !== options.workspacePath || agents.get?.(nativeSessionId) !== parent) {
25095
26037
  throw new Error("Native DSH workspace or live owner does not match the isolated context binding");
25096
26038
  }
25097
26039
  };
25098
26040
  const assertExecutionOwnership = (agent) => {
25099
26041
  const session = agent.session;
25100
- if (session.id !== executionSessionId || session.header?.cwd !== options.workspacePath || session.header.parentSession !== options.sessionId || session.header.origin !== "subagent") {
26042
+ if (session.id !== executionSessionId || session.header?.cwd !== options.workspacePath || session.header.parentSession !== nativeSessionId || session.header.origin !== "subagent") {
25101
26043
  throw new Error("DSH isolated execution Session ownership does not match this native binding");
25102
26044
  }
25103
26045
  if (agents.get !== void 0 && agents.get(executionSessionId) !== agent) {
@@ -25118,6 +26060,118 @@ function createDshHostFacade(options) {
25118
26060
  throw new Error("DSH isolated execution Session contains local manual input; refusing to replace or execute it");
25119
26061
  }
25120
26062
  };
26063
+ const recordedRevision = (session) => session.snapshotEvents(0).reduce((highest, value) => {
26064
+ const event = asObject4(value), data = asObject4(event?.data);
26065
+ const id = data?.id;
26066
+ if (event?.type !== "user/message" || typeof id !== "string" || !/^gatherthread-retired:[0-9]+$/.test(id) || asObject4(data?.source)?.kind !== "plugin" || asObject4(data?.source)?.plugin !== "gatherthread")
26067
+ return highest;
26068
+ const revision = Number(id.slice("gatherthread-retired:".length));
26069
+ return Number.isSafeInteger(revision) ? Math.max(highest, revision) : highest;
26070
+ }, 0);
26071
+ const resetCanonicalContext = async (revision) => {
26072
+ if (!Number.isSafeInteger(revision) || revision < 1 || revision < contentRevision)
26073
+ throw new Error("Stale DSH content revision");
26074
+ if (options.contextBinding === void 0 || Object.values(options.contextBinding).some((value) => !value) || typeof agents.get !== "function")
26075
+ throw new Error("DSH context reset requires an explicit owned GatherThread binding");
26076
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26077
+ await open7();
26078
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26079
+ if (promptActive || projectionActive)
26080
+ throw new Error("Wait for the active DSH turn before replacing its projection");
26081
+ const parent = requireAgent(handle);
26082
+ if (revision < recordedRevision(parent.session))
26083
+ throw new Error("Retired DSH revision cannot resume");
26084
+ assertExecutionParentIdle();
26085
+ const targetId = `gatherthread-projection-${createHash7("sha256").update(`${executionBinding}:${revision}`).digest("hex").slice(0, 32)}`;
26086
+ if (nativeSessionId === targetId && contentRevision === revision)
26087
+ return { sessionId: targetId };
26088
+ const ownerId = `gatherthread-projection-owner:${createHash7("sha256").update(`${executionBinding}:${revision}`).digest("hex")}`;
26089
+ const ownerText = JSON.stringify({ version: 1, binding: options.contextBinding, native_session_id: options.sessionId, content_revision: revision });
26090
+ projectionActive = true;
26091
+ let candidate;
26092
+ try {
26093
+ const retired = await createIsolatedMessage(`gatherthread-retired:${revision}`, "GatherThread retired this context. Continue here locally only.", options);
26094
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26095
+ if (recordedRevision(parent.session) < revision) {
26096
+ parent.session.append("user/message", retired, { surfaceOp: "append" });
26097
+ await sessions.flush(parent.session);
26098
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26099
+ }
26100
+ if (agents.get?.(targetId) !== void 0)
26101
+ throw new Error("DSH clean projection already has another live owner");
26102
+ const stored = await hasPersistedSession(persistence, targetId, lifecycleAbort.signal);
26103
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26104
+ const presets = asObject4(context.get("agentPresets"));
26105
+ const setup = (ctx) => {
26106
+ if (presets !== void 0) {
26107
+ if (typeof presets.composeFrom !== "function" || typeof presets.composedPreset !== "function")
26108
+ throw new Error("Native DSH tool inheritance unavailable");
26109
+ const expected = presets.composedPreset(parent.ctx);
26110
+ if (presets.composeFrom(ctx, parent.ctx) !== expected)
26111
+ throw new Error("DSH clean projection did not inherit native tools");
26112
+ }
26113
+ };
26114
+ candidate = await (stored ? agents.resume({
26115
+ resumeSessionId: targetId,
26116
+ agentOptions: { provider: options.provider, model: options.model },
26117
+ signal: lifecycleAbort.signal,
26118
+ setup
26119
+ }) : agents.create({
26120
+ sessionId: targetId,
26121
+ meta: { cwd: options.workspacePath, parentSession: options.sessionId, origin: "subagent" },
26122
+ agentOptions: { provider: options.provider, model: options.model },
26123
+ signal: lifecycleAbort.signal,
26124
+ setup
26125
+ }));
26126
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26127
+ const agent = candidate.agent;
26128
+ 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)
26129
+ throw new Error("DSH clean projection ownership is invalid");
26130
+ if (!stored) {
26131
+ if (agent.session.seq !== 0)
26132
+ throw new Error("DSH clean projection is not fresh");
26133
+ const owner = await createIsolatedMessage(ownerId, ownerText, options);
26134
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26135
+ agent.session.append("user/message", owner, { surfaceOp: "append" });
26136
+ }
26137
+ const events = agent.session.snapshotEvents(0).map(asObject4);
26138
+ if (!events.some((event) => {
26139
+ const data = asObject4(event?.data), source = asObject4(data?.source);
26140
+ 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;
26141
+ })) {
26142
+ throw new Error("DSH clean projection is missing its durable owner marker");
26143
+ }
26144
+ await sessions.flush(agent.session);
26145
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26146
+ if (sessionTitle && options.sessionTitle) {
26147
+ await sessionTitle.rename(agent.session, options.sessionTitle);
26148
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26149
+ }
26150
+ if (workspaceRegistry && options.workspaceTitle) {
26151
+ const workspace = await workspaceRegistry.create(options.workspacePath, options.workspaceTitle);
26152
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26153
+ await workspace.attachSession(targetId);
26154
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26155
+ }
26156
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26157
+ await releaseExecutionHandle();
26158
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26159
+ await releaseHandle();
26160
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26161
+ handle = candidate;
26162
+ candidate = void 0;
26163
+ nativeSessionId = targetId;
26164
+ contentRevision = revision;
26165
+ knownProjectionMessageIds = void 0;
26166
+ return { sessionId: targetId };
26167
+ } finally {
26168
+ try {
26169
+ await candidate?.dispose();
26170
+ } finally {
26171
+ projectionActive = false;
26172
+ }
26173
+ }
26174
+ };
25121
26175
  const prepareContextExecution = async (input2) => {
25122
26176
  if (disposed)
25123
26177
  throw new Error("DSH host facade is disposed");
@@ -25138,6 +26192,30 @@ function createDshHostFacade(options) {
25138
26192
  if (disposed || promptActive || projectionActive)
25139
26193
  throw new Error("DSH host facade permits only one active write");
25140
26194
  const parent = requireAgent(handle);
26195
+ const revision = historyContext.content_revision ?? 0;
26196
+ if (revision < Math.max(contentRevision, recordedRevision(parent.session)))
26197
+ throw new Error("Stale retired DSH context revision");
26198
+ if (revision !== contentRevision || revision > 0 && !executionSessionId.endsWith(createHash7("sha256").update(`${executionBinding}:${revision}`).digest("hex").slice(0, 32))) {
26199
+ await releaseExecutionHandle();
26200
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26201
+ contentRevision = revision;
26202
+ const binding = `${executionBinding}:${revision}`;
26203
+ executionSessionId = `gatherthread-execution-${createHash7("sha256").update(binding).digest("hex").slice(0, 32)}`;
26204
+ executionOwnerId = `gatherthread-execution-owner:${createHash7("sha256").update(binding).digest("hex")}`;
26205
+ executionOwnerText = JSON.stringify({
26206
+ version: 1,
26207
+ owner: "gatherthread",
26208
+ native_session_id: options.sessionId,
26209
+ execution_session_id: executionSessionId,
26210
+ binding: options.contextBinding,
26211
+ content_revision: revision
26212
+ });
26213
+ const marker = await createIsolatedMessage(`gatherthread-retired:${revision}`, "GatherThread previous execution context is local only.", options);
26214
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26215
+ parent.session.append("user/message", marker, { surfaceOp: "append" });
26216
+ await sessions.flush(parent.session);
26217
+ throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
26218
+ }
25141
26219
  assertExecutionParentIdle();
25142
26220
  const presets = asObject4(context.get("agentPresets"));
25143
26221
  let parentPreset;
@@ -25146,7 +26224,8 @@ function createDshHostFacade(options) {
25146
26224
  throw new Error("Pinned DSH public preset inheritance API is unavailable; refusing an isolated Agent without native tools");
25147
26225
  }
25148
26226
  parentPreset = presets.composedPreset(parent.ctx);
25149
- if (parentPreset === void 0 && (!Array.isArray(presets.roots) || presets.roots.length > 0)) {
26227
+ const roots = Array.isArray(presets.roots) ? presets.roots : void 0;
26228
+ if (parentPreset === void 0 && roots !== void 0 && roots.length > 0) {
25150
26229
  throw new Error("Native DSH Agent has no composed preset; restore its tool composition before using summarized context");
25151
26230
  }
25152
26231
  }
@@ -25180,7 +26259,7 @@ function createDshHostFacade(options) {
25180
26259
  sessionId: executionSessionId,
25181
26260
  meta: {
25182
26261
  cwd: options.workspacePath,
25183
- parentSession: options.sessionId,
26262
+ parentSession: nativeSessionId,
25184
26263
  origin: "subagent",
25185
26264
  ...parentPreset === void 0 ? {} : { agentPreset: parentPreset }
25186
26265
  },
@@ -25194,7 +26273,7 @@ function createDshHostFacade(options) {
25194
26273
  }
25195
26274
  const agent2 = operationAgent(executionSessionId);
25196
26275
  if (!stored) {
25197
- 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") {
26276
+ 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") {
25198
26277
  throw new Error("DSH did not create a fresh, owned isolated execution Session");
25199
26278
  }
25200
26279
  const ownerMessage = await createIsolatedMessage(executionOwnerId, executionOwnerText, options);
@@ -25230,7 +26309,7 @@ ${JSON.stringify(historyContext.items)}`;
25230
26309
  const nodes = agent.session.surface?.nodes;
25231
26310
  if (!Array.isArray(nodes) || nodes.some((seq) => !Number.isSafeInteger(seq) || seq < 0 || seq >= agent.session.seq) || new Set(nodes).size !== nodes.length)
25232
26311
  throw new Error("Pinned DSH public Session surface API is unavailable or invalid");
25233
- agent.session.append("user/message", message, nodes.length === 0 ? { surfaceOp: "append" } : { surfaceOp: { op: "replace", start: nodes[0], end: nodes.at(-1) }, sourceEventSeqs: [...nodes] });
26312
+ agent.session.append("user/message", message, nodes.length === 0 ? { surfaceOp: "append" } : { surfaceOp: { op: "replace", startSeq: nodes[0], endSeq: nodes.at(-1) }, sourceEventSeqs: [...nodes] });
25234
26313
  }
25235
26314
  await sessions.flush(agent.session);
25236
26315
  throwIfDisposed(disposed, lifecycleAbort.signal, "projection");
@@ -25239,11 +26318,11 @@ ${JSON.stringify(historyContext.items)}`;
25239
26318
  projectionActive = false;
25240
26319
  }
25241
26320
  };
25242
- const setupNativeAgent = async (agentContext) => {
26321
+ const setupNativeAgent = async (agentContext, agentValue) => {
25243
26322
  const presets = asObject4(context.get("agentPresets"));
25244
26323
  if (presets === void 0 || Array.isArray(presets.roots) && presets.roots.length === 0)
25245
26324
  return;
25246
- const agent = asAgent(asObject4(agentContext)?.agent);
26325
+ const agent = asAgent(agentValue);
25247
26326
  const projections = asObject4(context.get("sessionProjections"));
25248
26327
  if (agent === void 0 || typeof presets.mount !== "function" || typeof projections?.stateOf !== "function") {
25249
26328
  throw new Error("Pinned DSH public native preset composition API is unavailable");
@@ -25346,7 +26425,8 @@ ${JSON.stringify(historyContext.items)}`;
25346
26425
  return parsed;
25347
26426
  });
25348
26427
  };
25349
- const prompt = async (text, requestedSelection, requestedExecutionId) => {
26428
+ const prompt = async (text, requestedSelection, requestedExecutionId, signal) => {
26429
+ signal?.throwIfAborted();
25350
26430
  if (disposed)
25351
26431
  throw new Error("DSH host facade is disposed");
25352
26432
  if (!text.trim())
@@ -25361,11 +26441,15 @@ ${JSON.stringify(historyContext.items)}`;
25361
26441
  promptActive = true;
25362
26442
  let disposeSelection;
25363
26443
  let selectionRef;
26444
+ let abortPrompt;
25364
26445
  try {
25365
26446
  if (requestedExecutionId === void 0)
25366
26447
  await open7();
25367
26448
  throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
25368
26449
  const agent = operationAgent(requestedExecutionId);
26450
+ signal?.throwIfAborted();
26451
+ if (signal && typeof agent.cancel !== "function")
26452
+ throw new Error("DSH public cancel API is required for deletion-safe execution");
25369
26453
  if (requestedExecutionId !== void 0) {
25370
26454
  assertExecutionParentIdle();
25371
26455
  assertExecutionOwnership(agent);
@@ -25391,8 +26475,41 @@ ${JSON.stringify(historyContext.items)}`;
25391
26475
  assertExecutionParentIdle();
25392
26476
  assertExecutionOwnership(agent);
25393
26477
  }
26478
+ if (liveSubscribers.size > 0) {
26479
+ let imported;
26480
+ try {
26481
+ imported = asObject4(await (options.moduleImporter ?? importDshModule)(USER_MESSAGE_MODULE));
26482
+ } catch {
26483
+ }
26484
+ throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
26485
+ if (agent.status !== "idle" || agent.session.seq !== fromSequence)
26486
+ throw new Error("DSH Agent changed while preparing live output");
26487
+ livePrompt = {
26488
+ agent,
26489
+ closed: false,
26490
+ revision: 0,
26491
+ nativeFrames: typeof imported?.expandAssistantStream === "function",
26492
+ ...typeof imported?.isAgentLoopRequest === "function" ? { isLoopRequest: imported.isAgentLoopRequest } : {},
26493
+ provider: requestedSelection?.provider ?? options.provider,
26494
+ model: requestedSelection?.model ?? options.model
26495
+ };
26496
+ }
26497
+ signal?.throwIfAborted();
25394
26498
  agent.followup(message);
26499
+ abortPrompt = () => {
26500
+ livePrompt = void 0;
26501
+ if (typeof agent.cancel === "function")
26502
+ agent.cancel({ kind: "user" });
26503
+ else if (requestedExecutionId !== void 0)
26504
+ void releaseExecutionHandle();
26505
+ else
26506
+ void releaseHandle();
26507
+ };
26508
+ signal?.addEventListener("abort", abortPrompt, { once: true });
26509
+ if (signal?.aborted)
26510
+ abortPrompt();
25395
26511
  await agent.whenIdle();
26512
+ signal?.throwIfAborted();
25396
26513
  throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
25397
26514
  await sessions.flush(agent.session);
25398
26515
  throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
@@ -25403,11 +26520,14 @@ ${JSON.stringify(historyContext.items)}`;
25403
26520
  events: snapshotFrom(fromSequence, requestedExecutionId)
25404
26521
  };
25405
26522
  } finally {
26523
+ if (abortPrompt)
26524
+ signal?.removeEventListener("abort", abortPrompt);
25406
26525
  if (selectionRef !== void 0) {
25407
26526
  selectionRef.current = void 0;
25408
26527
  selectionRef.assembled = void 0;
25409
26528
  }
25410
26529
  disposeSelection?.();
26530
+ livePrompt = void 0;
25411
26531
  promptActive = false;
25412
26532
  }
25413
26533
  };
@@ -25471,7 +26591,7 @@ ${JSON.stringify(historyContext.items)}`;
25471
26591
  } catch {
25472
26592
  }
25473
26593
  try {
25474
- await contextPreparationPromise;
26594
+ await contextOperationPromise;
25475
26595
  } catch {
25476
26596
  }
25477
26597
  try {
@@ -25486,20 +26606,33 @@ ${JSON.stringify(historyContext.items)}`;
25486
26606
  return disposePromise;
25487
26607
  };
25488
26608
  return {
25489
- sessionId: options.sessionId,
26609
+ get sessionId() {
26610
+ return nativeSessionId;
26611
+ },
26612
+ ...options.contextBinding === void 0 ? {} : { contextDeletionVersion: 1 },
26613
+ resetCanonicalContext(revision) {
26614
+ if (contextOperationPromise !== void 0)
26615
+ return Promise.reject(new Error("DSH host facade permits only one active context operation"));
26616
+ const operation = resetCanonicalContext(revision);
26617
+ contextOperationPromise = operation;
26618
+ return operation.finally(() => {
26619
+ if (contextOperationPromise === operation)
26620
+ contextOperationPromise = void 0;
26621
+ });
26622
+ },
25490
26623
  open: open7,
25491
26624
  currentSequence(requestedExecutionId) {
25492
26625
  return operationAgent(requestedExecutionId).session.seq;
25493
26626
  },
25494
26627
  snapshotFrom,
25495
26628
  prepareContextExecution(input2) {
25496
- if (contextPreparationPromise !== void 0)
26629
+ if (contextOperationPromise !== void 0)
25497
26630
  return Promise.reject(new Error("DSH host facade permits only one active context preparation"));
25498
26631
  const operation = prepareContextExecution(input2);
25499
- contextPreparationPromise = operation;
26632
+ contextOperationPromise = operation;
25500
26633
  return operation.finally(() => {
25501
- if (contextPreparationPromise === operation)
25502
- contextPreparationPromise = void 0;
26634
+ if (contextOperationPromise === operation)
26635
+ contextOperationPromise = void 0;
25503
26636
  });
25504
26637
  },
25505
26638
  projectCanonicalEvents,
@@ -25511,6 +26644,12 @@ ${JSON.stringify(historyContext.items)}`;
25511
26644
  eventSubscribers.add(listener);
25512
26645
  return () => eventSubscribers.delete(listener);
25513
26646
  },
26647
+ onLiveOutput(listener) {
26648
+ if (disposed)
26649
+ throw new Error("DSH host facade is disposed");
26650
+ liveSubscribers.add(listener);
26651
+ return () => liveSubscribers.delete(listener);
26652
+ },
25514
26653
  onStatus(listener) {
25515
26654
  if (disposed)
25516
26655
  throw new Error("DSH host facade is disposed");
@@ -25543,6 +26682,7 @@ async function registerDshNativeWorkspace(contextValue, workspacePath, workspace
25543
26682
  const sessionQuery = requireService(context, "sessionQuery", ["readSession"]);
25544
26683
  const sessionTitle = requireService(context, "sessionTitle", ["rename", "get"]);
25545
26684
  const completed = /* @__PURE__ */ new Map();
26685
+ const retired = /* @__PURE__ */ new Set();
25546
26686
  const observedSessionIds = new Set(workspace.sessionIds);
25547
26687
  const runningSessionIds = /* @__PURE__ */ new Set();
25548
26688
  const offActivity = context.on("agent/status", (...args) => {
@@ -25563,6 +26703,10 @@ async function registerDshNativeWorkspace(contextValue, workspacePath, workspace
25563
26703
  return;
25564
26704
  observedSessionIds.add(session.id);
25565
26705
  const event = asSessionEvent(args[1]);
26706
+ if (event?.type === "user/message" && /^gatherthread-retired:[0-9]+$/.test(String(asObject4(event.data)?.id)) && asObject4(asObject4(event.data)?.source)?.plugin === "gatherthread") {
26707
+ retired.add(session.id);
26708
+ completed.delete(session.id);
26709
+ }
25566
26710
  if (event?.type === "turn/start")
25567
26711
  runningSessionIds.add(session.id);
25568
26712
  if (event?.type === "turn/end")
@@ -25613,6 +26757,10 @@ async function registerDshNativeWorkspace(contextValue, workspacePath, workspace
25613
26757
  for (const localSessionId of [...currentIds]) {
25614
26758
  if (!isUserCreatedDshSessionId(localSessionId))
25615
26759
  continue;
26760
+ if (retired.has(localSessionId)) {
26761
+ candidates.delete(localSessionId);
26762
+ continue;
26763
+ }
25616
26764
  const cached2 = completed.get(localSessionId);
25617
26765
  if (cached2 !== void 0)
25618
26766
  continue;
@@ -25627,8 +26775,11 @@ async function registerDshNativeWorkspace(contextValue, workspacePath, workspace
25627
26775
  throw new Error("Pinned DSH Session reader returned an invalid event");
25628
26776
  return parsed;
25629
26777
  });
25630
- if (!hasCompletedDshLocalTurn(events, localSessionId))
26778
+ if (!hasCompletedDshLocalTurn(events, localSessionId)) {
26779
+ completed.delete(localSessionId);
26780
+ candidates.delete(localSessionId);
25631
26781
  continue;
26782
+ }
25632
26783
  const title = live === void 0 ? titleFromEvents(events) : normalizedLocalSessionTitle(sessionTitle.get(live)?.title) ?? titleFromEvents(events);
25633
26784
  const candidate = { localSessionId, title };
25634
26785
  completed.set(localSessionId, candidate);
@@ -25653,8 +26804,10 @@ async function registerDshNativeWorkspace(contextValue, workspacePath, workspace
25653
26804
  return;
25654
26805
  events.push(parsed);
25655
26806
  }
25656
- if (!hasCompletedDshLocalTurn(events, session.id))
26807
+ if (!hasCompletedDshLocalTurn(events, session.id)) {
26808
+ completed.delete(session.id);
25657
26809
  return;
26810
+ }
25658
26811
  completed.set(session.id, {
25659
26812
  localSessionId: session.id,
25660
26813
  title: normalizedLocalSessionTitle(sessionTitle.get(session)?.title) ?? titleFromEvents(events)
@@ -26784,7 +27937,7 @@ function publicError2(error62, fallback) {
26784
27937
  }
26785
27938
 
26786
27939
  // dist/src/state-store.js
26787
- import { randomUUID as randomUUID4 } from "node:crypto";
27940
+ import { randomUUID as randomUUID6 } from "node:crypto";
26788
27941
  import { constants as constants4 } from "node:fs";
26789
27942
  import { lstat as lstat7, mkdir as mkdir5, open as open6, rename as rename3, unlink as unlink4 } from "node:fs/promises";
26790
27943
  import path9 from "node:path";
@@ -26839,7 +27992,7 @@ var FileConnectorStateStore = class {
26839
27992
  const targetBefore = await optionalLstat(this.#path);
26840
27993
  if (targetBefore !== void 0)
26841
27994
  assertPrivateRegularFile(targetBefore, "DSH connector state");
26842
- const temporaryPath = `${this.#path}.tmp-${process.pid}-${randomUUID4()}`;
27995
+ const temporaryPath = `${this.#path}.tmp-${process.pid}-${randomUUID6()}`;
26843
27996
  const handle = await open6(temporaryPath, "wx", 384);
26844
27997
  try {
26845
27998
  await handle.writeFile(`${JSON.stringify(validated, null, 2)}
@@ -26879,7 +28032,10 @@ function validateConnectorState(value) {
26879
28032
  "publishedDshSequence",
26880
28033
  ...legacyUploadPolicy ? [] : ["automaticUpload"],
26881
28034
  "activeRequest",
26882
- "outbox"
28035
+ "outbox",
28036
+ "contentRevision",
28037
+ "projectionSessionId",
28038
+ "localOnlySessionIds"
26883
28039
  ]), "state");
26884
28040
  if (state.version !== 1 && state.version !== 2 && state.version !== 3) {
26885
28041
  throw new Error("Unsupported DSH connector state version");
@@ -26894,6 +28050,9 @@ function validateConnectorState(value) {
26894
28050
  throw new Error("state.outbox must be an array");
26895
28051
  const outbox = state.outbox.map(parseOutboxOperation);
26896
28052
  const validated = {
28053
+ ...state.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(state.contentRevision, "state.contentRevision") },
28054
+ ...state.projectionSessionId === void 0 ? {} : { projectionSessionId: safeString(state.projectionSessionId, "state.projectionSessionId", 128) },
28055
+ ...state.localOnlySessionIds === void 0 ? {} : { localOnlySessionIds: parseRetiredSessionIds(state.localOnlySessionIds) },
26897
28056
  version: 3,
26898
28057
  binding: {
26899
28058
  projectId: safeString(binding.projectId, "state.binding.projectId", 128),
@@ -26912,8 +28071,9 @@ function validateConnectorState(value) {
26912
28071
  }
26913
28072
  function parseActiveRequest(value) {
26914
28073
  const active = requiredObject4(value, "state.activeRequest");
26915
- exactKeys(active, /* @__PURE__ */ new Set(["requestId", "requestSequence", "dshFromSequence", "dshToSequence", "promptDigest", "claimAttempt", "contextExecution"]), "state.activeRequest");
28074
+ exactKeys(active, /* @__PURE__ */ new Set(["requestId", "requestSequence", "dshFromSequence", "dshToSequence", "promptDigest", "claimAttempt", "contextExecution", "contentRevision"]), "state.activeRequest");
26916
28075
  const parsed = {
28076
+ ...active.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(active.contentRevision, "state.activeRequest.contentRevision") },
26917
28077
  requestId: safeString(active.requestId, "state.activeRequest.requestId", 128),
26918
28078
  requestSequence: positiveInteger(active.requestSequence, "state.activeRequest.requestSequence"),
26919
28079
  dshFromSequence: nonNegativeInteger(active.dshFromSequence, "state.activeRequest.dshFromSequence"),
@@ -26989,7 +28149,8 @@ function parseLocalTurnInput(value, label) {
26989
28149
  "observedReasoningEffort",
26990
28150
  "requestPayload",
26991
28151
  "responsePayload",
26992
- "toolEvents"
28152
+ "toolEvents",
28153
+ "contentRevision"
26993
28154
  ]), label);
26994
28155
  const occurredAt = safeString(input2.occurredAt, `${label}.occurredAt`, 64);
26995
28156
  if (!Number.isFinite(Date.parse(occurredAt)))
@@ -26999,6 +28160,7 @@ function parseLocalTurnInput(value, label) {
26999
28160
  }
27000
28161
  return {
27001
28162
  localTurnId: safeString(input2.localTurnId, `${label}.localTurnId`, 200),
28163
+ ...input2.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(input2.contentRevision, `${label}.contentRevision`) },
27002
28164
  runtimeId: safeString(input2.runtimeId, `${label}.runtimeId`, 128),
27003
28165
  basedOnSequence: nonNegativeInteger(input2.basedOnSequence, `${label}.basedOnSequence`),
27004
28166
  occurredAt,
@@ -27026,13 +28188,15 @@ function parseAppendInput(value, label) {
27026
28188
  "runtimeId",
27027
28189
  "claimAttempt",
27028
28190
  "observedModel",
27029
- "observedReasoningEffort"
28191
+ "observedReasoningEffort",
28192
+ "contentRevision"
27030
28193
  ]), label);
27031
28194
  if (input2.type !== "tool_call" && input2.type !== "tool_result") {
27032
28195
  throw new Error(`${label}.type must be tool_call or tool_result`);
27033
28196
  }
27034
28197
  return {
27035
28198
  type: input2.type,
28199
+ ...input2.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(input2.contentRevision, `${label}.contentRevision`) },
27036
28200
  idempotencyKey: safeString(input2.idempotencyKey, `${label}.idempotencyKey`, 200),
27037
28201
  payload: jsonValue(input2.payload, `${label}.payload`),
27038
28202
  ...input2.replyTo === void 0 ? {} : { replyTo: safeString(input2.replyTo, `${label}.replyTo`, 128) },
@@ -27049,9 +28213,10 @@ function parseAppendInput(value, label) {
27049
28213
  }
27050
28214
  function parseCompletionInput(value, label) {
27051
28215
  const input2 = requiredObject4(value, label);
27052
- exactKeys(input2, /* @__PURE__ */ new Set(["runtimeId", "claimAttempt", "idempotencyKey", "payload", "observedModel", "observedReasoningEffort"]), label);
28216
+ exactKeys(input2, /* @__PURE__ */ new Set(["runtimeId", "claimAttempt", "idempotencyKey", "payload", "observedModel", "observedReasoningEffort", "contentRevision"]), label);
27053
28217
  return {
27054
28218
  runtimeId: safeString(input2.runtimeId, `${label}.runtimeId`, 128),
28219
+ ...input2.contentRevision === void 0 ? {} : { contentRevision: nonNegativeInteger(input2.contentRevision, `${label}.contentRevision`) },
27055
28220
  ...input2.claimAttempt === void 0 ? {} : {
27056
28221
  claimAttempt: positiveInteger(input2.claimAttempt, `${label}.claimAttempt`)
27057
28222
  },
@@ -27063,6 +28228,11 @@ function parseCompletionInput(value, label) {
27063
28228
  }
27064
28229
  };
27065
28230
  }
28231
+ function parseRetiredSessionIds(value) {
28232
+ if (!Array.isArray(value) || value.length > 4096 || new Set(value).size !== value.length)
28233
+ throw new Error("Invalid DSH retired Session identities");
28234
+ return value.map((id, index) => safeString(id, `state.localOnlySessionIds[${index}]`, 128));
28235
+ }
27066
28236
  function assertAlreadyRedacted(state) {
27067
28237
  const encoded = JSON.stringify(state);
27068
28238
  const redacted = JSON.stringify(redactValue(state));
@@ -27889,9 +29059,13 @@ var DshNativeHostController = class {
27889
29059
  if (route === void 0)
27890
29060
  return;
27891
29061
  throwIfAborted(signal);
27892
- const profilesChanged = await this.#refreshExecutionProfiles(route, signal);
29062
+ const catalogUpdate = await this.#refreshExecutionProfiles(route, signal);
27893
29063
  throwIfAborted(signal);
27894
- if (profilesChanged) {
29064
+ if (catalogUpdate === "route_unavailable") {
29065
+ await this.#abandonUnavailableRoute(grant);
29066
+ return;
29067
+ }
29068
+ if (catalogUpdate === "changed") {
27895
29069
  for (const owner of this.#owners.values())
27896
29070
  this.#pendingProfileOwners.add(owner);
27897
29071
  }
@@ -27933,16 +29107,17 @@ var DshNativeHostController = class {
27933
29107
  /**
27934
29108
  * Re-read the harness catalog when the route changed or the entry went stale.
27935
29109
  *
27936
- * Returns whether the catalog differs from the one already advertised. Discovery
27937
- * is cached per route and also time-bounded: DSH publishes a model metadata
27938
- * catalog that can gain models while a connection stays open, so a connect-time
27939
- * snapshot would otherwise keep offering the old list for the life of the process.
29110
+ * Returns whether the catalog differs from the one already advertised, or that
29111
+ * DSH no longer offers the model this connection runs. Discovery is cached per
29112
+ * route and also time-bounded: DSH publishes a model metadata catalog that can
29113
+ * gain models while a connection stays open, so a connect-time snapshot would
29114
+ * otherwise keep offering the old list for the life of the process.
27940
29115
  */
27941
29116
  async #refreshExecutionProfiles(route, signal) {
27942
29117
  const routeKey = `${route.provider}\0${route.model}`;
27943
29118
  const discoveredAt = this.#executionProfilesDiscoveredAt;
27944
29119
  if (this.#executionProfileRouteKey === routeKey && discoveredAt !== void 0 && this.#now() - discoveredAt < EXECUTION_PROFILE_REFRESH_INTERVAL_MS) {
27945
- return false;
29120
+ return "unchanged";
27946
29121
  }
27947
29122
  const previous = this.#executionProfiles;
27948
29123
  const remember = (profiles2) => {
@@ -27950,18 +29125,44 @@ var DshNativeHostController = class {
27950
29125
  this.#executionProfiles = profiles2;
27951
29126
  this.#executionProfileRouteKey = routeKey;
27952
29127
  this.#executionProfilesDiscoveredAt = this.#now();
27953
- return changed;
29128
+ return changed ? "changed" : "unchanged";
27954
29129
  };
27955
29130
  if (route.provider !== "deepseek-official")
27956
29131
  return remember(void 0);
27957
29132
  const discovered = this.#options.listExecutionProfiles === void 0 ? await listNativeExecutionProfiles(this.#options.context, route.provider, signal) : await this.#options.listExecutionProfiles(route.provider, signal);
27958
29133
  throwIfAborted(signal);
27959
29134
  const profiles = normalizeExecutionProfiles(discovered, route.provider);
27960
- if (!profiles.some((profile) => profile.model === route.model)) {
27961
- throw new Error("DeepSeek Harness did not advertise the configured model as an execution profile");
27962
- }
29135
+ if (!profiles.some((profile) => profile.model === route.model))
29136
+ return "route_unavailable";
27963
29137
  return remember(profiles);
27964
29138
  }
29139
+ /**
29140
+ * Drop the route after DSH stops offering the model this connection runs.
29141
+ *
29142
+ * A harness catalog is the authority on what a runtime can run, so the route is
29143
+ * abandoned instead of being repointed at another model: registering a
29144
+ * replacement silently would run a model this device never selected. Clearing the
29145
+ * stored route returns the connection to the state it has before its first
29146
+ * selection, where the panel asks for an explicit provider and model against the
29147
+ * harness's current catalog. Owners and the cached declaration go with it, so
29148
+ * nothing keeps advertising the profiles and bindings built from the dropped route.
29149
+ */
29150
+ async #abandonUnavailableRoute(grant) {
29151
+ await this.#stopOwners();
29152
+ this.#executionProfiles = void 0;
29153
+ this.#executionProfileRouteKey = void 0;
29154
+ this.#executionProfilesDiscoveredAt = void 0;
29155
+ this.#grant = await this.#credentials.save({
29156
+ schemaVersion: grant.schemaVersion,
29157
+ serverUrl: grant.serverUrl,
29158
+ apiUrl: grant.apiUrl,
29159
+ deviceId: grant.deviceId,
29160
+ deviceName: grant.deviceName,
29161
+ token: grant.token
29162
+ });
29163
+ this.#recoverableError = "route_unavailable";
29164
+ this.#options.status.setConnection("stopped");
29165
+ }
27965
29166
  /**
27966
29167
  * Republish the current catalog to every owner that has not confirmed it.
27967
29168
  *