@codexhost/cli-linux-x64 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14588,8 +14588,11 @@ var codexhostErrorSchema = external_exports.strictObject({
14588
14588
  code: external_exports.string().min(1),
14589
14589
  message: external_exports.string().min(1),
14590
14590
  retryable: external_exports.boolean(),
14591
- diagnostic: external_exports.string().min(1).optional()
14592
- }).superRefine(rejectExplicitUndefined(["diagnostic"]));
14591
+ diagnostic: external_exports.string().min(1).optional(),
14592
+ stage: external_exports.string().min(1).optional(),
14593
+ durationMs: external_exports.number().int().nonnegative().optional(),
14594
+ stderrTail: external_exports.string().min(1).optional()
14595
+ }).superRefine(rejectExplicitUndefined(["diagnostic", "stage", "durationMs", "stderrTail"]));
14593
14596
 
14594
14597
  // packages/shared-contracts/dist/ids.js
14595
14598
  var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
@@ -14934,6 +14937,47 @@ var threadOwnershipListResultSchema = external_exports.object({
14934
14937
  }
14935
14938
  });
14936
14939
 
14940
+ // packages/shared-contracts/dist/harness-commands.js
14941
+ var commandIdSchema = external_exports.string().trim().min(1).max(128).regex(/^[A-Za-z0-9._:-]+$/u).brand();
14942
+ var commandInvocationSchema = external_exports.string().min(1).max(128);
14943
+ var commandLabelSchema = external_exports.string().trim().min(1).max(128);
14944
+ var commandDescriptionSchema = external_exports.string().trim().min(1).max(512);
14945
+ var harnessCommandDescriptorSchema = external_exports.object({
14946
+ id: commandIdSchema,
14947
+ invocation: commandInvocationSchema,
14948
+ label: commandLabelSchema,
14949
+ description: commandDescriptionSchema.optional(),
14950
+ argumentMode: external_exports.enum(["none", "text"])
14951
+ }).strict();
14952
+ var harnessCommandCatalogSchema = external_exports.object({
14953
+ commands: external_exports.array(harnessCommandDescriptorSchema)
14954
+ }).strict().superRefine((catalog, context) => {
14955
+ const ids = /* @__PURE__ */ new Set();
14956
+ for (const [index, command] of catalog.commands.entries()) {
14957
+ if (ids.has(command.id)) {
14958
+ context.addIssue({
14959
+ code: "custom",
14960
+ message: "Harness command IDs must be unique",
14961
+ path: ["commands", index, "id"]
14962
+ });
14963
+ }
14964
+ ids.add(command.id);
14965
+ }
14966
+ });
14967
+ var threadCommandsInspectParamsSchema = external_exports.object({
14968
+ threadId: hostThreadIdSchema
14969
+ }).strict();
14970
+ var threadCommandExecuteParamsSchema = external_exports.object({
14971
+ threadId: hostThreadIdSchema,
14972
+ commandId: commandIdSchema,
14973
+ turnId: hostTurnIdSchema.optional(),
14974
+ arguments: jsonObjectSchema.optional()
14975
+ }).strict();
14976
+ var threadCommandExecuteResultSchema = external_exports.object({
14977
+ accepted: external_exports.literal(true),
14978
+ turnId: hostTurnIdSchema
14979
+ }).strict();
14980
+
14937
14981
  // packages/shared-contracts/dist/json-rpc.js
14938
14982
  var jsonRpcVersionSchema = external_exports.literal("2.0").optional();
14939
14983
  var absentSchema = external_exports.never().optional();
@@ -15159,6 +15203,15 @@ var HarnessOutputChannel = class {
15159
15203
  }
15160
15204
  };
15161
15205
 
15206
+ // packages/harness-adapter/dist/diagnostics.js
15207
+ var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
15208
+ var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
15209
+ var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
15210
+ function sanitizeDiagnosticTail(value) {
15211
+ const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
15212
+ return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
15213
+ }
15214
+
15162
15215
  // packages/harness-adapter/dist/usage.js
15163
15216
  var tokenFields = [
15164
15217
  "inputTokens",
@@ -42168,6 +42221,7 @@ var ClaudeSdkTransport = class {
42168
42221
  #active = null;
42169
42222
  #closePromise = null;
42170
42223
  #consumeTask = null;
42224
+ #stderrTail = "";
42171
42225
  #interactionOrdinal = 0;
42172
42226
  #query = null;
42173
42227
  #started = false;
@@ -42465,7 +42519,9 @@ var ClaudeSdkTransport = class {
42465
42519
  stdio: ["pipe", "pipe", "pipe"],
42466
42520
  windowsHide: true
42467
42521
  });
42468
- child.stderr.resume();
42522
+ child.stderr.on("data", (chunk) => {
42523
+ this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
42524
+ });
42469
42525
  this.#children.push(child);
42470
42526
  return child;
42471
42527
  }
@@ -42480,6 +42536,7 @@ var ClaudeSdkTransport = class {
42480
42536
  };
42481
42537
  var ClaudeSdkModelInspector = class {
42482
42538
  #children = [];
42539
+ #stderrTail = "";
42483
42540
  #closeTimeoutMs;
42484
42541
  #command;
42485
42542
  #cwd;
@@ -42488,6 +42545,9 @@ var ClaudeSdkModelInspector = class {
42488
42545
  #queryFactory;
42489
42546
  #closePromise = null;
42490
42547
  #query = null;
42548
+ get stderrTail() {
42549
+ return this.#stderrTail;
42550
+ }
42491
42551
  constructor(options) {
42492
42552
  this.#closeTimeoutMs = options.closeTimeoutMs;
42493
42553
  this.#command = options.command;
@@ -42564,7 +42624,9 @@ var ClaudeSdkModelInspector = class {
42564
42624
  stdio: ["pipe", "pipe", "pipe"],
42565
42625
  windowsHide: true
42566
42626
  });
42567
- child.stderr.resume();
42627
+ child.stderr.on("data", (chunk) => {
42628
+ this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
42629
+ });
42568
42630
  this.#children.push(child);
42569
42631
  return child;
42570
42632
  }
@@ -43747,10 +43809,14 @@ var ClaudeCodeAdapter = class {
43747
43809
  }
43748
43810
  async #inspectModels(cwd) {
43749
43811
  let inspector = null;
43812
+ const startedAt = Date.now();
43813
+ let stage = "resolve-executable";
43750
43814
  try {
43751
43815
  this.#dependencies.inspectInstallation();
43816
+ stage = "startup";
43752
43817
  inspector = this.#dependencies.createInspector({ cwd });
43753
43818
  this.#inspectors.add(inspector);
43819
+ stage = "model-catalog";
43754
43820
  const snapshot = await inspector.inspect();
43755
43821
  const permissionModes = snapshot.canSelectPermissionMode ? claudePermissionModeCatalogForModels(snapshot.models) : void 0;
43756
43822
  if (!snapshot.canSelectModel) {
@@ -43791,7 +43857,12 @@ var ClaudeCodeAdapter = class {
43791
43857
  } : startupFailure(error54);
43792
43858
  return {
43793
43859
  status: normalized.code === "notInstalled" ? "notInstalled" : "error",
43794
- error: normalized
43860
+ error: {
43861
+ ...normalized,
43862
+ stage,
43863
+ durationMs: Date.now() - startedAt,
43864
+ ...inspector?.stderrTail ? { stderrTail: inspector.stderrTail } : {}
43865
+ }
43795
43866
  };
43796
43867
  } finally {
43797
43868
  if (inspector) {
@@ -45154,7 +45225,27 @@ function resolveDeepSeekCommand(configured, environment) {
45154
45225
  if (dsh)
45155
45226
  return { command: dsh, arguments: [], kind: "dsh" };
45156
45227
  const npx = resolveExecutable(process.platform === "win32" ? "npx.cmd" : "npx", environment);
45157
- return npx ? { command: npx, arguments: ["--no-install", "@deepseek-ai/dsh"], kind: "npx" } : null;
45228
+ return npx ? {
45229
+ command: npx,
45230
+ arguments: ["--offline", "--no-install", "@deepseek-ai/dsh"],
45231
+ kind: "npx"
45232
+ } : null;
45233
+ }
45234
+ function deepSeekProcessInvocation(command, arguments_2, environment, platform = process.platform) {
45235
+ const extension = path5.win32.extname(command).toLowerCase();
45236
+ if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
45237
+ return { command, arguments: arguments_2, windowsVerbatimArguments: false };
45238
+ }
45239
+ const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
45240
+ const commandLine = [command, ...arguments_2].map(quote).join(" ");
45241
+ return {
45242
+ command: environmentValue(environment, "ComSpec") ?? "cmd.exe",
45243
+ arguments: ["/d", "/v:off", "/s", "/c", `"${commandLine}"`],
45244
+ windowsVerbatimArguments: true
45245
+ };
45246
+ }
45247
+ function isMissingExecutableError(error54) {
45248
+ return typeof error54 === "object" && error54 !== null && "code" in error54 && error54.code === "ENOENT";
45158
45249
  }
45159
45250
  function unwrap(response, operation) {
45160
45251
  if (response.result.ok)
@@ -45174,13 +45265,15 @@ var DeepSeekHostConnection = class {
45174
45265
  #closePromise = null;
45175
45266
  #connectPromise = null;
45176
45267
  #managedProcess = null;
45268
+ #stderrTail = "";
45177
45269
  #pumpPromise = null;
45178
45270
  constructor(options = {}, dependencies = {
45179
45271
  createClient: (endpoint, timeoutMs) => new NodeDeepSeekHostClient(endpoint, timeoutMs),
45180
45272
  spawn: (command, args, spawnOptions) => spawn2(command, args, {
45181
45273
  env: spawnOptions.env,
45182
45274
  stdio: spawnOptions.stdio,
45183
- windowsHide: true
45275
+ windowsHide: true,
45276
+ windowsVerbatimArguments: spawnOptions.windowsVerbatimArguments
45184
45277
  }),
45185
45278
  sleep: (milliseconds) => new Promise((resolve2) => setTimeout(resolve2, milliseconds))
45186
45279
  }) {
@@ -45195,6 +45288,9 @@ var DeepSeekHostConnection = class {
45195
45288
  get client() {
45196
45289
  return this.#client;
45197
45290
  }
45291
+ get stderrTail() {
45292
+ return this.#stderrTail;
45293
+ }
45198
45294
  connect() {
45199
45295
  this.#connectPromise ??= this.#performConnect();
45200
45296
  return this.#connectPromise;
@@ -45233,19 +45329,28 @@ var DeepSeekHostConnection = class {
45233
45329
  "--port",
45234
45330
  endpoint.port || "80"
45235
45331
  ];
45236
- const child = this.#dependencies.spawn(invocation.command, args, {
45332
+ const processInvocation = deepSeekProcessInvocation(invocation.command, args, this.#environment);
45333
+ const child = this.#dependencies.spawn(processInvocation.command, processInvocation.arguments, {
45237
45334
  env: this.#environment,
45238
- stdio: "ignore"
45335
+ stdio: "pipe",
45336
+ windowsVerbatimArguments: processInvocation.windowsVerbatimArguments
45239
45337
  });
45240
45338
  this.#managedProcess = child;
45339
+ child.stderr?.on("data", (chunk) => {
45340
+ this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
45341
+ });
45241
45342
  let processError = null;
45242
45343
  child.once("error", (error54) => {
45243
45344
  processError = error54;
45244
45345
  });
45245
45346
  const deadline = Date.now() + this.#startupTimeoutMs;
45246
45347
  for (; ; ) {
45247
- if (processError)
45248
- throw processError;
45348
+ if (processError) {
45349
+ if (isMissingExecutableError(processError)) {
45350
+ throw new DeepSeekHarnessTransportError("notInstalled", "DeepSeek Harness command is not installed");
45351
+ }
45352
+ throw new DeepSeekHarnessTransportError("unavailable", `DeepSeek Harness Web could not start: ${String(processError)}`);
45353
+ }
45249
45354
  if (child.exitCode !== null || child.signalCode !== null) {
45250
45355
  if (invocation.kind === "npx") {
45251
45356
  throw new DeepSeekHarnessTransportError("notInstalled", "DeepSeek Harness package is not installed");
@@ -47094,13 +47199,17 @@ var DeepSeekHarnessAdapter = class {
47094
47199
  if (this.#closePromise) {
47095
47200
  return { status: "unavailable", error: invalidState2("DeepSeek Harness Adapter is closing") };
47096
47201
  }
47202
+ const startedAt = Date.now();
47203
+ let stage = "startup";
47097
47204
  try {
47098
47205
  await this.#connection.connect();
47206
+ stage = "host-describe";
47099
47207
  const [description, directory] = await Promise.all([
47100
47208
  this.#connection.client.host.describe({}),
47101
47209
  this.#connection.client.llm.models({})
47102
47210
  ]);
47103
47211
  const host2 = unwrapRpc(description, "host.describe");
47212
+ stage = "model-catalog";
47104
47213
  const models = unwrapRpc(directory, "llm.models");
47105
47214
  if (!nonBlankString(host2.provider) || !nonBlankString(host2.model)) {
47106
47215
  throw new DeepSeekHarnessTransportError("protocolError", "DeepSeek Harness Host has no default Model selection");
@@ -47124,7 +47233,12 @@ var DeepSeekHarnessAdapter = class {
47124
47233
  const normalized = normalizedError(error54, "unavailable");
47125
47234
  return {
47126
47235
  status: normalized.code === "notInstalled" ? "notInstalled" : "unavailable",
47127
- error: normalized
47236
+ error: {
47237
+ ...normalized,
47238
+ stage,
47239
+ durationMs: Date.now() - startedAt,
47240
+ ...normalized.stderrTail || !this.#connection.stderrTail ? {} : { stderrTail: this.#connection.stderrTail }
47241
+ }
47128
47242
  };
47129
47243
  }
47130
47244
  }
@@ -51955,6 +52069,27 @@ function mapGrokReplay(replay, harnessId, sessionId, cwd, knownTurnRefs = [], to
51955
52069
  if (isSyntheticGrokTurnKey(event.nativeTurnKey))
51956
52070
  continue;
51957
52071
  completeTurn(terminalOutcome(event.stopReason), event.nativeTurnKey);
52072
+ } else if (event.type === "compaction.started") {
52073
+ completeReasoning();
52074
+ completeAgent();
52075
+ } else if (event.type === "compaction.completed") {
52076
+ completeReasoning();
52077
+ completeAgent();
52078
+ const outcome = event.outcome === "succeeded" ? { status: "succeeded" } : event.outcome === "cancelled" ? { status: "cancelled", reason: "Context compaction was cancelled" } : {
52079
+ status: "failed",
52080
+ error: {
52081
+ code: "nativeFailure",
52082
+ message: event.errorMessage ?? "Grok context compaction failed",
52083
+ retryable: true
52084
+ }
52085
+ };
52086
+ items.push({
52087
+ item: {
52088
+ type: "contextCompaction",
52089
+ itemId: stableId("compaction", turnIndex, ++messageIndex)
52090
+ },
52091
+ outcome
52092
+ });
51958
52093
  } else if (event.type === "agent.text") {
51959
52094
  if (!agent) {
51960
52095
  completeReasoning();
@@ -52201,13 +52336,122 @@ async function forkGrokSession(input) {
52201
52336
  return { ok: true, value: { sessionId: derivedSessionId } };
52202
52337
  }
52203
52338
 
52339
+ // packages/adapters/grok/dist/grok-compaction.js
52340
+ var GROK_SESSION_UPDATE_EXTENSION_METHODS = [
52341
+ "_x.ai/session/update",
52342
+ "x.ai/session_notification"
52343
+ ];
52344
+ function isRecord12(value) {
52345
+ return typeof value === "object" && value !== null && !Array.isArray(value);
52346
+ }
52347
+ function optionalNonNegativeInt(value) {
52348
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
52349
+ }
52350
+ function firstPresent(record3, keys) {
52351
+ for (const key of keys) {
52352
+ if (record3[key] !== void 0)
52353
+ return record3[key];
52354
+ }
52355
+ return void 0;
52356
+ }
52357
+ function optionalErrorMessage(record3) {
52358
+ const value = firstPresent(record3, ["errorMessage", "error_message", "message"]);
52359
+ return typeof value === "string" && value.length > 0 ? value : void 0;
52360
+ }
52361
+ function isGrokExtensionSessionUpdateMethod(method) {
52362
+ return GROK_SESSION_UPDATE_EXTENSION_METHODS.includes(method);
52363
+ }
52364
+ function grokCompactionEventFromUpdate(update) {
52365
+ if (!isRecord12(update) || typeof update.sessionUpdate !== "string")
52366
+ return null;
52367
+ const tokensUsed = optionalNonNegativeInt(firstPresent(update, ["tokensUsed", "tokens_used"]));
52368
+ const contextWindowTokens = optionalNonNegativeInt(firstPresent(update, ["contextWindowTokens", "contextWindow", "context_window"]));
52369
+ const tokensBefore = optionalNonNegativeInt(firstPresent(update, ["tokensBefore", "tokens_before"]));
52370
+ const tokensAfter = optionalNonNegativeInt(firstPresent(update, ["tokensAfter", "tokens_after"]));
52371
+ if (update.sessionUpdate === "auto_compact_started") {
52372
+ return {
52373
+ type: "compaction.started",
52374
+ ...tokensUsed !== void 0 ? { tokensUsed } : {},
52375
+ ...contextWindowTokens !== void 0 ? { contextWindowTokens } : {}
52376
+ };
52377
+ }
52378
+ if (update.sessionUpdate === "auto_compact_completed") {
52379
+ return {
52380
+ type: "compaction.completed",
52381
+ outcome: "succeeded",
52382
+ ...tokensBefore !== void 0 ? { tokensBefore } : {},
52383
+ ...tokensAfter !== void 0 ? { tokensAfter } : {},
52384
+ ...contextWindowTokens !== void 0 ? { contextWindowTokens } : {}
52385
+ };
52386
+ }
52387
+ if (update.sessionUpdate === "auto_compact_failed") {
52388
+ const errorMessage5 = optionalErrorMessage(update);
52389
+ return {
52390
+ type: "compaction.completed",
52391
+ outcome: "failed",
52392
+ ...errorMessage5 ? { errorMessage: errorMessage5 } : {}
52393
+ };
52394
+ }
52395
+ if (update.sessionUpdate === "auto_compact_cancelled") {
52396
+ return { type: "compaction.completed", outcome: "cancelled" };
52397
+ }
52398
+ return null;
52399
+ }
52400
+
52401
+ // packages/adapters/grok/dist/grok-manual-compaction.js
52402
+ var GROK_COMPACT_CONVERSATION_METHOD = "x.ai/compact_conversation";
52403
+ var GROK_COMPACT_CONVERSATION_FALLBACK_METHOD = "_x.ai/compact_conversation";
52404
+ function isRecord13(value) {
52405
+ return typeof value === "object" && value !== null && !Array.isArray(value);
52406
+ }
52407
+ function optionalNonNegativeInt2(value) {
52408
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
52409
+ }
52410
+ function optionalErrorMessage2(value) {
52411
+ return typeof value === "string" && value.length > 0 ? value : void 0;
52412
+ }
52413
+ function parseGrokCompactResult(value, cancelled = false) {
52414
+ if (cancelled)
52415
+ return { outcome: "cancelled" };
52416
+ if (!isRecord13(value))
52417
+ return { outcome: "succeeded" };
52418
+ const tokensBefore = optionalNonNegativeInt2(value.tokensBefore ?? value.tokens_before);
52419
+ const tokensAfter = optionalNonNegativeInt2(value.tokensAfter ?? value.tokens_after);
52420
+ const contextWindowTokens = optionalNonNegativeInt2(value.contextWindowTokens ?? value.context_window);
52421
+ const errorMessage5 = optionalErrorMessage2(value.errorMessage ?? value.error_message ?? value.message);
52422
+ const outcome = value.outcome;
52423
+ if (outcome === "cancelled" || value.aborted === true) {
52424
+ return {
52425
+ outcome: "cancelled",
52426
+ ...tokensBefore !== void 0 ? { tokensBefore } : {},
52427
+ ...tokensAfter !== void 0 ? { tokensAfter } : {},
52428
+ ...contextWindowTokens !== void 0 ? { contextWindowTokens } : {}
52429
+ };
52430
+ }
52431
+ if (outcome === "failed" || value.success === false || errorMessage5) {
52432
+ return {
52433
+ outcome: "failed",
52434
+ ...tokensBefore !== void 0 ? { tokensBefore } : {},
52435
+ ...tokensAfter !== void 0 ? { tokensAfter } : {},
52436
+ ...contextWindowTokens !== void 0 ? { contextWindowTokens } : {},
52437
+ ...errorMessage5 ? { errorMessage: errorMessage5 } : {}
52438
+ };
52439
+ }
52440
+ return {
52441
+ outcome: "succeeded",
52442
+ ...tokensBefore !== void 0 ? { tokensBefore } : {},
52443
+ ...tokensAfter !== void 0 ? { tokensAfter } : {},
52444
+ ...contextWindowTokens !== void 0 ? { contextWindowTokens } : {}
52445
+ };
52446
+ }
52447
+
52204
52448
  // packages/adapters/grok/dist/grok-rewind.js
52205
52449
  import path10 from "node:path";
52206
52450
  var GROK_REWIND_EXECUTE_METHOD = "_x.ai/rewind/execute";
52207
52451
  function error53(code, message3, retryable = false) {
52208
52452
  return { code, message: message3, retryable };
52209
52453
  }
52210
- function isRecord12(value) {
52454
+ function isRecord14(value) {
52211
52455
  return typeof value === "object" && value !== null && !Array.isArray(value);
52212
52456
  }
52213
52457
  function buildGrokRewindParams(input) {
@@ -52219,10 +52463,10 @@ function buildGrokRewindParams(input) {
52219
52463
  };
52220
52464
  }
52221
52465
  function parseGrokRewindResponse(value) {
52222
- if (!isRecord12(value))
52466
+ if (!isRecord14(value))
52223
52467
  return null;
52224
- const payload = typeof value.success !== "boolean" && isRecord12(value.result) ? value.result : value;
52225
- if (!isRecord12(payload) || typeof payload.success !== "boolean")
52468
+ const payload = typeof value.success !== "boolean" && isRecord14(value.result) ? value.result : value;
52469
+ if (!isRecord14(payload) || typeof payload.success !== "boolean")
52226
52470
  return null;
52227
52471
  return rewindPayload(payload);
52228
52472
  }
@@ -52333,13 +52577,15 @@ async function rewindGrokLastTurn(input) {
52333
52577
  // packages/adapters/grok/dist/acp-transport.js
52334
52578
  var GrokTransportError = class extends Error {
52335
52579
  kind;
52580
+ diagnostic;
52336
52581
  constructor(kind, message3, options) {
52337
52582
  super(message3, options);
52338
52583
  this.kind = kind;
52584
+ this.diagnostic = options?.diagnostic;
52339
52585
  this.name = "GrokTransportError";
52340
52586
  }
52341
52587
  };
52342
- function isRecord13(value) {
52588
+ function isRecord15(value) {
52343
52589
  return typeof value === "object" && value !== null && !Array.isArray(value);
52344
52590
  }
52345
52591
  function errorText(error54) {
@@ -52371,6 +52617,9 @@ function withTimeout(promise2, milliseconds, operation) {
52371
52617
  clearTimeout(timeout);
52372
52618
  });
52373
52619
  }
52620
+ function yieldToEventLoop() {
52621
+ return new Promise((resolve2) => setImmediate(resolve2));
52622
+ }
52374
52623
  function waitForExit(child, timeoutMs) {
52375
52624
  if (child.exitCode !== null || child.signalCode !== null)
52376
52625
  return Promise.resolve(true);
@@ -52392,7 +52641,7 @@ function signalProcessTree(child, signal) {
52392
52641
  try {
52393
52642
  process.kill(-child.pid, signal);
52394
52643
  } catch (error54) {
52395
- if (!isRecord13(error54) || error54.code !== "ESRCH")
52644
+ if (!isRecord15(error54) || error54.code !== "ESRCH")
52396
52645
  throw error54;
52397
52646
  }
52398
52647
  }
@@ -52414,6 +52663,9 @@ function transportEvent(update, metadata) {
52414
52663
  }
52415
52664
  return { type: "rewind.marker", targetPromptIndex, ...metadata ? { metadata } : {} };
52416
52665
  }
52666
+ const compaction = grokCompactionEventFromUpdate(extension);
52667
+ if (compaction)
52668
+ return compaction;
52417
52669
  switch (update.sessionUpdate) {
52418
52670
  case "user_message_chunk":
52419
52671
  case "agent_message_chunk":
@@ -52474,7 +52726,7 @@ async function readNativeSignals(options, sessionId) {
52474
52726
  }
52475
52727
  }
52476
52728
  function isMissingFile(error54) {
52477
- return isRecord13(error54) && error54.code === "ENOENT";
52729
+ return isRecord15(error54) && error54.code === "ENOENT";
52478
52730
  }
52479
52731
  async function locateGrokNativeSession(options, sessionId) {
52480
52732
  if (sessionId.length === 0)
@@ -52497,7 +52749,7 @@ async function locateGrokNativeSession(options, sessionId) {
52497
52749
  try {
52498
52750
  summaryRaw = await readFile(path11.join(grokHomeDir(options), "sessions", entry.name, sessionId, "summary.json"), "utf8");
52499
52751
  } catch (error54) {
52500
- if (isMissingFile(error54) || isRecord13(error54) && error54.code === "ENOTDIR")
52752
+ if (isMissingFile(error54) || isRecord15(error54) && error54.code === "ENOTDIR")
52501
52753
  continue;
52502
52754
  throw new GrokTransportError("unavailable", "Grok Native Session metadata could not be read", {
52503
52755
  cause: error54
@@ -52509,10 +52761,10 @@ async function locateGrokNativeSession(options, sessionId) {
52509
52761
  } catch {
52510
52762
  continue;
52511
52763
  }
52512
- if (!isRecord13(parsed))
52764
+ if (!isRecord15(parsed))
52513
52765
  continue;
52514
52766
  const info = parsed.info;
52515
- const cwd = isRecord13(info) && typeof info.cwd === "string" && info.cwd.length > 0 ? path11.resolve(info.cwd) : path11.resolve(decodeURIComponent(entry.name));
52767
+ const cwd = isRecord15(info) && typeof info.cwd === "string" && info.cwd.length > 0 ? path11.resolve(info.cwd) : path11.resolve(decodeURIComponent(entry.name));
52516
52768
  const sourceWorkspaceDir = typeof parsed.source_workspace_dir === "string" && parsed.source_workspace_dir.length > 0 ? path11.resolve(parsed.source_workspace_dir) : void 0;
52517
52769
  matches.push({
52518
52770
  cwd,
@@ -52545,12 +52797,12 @@ function parseNativeHistory(contents, sessionId) {
52545
52797
  } catch {
52546
52798
  throw new GrokTransportError("protocolError", "Grok Native history contains invalid JSON");
52547
52799
  }
52548
- if (!isRecord13(record3) || !isRecord13(record3.params))
52800
+ if (!isRecord15(record3) || !isRecord15(record3.params))
52549
52801
  continue;
52550
52802
  const params = record3.params;
52551
- if (params.sessionId !== sessionId || !isRecord13(params.update))
52803
+ if (params.sessionId !== sessionId || !isRecord15(params.update))
52552
52804
  continue;
52553
- const metadata = isRecord13(params._meta) ? params._meta : void 0;
52805
+ const metadata = isRecord15(params._meta) ? params._meta : void 0;
52554
52806
  const event = transportEvent(params.update, metadata);
52555
52807
  if (event)
52556
52808
  events.push(metadata ? { ...event, metadata } : event);
@@ -52559,6 +52811,7 @@ function parseNativeHistory(contents, sessionId) {
52559
52811
  }
52560
52812
  var GrokAcpTransport = class {
52561
52813
  #options;
52814
+ #activeCompact = null;
52562
52815
  #activePrompt = null;
52563
52816
  #child = null;
52564
52817
  #closed = false;
@@ -52567,6 +52820,7 @@ var GrokAcpTransport = class {
52567
52820
  #initialize = null;
52568
52821
  #replay = null;
52569
52822
  #sessionId = null;
52823
+ #stderrTail = "";
52570
52824
  constructor(options) {
52571
52825
  this.#options = {
52572
52826
  commandTimeoutMs: 3e4,
@@ -52579,6 +52833,9 @@ var GrokAcpTransport = class {
52579
52833
  throw new Error("Grok ACP Session is not open");
52580
52834
  return this.#sessionId;
52581
52835
  }
52836
+ get stderrTail() {
52837
+ return this.#stderrTail;
52838
+ }
52582
52839
  async inspect() {
52583
52840
  if (this.#sessionId)
52584
52841
  throw new Error("Grok ACP inspection cannot reuse an open Session");
@@ -52747,7 +53004,9 @@ var GrokAcpTransport = class {
52747
53004
  windowsVerbatimArguments: invocation.windowsVerbatimArguments
52748
53005
  });
52749
53006
  this.#child = child;
52750
- child.stderr.resume();
53007
+ child.stderr.on("data", (chunk) => {
53008
+ this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
53009
+ });
52751
53010
  await withTimeout(new Promise((resolve2, reject) => {
52752
53011
  child.once("spawn", resolve2);
52753
53012
  child.once("error", reject);
@@ -52755,7 +53014,8 @@ var GrokAcpTransport = class {
52755
53014
  const stream = ndJsonStream2(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout));
52756
53015
  const connection = new ClientSideConnection(() => ({
52757
53016
  sessionUpdate: (params) => this.#handleUpdate(params),
52758
- requestPermission: (params) => this.#handlePermission(params)
53017
+ requestPermission: (params) => this.#handlePermission(params),
53018
+ extNotification: (method, params) => this.#handleExtensionNotification(method, params)
52759
53019
  }), stream);
52760
53020
  this.#connection = connection;
52761
53021
  child.once("error", (error54) => this.#fault(new GrokTransportError("processExited", error54.message)));
@@ -52794,6 +53054,40 @@ var GrokAcpTransport = class {
52794
53054
  this.#activePrompt = null;
52795
53055
  }
52796
53056
  }
53057
+ async compact(userContext, onEvent) {
53058
+ const connection = this.#connection;
53059
+ if (!connection || !this.#sessionId || this.#closed || this.#closing) {
53060
+ throw new GrokTransportError("unavailable", "Grok ACP Session is unavailable");
53061
+ }
53062
+ if (this.#activePrompt || this.#activeCompact) {
53063
+ throw new GrokTransportError("unavailable", "Grok ACP Session already has an active operation");
53064
+ }
53065
+ const active = { onEvent, cancellationRequested: false };
53066
+ this.#activeCompact = active;
53067
+ try {
53068
+ const params = {
53069
+ sessionId: this.#sessionId,
53070
+ ...userContext !== void 0 ? { userContext } : {}
53071
+ };
53072
+ let raw;
53073
+ try {
53074
+ raw = await connection.request(GROK_COMPACT_CONVERSATION_METHOD, params);
53075
+ } catch (error54) {
53076
+ if (!isGrokMethodNotFound(error54))
53077
+ throw error54;
53078
+ raw = await connection.request(GROK_COMPACT_CONVERSATION_FALLBACK_METHOD, params);
53079
+ }
53080
+ await yieldToEventLoop();
53081
+ return parseGrokCompactResult(raw, active.cancellationRequested);
53082
+ } catch (error54) {
53083
+ if (error54 instanceof GrokTransportError)
53084
+ throw error54;
53085
+ throw new GrokTransportError("unavailable", "Grok Native Compact failed", { cause: error54 });
53086
+ } finally {
53087
+ if (this.#activeCompact === active)
53088
+ this.#activeCompact = null;
53089
+ }
53090
+ }
52797
53091
  async setModel(modelId, reasoningEffort) {
52798
53092
  const connection = this.#connection;
52799
53093
  if (!connection || !this.#sessionId)
@@ -52803,7 +53097,7 @@ var GrokAcpTransport = class {
52803
53097
  modelId,
52804
53098
  ...reasoningEffort ? { reasoningEffort } : {}
52805
53099
  });
52806
- if (!isRecord13(response) || !isRecord13(response._meta) || !isRecord13(response._meta.model)) {
53100
+ if (!isRecord15(response) || !isRecord15(response._meta) || !isRecord15(response._meta.model)) {
52807
53101
  throw new GrokTransportError("protocolError", "Grok rejected Model configuration");
52808
53102
  }
52809
53103
  const selected = response._meta.model.Ok;
@@ -52813,9 +53107,11 @@ var GrokAcpTransport = class {
52813
53107
  }
52814
53108
  cancel() {
52815
53109
  const connection = this.#connection;
52816
- if (!connection || !this.#sessionId || !this.#activePrompt) {
52817
- return Promise.reject(new Error("Grok ACP Session has no cancellable Prompt"));
53110
+ if (!connection || !this.#sessionId || !this.#activePrompt && !this.#activeCompact) {
53111
+ return Promise.reject(new Error("Grok ACP Session has no cancellable operation"));
52818
53112
  }
53113
+ if (this.#activeCompact)
53114
+ this.#activeCompact.cancellationRequested = true;
52819
53115
  return connection.cancel({ sessionId: this.#sessionId });
52820
53116
  }
52821
53117
  async close() {
@@ -52839,19 +53135,29 @@ var GrokAcpTransport = class {
52839
53135
  this.#closed = true;
52840
53136
  this.#closing = false;
52841
53137
  this.#activePrompt = null;
53138
+ this.#activeCompact = null;
52842
53139
  }
52843
53140
  #handleUpdate(notification) {
52844
53141
  if (this.#sessionId && notification.sessionId !== this.#sessionId)
52845
53142
  return;
52846
- const metadata = isRecord13(notification._meta) ? notification._meta : void 0;
53143
+ const metadata = isRecord15(notification._meta) ? notification._meta : void 0;
52847
53144
  const event = transportEvent(notification.update, metadata);
52848
53145
  if (!event)
52849
53146
  return;
52850
53147
  const enriched = metadata ? { ...event, metadata } : event;
52851
53148
  if (this.#replay)
52852
53149
  this.#replay.push(enriched);
53150
+ else if (this.#activePrompt)
53151
+ this.#activePrompt.onEvent(enriched);
52853
53152
  else
52854
- this.#activePrompt?.onEvent(enriched);
53153
+ this.#activeCompact?.onEvent(enriched);
53154
+ }
53155
+ #handleExtensionNotification(method, params) {
53156
+ if (!isGrokExtensionSessionUpdateMethod(method))
53157
+ return;
53158
+ if (typeof params.sessionId !== "string" || !isRecord15(params.update))
53159
+ return;
53160
+ this.#handleUpdate(params);
52855
53161
  }
52856
53162
  #handlePermission(params) {
52857
53163
  if (params.sessionId !== this.#sessionId || !this.#activePrompt) {
@@ -52867,7 +53173,7 @@ var GrokAcpTransport = class {
52867
53173
  };
52868
53174
 
52869
53175
  // packages/adapters/grok/dist/grok-models.js
52870
- function isRecord14(value) {
53176
+ function isRecord16(value) {
52871
53177
  return typeof value === "object" && value !== null && !Array.isArray(value);
52872
53178
  }
52873
53179
  function nonBlank(value) {
@@ -52879,7 +53185,7 @@ function thinkingOptions(value) {
52879
53185
  const seen = /* @__PURE__ */ new Set();
52880
53186
  const options = [];
52881
53187
  for (const candidate of value) {
52882
- if (!isRecord14(candidate) || !nonBlank(candidate.label))
53188
+ if (!isRecord16(candidate) || !nonBlank(candidate.label))
52883
53189
  continue;
52884
53190
  const id2 = harnessThinkingOptionIdSchema.safeParse(candidate.id ?? candidate.value);
52885
53191
  if (!id2.success || seen.has(id2.data))
@@ -52890,7 +53196,7 @@ function thinkingOptions(value) {
52890
53196
  return options;
52891
53197
  }
52892
53198
  function parseGrokModelState(value) {
52893
- if (!isRecord14(value) || !nonBlank(value.currentModelId) || !Array.isArray(value.availableModels)) {
53199
+ if (!isRecord16(value) || !nonBlank(value.currentModelId) || !Array.isArray(value.availableModels)) {
52894
53200
  return null;
52895
53201
  }
52896
53202
  const currentModel = harnessModelRefSchema.safeParse({ id: value.currentModelId });
@@ -52901,12 +53207,12 @@ function parseGrokModelState(value) {
52901
53207
  const models = [];
52902
53208
  let currentThinkingOptionId;
52903
53209
  for (const candidate of value.availableModels) {
52904
- if (!isRecord14(candidate) || !nonBlank(candidate.modelId) || !nonBlank(candidate.name))
53210
+ if (!isRecord16(candidate) || !nonBlank(candidate.modelId) || !nonBlank(candidate.name))
52905
53211
  continue;
52906
53212
  const ref = harnessModelRefSchema.safeParse({ id: candidate.modelId });
52907
53213
  if (!ref.success)
52908
53214
  continue;
52909
- const metadata = isRecord14(candidate._meta) ? candidate._meta : {};
53215
+ const metadata = isRecord16(candidate._meta) ? candidate._meta : {};
52910
53216
  const options2 = thinkingOptions(metadata.reasoningEfforts);
52911
53217
  if (typeof metadata.totalContextTokens === "number" && Number.isSafeInteger(metadata.totalContextTokens) && metadata.totalContextTokens > 0) {
52912
53218
  contextWindowTokensByModel.set(ref.data.id, metadata.totalContextTokens);
@@ -52941,10 +53247,10 @@ function parseGrokModelState(value) {
52941
53247
  };
52942
53248
  }
52943
53249
  function modelStateFromInitialize(response) {
52944
- return parseGrokModelState(isRecord14(response._meta) ? response._meta.modelState : void 0);
53250
+ return parseGrokModelState(isRecord16(response._meta) ? response._meta.modelState : void 0);
52945
53251
  }
52946
53252
  function modelStateFromSessionResponse(response) {
52947
- return parseGrokModelState(isRecord14(response) ? response.models : void 0);
53253
+ return parseGrokModelState(isRecord16(response) ? response.models : void 0);
52948
53254
  }
52949
53255
  function stateForGrokModel(modelState, nativeState, model = modelState.currentModel, thinkingOptionId = modelState.currentThinkingOptionId) {
52950
53256
  const selectedModel = model;
@@ -52967,7 +53273,7 @@ import os4 from "node:os";
52967
53273
  import path12 from "node:path";
52968
53274
  var GROK_CREDITS_ENDPOINT = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
52969
53275
  var REQUEST_TIMEOUT_MS = 15e3;
52970
- function isRecord15(value) {
53276
+ function isRecord17(value) {
52971
53277
  return typeof value === "object" && value !== null && !Array.isArray(value);
52972
53278
  }
52973
53279
  function finitePercent(value) {
@@ -52997,7 +53303,7 @@ function productUsageFrom(value) {
52997
53303
  if (!Array.isArray(value))
52998
53304
  return void 0;
52999
53305
  const products = value.flatMap((entry) => {
53000
- if (!isRecord15(entry) || typeof entry.product !== "string")
53306
+ if (!isRecord17(entry) || typeof entry.product !== "string")
53001
53307
  return [];
53002
53308
  const usagePercent = finitePercent(entry.usagePercent);
53003
53309
  return usagePercent === void 0 ? [] : [{ product: entry.product, usagePercent }];
@@ -53005,13 +53311,13 @@ function productUsageFrom(value) {
53005
53311
  return products.length > 0 ? products : void 0;
53006
53312
  }
53007
53313
  function parseGrokCreditsResponse(value, fetchedAt = (/* @__PURE__ */ new Date()).toISOString()) {
53008
- if (!isRecord15(value) || !isRecord15(value.config))
53314
+ if (!isRecord17(value) || !isRecord17(value.config))
53009
53315
  return null;
53010
53316
  const config2 = value.config;
53011
- const period = isRecord15(config2.currentPeriod) ? config2.currentPeriod : void 0;
53317
+ const period = isRecord17(config2.currentPeriod) ? config2.currentPeriod : void 0;
53012
53318
  const resetsAt = (typeof period?.end === "string" && period.end.length > 0 ? period.end : void 0) ?? (typeof config2.billingPeriodEnd === "string" && config2.billingPeriodEnd.length > 0 ? config2.billingPeriodEnd : void 0);
53013
- const onDemandCap = isRecord15(config2.onDemandCap) ? nonNegativeNumber(config2.onDemandCap.val) : void 0;
53014
- const onDemandUsed = isRecord15(config2.onDemandUsed) ? nonNegativeNumber(config2.onDemandUsed.val) : void 0;
53319
+ const onDemandCap = isRecord17(config2.onDemandCap) ? nonNegativeNumber(config2.onDemandCap.val) : void 0;
53320
+ const onDemandUsed = isRecord17(config2.onDemandUsed) ? nonNegativeNumber(config2.onDemandUsed.val) : void 0;
53015
53321
  const usedPercent = finitePercent(config2.creditUsagePercent) ?? (onDemandCap !== void 0 && onDemandCap > 0 && onDemandUsed !== void 0 ? Math.min(100, Math.max(0, onDemandUsed / onDemandCap * 100)) : resetsAt ? 0 : void 0);
53016
53322
  if (usedPercent === void 0)
53017
53323
  return null;
@@ -53025,11 +53331,11 @@ function parseGrokCreditsResponse(value, fetchedAt = (/* @__PURE__ */ new Date()
53025
53331
  };
53026
53332
  }
53027
53333
  function selectAccessToken(auth, now) {
53028
- if (!isRecord15(auth))
53334
+ if (!isRecord17(auth))
53029
53335
  return null;
53030
- const entries = Object.entries(auth).filter(([, value]) => isRecord15(value) && typeof value.key === "string" && value.key.length > 0).sort(([left], [right]) => Number(right.startsWith("https://auth.x.ai")) - Number(left.startsWith("https://auth.x.ai")));
53336
+ const entries = Object.entries(auth).filter(([, value]) => isRecord17(value) && typeof value.key === "string" && value.key.length > 0).sort(([left], [right]) => Number(right.startsWith("https://auth.x.ai")) - Number(left.startsWith("https://auth.x.ai")));
53031
53337
  for (const [, value] of entries) {
53032
- if (!isRecord15(value) || typeof value.key !== "string")
53338
+ if (!isRecord17(value) || typeof value.key !== "string")
53033
53339
  continue;
53034
53340
  if (typeof value.expires_at === "string") {
53035
53341
  const expiresAt = Date.parse(value.expires_at);
@@ -53069,7 +53375,7 @@ async function fetchGrokCredits(input = {}) {
53069
53375
 
53070
53376
  // packages/adapters/grok/dist/grok-usage.js
53071
53377
  var USD_TICKS_PER_DOLLAR = 1e10;
53072
- function isRecord16(value) {
53378
+ function isRecord18(value) {
53073
53379
  return typeof value === "object" && value !== null && !Array.isArray(value);
53074
53380
  }
53075
53381
  function optionalToken(value) {
@@ -53086,7 +53392,7 @@ function combineUsage(base, next) {
53086
53392
  return base === null ? next : parseHostUsage({ ...base, ...next });
53087
53393
  }
53088
53394
  function usageFromNative(value) {
53089
- if (!isRecord16(value))
53395
+ if (!isRecord18(value))
53090
53396
  return null;
53091
53397
  const inputTokens = optionalToken(value.inputTokens);
53092
53398
  const cachedRead = optionalToken(value.cachedReadTokens);
@@ -53113,7 +53419,7 @@ function usageFromPrompt(response) {
53113
53419
  return response.usage ? usageFromNative(response.usage) : null;
53114
53420
  }
53115
53421
  function usageFromSignals(value) {
53116
- if (!isRecord16(value))
53422
+ if (!isRecord18(value))
53117
53423
  return null;
53118
53424
  try {
53119
53425
  return parseHostUsage({
@@ -53133,7 +53439,7 @@ var summedUsageFields = [
53133
53439
  "totalTokens"
53134
53440
  ];
53135
53441
  function nativeCostTicks(value) {
53136
- if (!isRecord16(value))
53442
+ if (!isRecord18(value))
53137
53443
  return void 0;
53138
53444
  const ticks = value.costUsdTicks;
53139
53445
  if (typeof ticks !== "number" || !Number.isSafeInteger(ticks) || ticks < 0)
@@ -53194,10 +53500,23 @@ function sessionUsageFromHistory(events) {
53194
53500
  return null;
53195
53501
  }
53196
53502
  }
53503
+ function usageFromCompact(tokensAfter, contextWindowTokens) {
53504
+ if (tokensAfter === void 0 || contextWindowTokens === void 0 || !Number.isSafeInteger(tokensAfter) || tokensAfter < 0 || !Number.isSafeInteger(contextWindowTokens) || contextWindowTokens <= 0) {
53505
+ return null;
53506
+ }
53507
+ try {
53508
+ return parseHostUsage({
53509
+ contextUsedTokens: tokensAfter,
53510
+ contextWindowTokens
53511
+ });
53512
+ } catch {
53513
+ return null;
53514
+ }
53515
+ }
53197
53516
  function usageFromUpdate(update, metadata, contextWindowTokens) {
53198
53517
  try {
53199
53518
  if (update?.sessionUpdate === "usage_update") {
53200
- const cost = isRecord16(update.cost) ? update.cost : null;
53519
+ const cost = isRecord18(update.cost) ? update.cost : null;
53201
53520
  return parseHostUsage({
53202
53521
  contextUsedTokens: update.used,
53203
53522
  contextWindowTokens: update.size,
@@ -53219,6 +53538,17 @@ function usageFromUpdate(update, metadata, contextWindowTokens) {
53219
53538
 
53220
53539
  // packages/adapters/grok/dist/grok-adapter.js
53221
53540
  var grokHarnessId = harnessIdSchema.parse("grok");
53541
+ var grokCommandCatalog = harnessCommandCatalogSchema.parse({
53542
+ commands: [
53543
+ {
53544
+ id: "grok.compact",
53545
+ invocation: "/compact",
53546
+ label: "Compact context",
53547
+ description: "Compact the current conversation context",
53548
+ argumentMode: "text"
53549
+ }
53550
+ ]
53551
+ });
53222
53552
  function capabilitiesForModels(modelState) {
53223
53553
  return {
53224
53554
  configuration: {
@@ -53238,7 +53568,8 @@ function normalizeError(error54, fallback) {
53238
53568
  return {
53239
53569
  code: error54.kind,
53240
53570
  message: error54.message,
53241
- retryable: !["notInstalled", "protocolError"].includes(error54.kind)
53571
+ retryable: !["notInstalled", "protocolError"].includes(error54.kind),
53572
+ ...error54.diagnostic ? { diagnostic: error54.diagnostic } : {}
53242
53573
  };
53243
53574
  }
53244
53575
  return {
@@ -53275,6 +53606,7 @@ function terminalOutcome2(response, cancelled) {
53275
53606
  var GrokHarnessSession = class {
53276
53607
  harnessId = grokHarnessId;
53277
53608
  capabilities;
53609
+ commands;
53278
53610
  initialState;
53279
53611
  initialUsage;
53280
53612
  outputs;
@@ -53306,6 +53638,10 @@ var GrokHarnessSession = class {
53306
53638
  this.initialUsage = options.initialUsage ?? null;
53307
53639
  this.#usage = this.initialUsage;
53308
53640
  this.capabilities = capabilitiesForModels(modelState);
53641
+ this.commands = {
53642
+ list: async () => ({ ok: true, value: grokCommandCatalog }),
53643
+ execute: (command) => this.#executeHarnessCommand(command)
53644
+ };
53309
53645
  this.#state = stateForGrokModel(modelState, { nativeRef: nativeRef(opened.sessionId) });
53310
53646
  this.initialState = this.#state;
53311
53647
  this.#snapshot = {
@@ -53344,6 +53680,8 @@ var GrokHarnessSession = class {
53344
53680
  async execute(command) {
53345
53681
  if (this.#phase !== "open")
53346
53682
  return { ok: false, error: invalidState3("Grok Session is not open") };
53683
+ if ("commandId" in command)
53684
+ return this.#executeHarnessCommand(command);
53347
53685
  if (command.type === "turn.cancel")
53348
53686
  return this.#cancel(command);
53349
53687
  if (command.type === "interaction.respond")
@@ -53398,6 +53736,9 @@ var GrokHarnessSession = class {
53398
53736
  agentMessageId: null,
53399
53737
  reasoning: null,
53400
53738
  reasoningMessageId: null,
53739
+ compactionItem: null,
53740
+ compactionContextWindow: void 0,
53741
+ compactionTerminal: null,
53401
53742
  tools: /* @__PURE__ */ new Map(),
53402
53743
  completedItems: [],
53403
53744
  approvals: /* @__PURE__ */ new Map(),
@@ -53414,6 +53755,111 @@ var GrokHarnessSession = class {
53414
53755
  }));
53415
53756
  return { ok: true, value: { turnId: command.turnId } };
53416
53757
  }
53758
+ async #executeHarnessCommand(command) {
53759
+ if (command.commandId !== "grok.compact") {
53760
+ return {
53761
+ ok: false,
53762
+ error: {
53763
+ code: "unsupported",
53764
+ message: `Grok does not expose Harness command '${command.commandId}'`,
53765
+ retryable: false
53766
+ }
53767
+ };
53768
+ }
53769
+ if (this.#active || this.#configuring) {
53770
+ return {
53771
+ ok: false,
53772
+ error: {
53773
+ code: "sessionBusy",
53774
+ message: "Grok Session already has an active operation",
53775
+ retryable: true
53776
+ }
53777
+ };
53778
+ }
53779
+ const arguments_2 = command.arguments;
53780
+ const userContext = arguments_2?.text;
53781
+ if (userContext !== void 0 && typeof userContext !== "string") {
53782
+ return {
53783
+ ok: false,
53784
+ error: {
53785
+ code: "invalidRequest",
53786
+ message: "Grok compact command argument 'text' must be a string",
53787
+ retryable: false
53788
+ }
53789
+ };
53790
+ }
53791
+ if (arguments_2 && Object.keys(arguments_2).some((key) => key !== "text")) {
53792
+ return {
53793
+ ok: false,
53794
+ error: {
53795
+ code: "invalidRequest",
53796
+ message: "Grok compact command has an unknown argument",
53797
+ retryable: false
53798
+ }
53799
+ };
53800
+ }
53801
+ let resolveCompletion = () => void 0;
53802
+ const completion = new Promise((resolve2) => {
53803
+ resolveCompletion = resolve2;
53804
+ });
53805
+ const active = {
53806
+ command: { type: "turn.start", turnId: command.turnId, input: [] },
53807
+ agent: null,
53808
+ agentMessageId: null,
53809
+ reasoning: null,
53810
+ reasoningMessageId: null,
53811
+ compactionItem: null,
53812
+ compactionContextWindow: void 0,
53813
+ compactionTerminal: null,
53814
+ tools: /* @__PURE__ */ new Map(),
53815
+ completedItems: [],
53816
+ approvals: /* @__PURE__ */ new Map(),
53817
+ cancellationRequested: false,
53818
+ beforeNativeTurnKeys: /* @__PURE__ */ new Set(),
53819
+ completion,
53820
+ resolveCompletion
53821
+ };
53822
+ this.#active = active;
53823
+ this.#event({ type: "turn.started", turnId: command.turnId });
53824
+ void this.#transport.compact(userContext, (event) => this.#handleEvent(active, event)).then((result) => this.#settleManualCompact(active, result), (error54) => this.#finish(active, active.compactionTerminal ? this.#turnOutcomeFromCompaction(active.compactionTerminal) : {
53825
+ status: "failed",
53826
+ error: normalizeError(error54, "nativeFailure")
53827
+ }));
53828
+ return { ok: true, value: { turnId: command.turnId } };
53829
+ }
53830
+ #settleManualCompact(active, result) {
53831
+ if (this.#active !== active)
53832
+ return;
53833
+ const terminal = active.compactionTerminal;
53834
+ if (!terminal) {
53835
+ this.#completeCompaction(active, {
53836
+ type: "compaction.completed",
53837
+ outcome: result.outcome,
53838
+ ...result.tokensBefore !== void 0 ? { tokensBefore: result.tokensBefore } : {},
53839
+ ...result.tokensAfter !== void 0 ? { tokensAfter: result.tokensAfter } : {},
53840
+ ...result.contextWindowTokens !== void 0 ? { contextWindowTokens: result.contextWindowTokens } : {},
53841
+ ...result.errorMessage ? { errorMessage: result.errorMessage } : {}
53842
+ });
53843
+ }
53844
+ this.#finish(active, terminal ? this.#turnOutcomeFromCompaction(terminal) : result.outcome === "succeeded" ? { status: "succeeded" } : result.outcome === "cancelled" ? { status: "cancelled", reason: "Context compaction was cancelled" } : {
53845
+ status: "failed",
53846
+ error: {
53847
+ code: "nativeFailure",
53848
+ message: result.errorMessage ?? "Grok context compaction failed",
53849
+ retryable: true
53850
+ }
53851
+ });
53852
+ }
53853
+ #turnOutcomeFromCompaction(event) {
53854
+ return event.outcome === "succeeded" ? { status: "succeeded" } : event.outcome === "cancelled" ? { status: "cancelled", reason: "Context compaction was cancelled" } : {
53855
+ status: "failed",
53856
+ error: {
53857
+ code: "nativeFailure",
53858
+ message: event.errorMessage ?? "Grok context compaction failed",
53859
+ retryable: true
53860
+ }
53861
+ };
53862
+ }
53417
53863
  close() {
53418
53864
  if (!this.#closePromise)
53419
53865
  this.#closePromise = this.#close().finally(this.#onClosed);
@@ -53572,9 +54018,57 @@ var GrokHarnessSession = class {
53572
54018
  this.#startTool(active, event);
53573
54019
  else if (event.type === "tool.update")
53574
54020
  this.#updateTool(active, event);
53575
- else if (event.type === "usage" || event.type === "turn.completed")
54021
+ else if (event.type === "compaction.started")
54022
+ this.#startCompaction(active, event);
54023
+ else if (event.type === "compaction.completed") {
54024
+ active.compactionTerminal = event;
54025
+ this.#completeCompaction(active, event);
54026
+ } else if (event.type === "usage" || event.type === "turn.completed")
53576
54027
  return;
53577
54028
  }
54029
+ #startCompaction(active, event) {
54030
+ if (active.compactionItem)
54031
+ return;
54032
+ this.#completeReasoning(active, { status: "succeeded" });
54033
+ this.#completeAgent(active, { status: "succeeded" });
54034
+ if (event.contextWindowTokens !== void 0) {
54035
+ active.compactionContextWindow = event.contextWindowTokens;
54036
+ }
54037
+ const item = {
54038
+ type: "contextCompaction",
54039
+ itemId: hostItemIdSchema.parse(this.#randomUUID())
54040
+ };
54041
+ active.compactionItem = item;
54042
+ this.#event({ type: "item.started", turnId: active.command.turnId, item });
54043
+ }
54044
+ #completeCompaction(active, event) {
54045
+ if (!active.compactionItem) {
54046
+ this.#startCompaction(active, {
54047
+ type: "compaction.started",
54048
+ ...event.contextWindowTokens !== void 0 ? { contextWindowTokens: event.contextWindowTokens } : {}
54049
+ });
54050
+ }
54051
+ const item = active.compactionItem;
54052
+ if (!item)
54053
+ return;
54054
+ active.compactionItem = null;
54055
+ const contextWindowTokens = event.contextWindowTokens ?? active.compactionContextWindow ?? (this.#state.effectiveModel ? this.#modelState.contextWindowTokensByModel.get(this.#state.effectiveModel.id) : void 0);
54056
+ active.compactionContextWindow = void 0;
54057
+ const outcome = event.outcome === "succeeded" ? { status: "succeeded" } : event.outcome === "cancelled" ? { status: "cancelled", reason: "Context compaction was cancelled" } : {
54058
+ status: "failed",
54059
+ error: {
54060
+ code: "nativeFailure",
54061
+ message: event.errorMessage ?? "Grok context compaction failed",
54062
+ retryable: true
54063
+ }
54064
+ };
54065
+ this.#completeItem(active, item, outcome);
54066
+ if (event.outcome !== "succeeded")
54067
+ return;
54068
+ const usage = usageFromCompact(event.tokensAfter, contextWindowTokens);
54069
+ if (usage)
54070
+ this.#publishUsage(usage, active.command.turnId);
54071
+ }
53578
54072
  #appendAgent(active, text, messageId) {
53579
54073
  const identity = messageId ?? "agent";
53580
54074
  if (active.agentMessageId !== identity) {
@@ -53756,6 +54250,10 @@ var GrokHarnessSession = class {
53756
54250
  const itemOutcome3 = outcome;
53757
54251
  this.#completeReasoning(active, itemOutcome3);
53758
54252
  this.#completeAgent(active, itemOutcome3);
54253
+ if (active.compactionItem) {
54254
+ this.#completeItem(active, active.compactionItem, itemOutcome3);
54255
+ active.compactionItem = null;
54256
+ }
53759
54257
  for (const tool of active.tools.values())
53760
54258
  this.#completeItem(active, tool.item, itemOutcome3);
53761
54259
  active.tools.clear();
@@ -53888,9 +54386,13 @@ var GrokAdapter = class {
53888
54386
  return cached2;
53889
54387
  }
53890
54388
  let transport = null;
54389
+ const startedAt = Date.now();
54390
+ let stage = "spawn";
53891
54391
  try {
53892
54392
  transport = this.#createTransport(cwd, () => void 0);
54393
+ stage = "startup";
53893
54394
  const initialize = await transport.inspect();
54395
+ stage = "model-catalog";
53894
54396
  const modelState = modelStateFromInitialize(initialize);
53895
54397
  if (!modelState)
53896
54398
  throw new GrokTransportError("protocolError", "Grok returned an invalid Model catalog");
@@ -53908,7 +54410,12 @@ var GrokAdapter = class {
53908
54410
  const normalized = normalizeError(error54, "unavailable");
53909
54411
  return {
53910
54412
  status: normalized.code === "notInstalled" ? "notInstalled" : "error",
53911
- error: normalized
54413
+ error: {
54414
+ ...normalized,
54415
+ stage,
54416
+ durationMs: Date.now() - startedAt,
54417
+ ...normalized.diagnostic || !transport?.stderrTail ? {} : { stderrTail: transport.stderrTail }
54418
+ }
53912
54419
  };
53913
54420
  }
53914
54421
  }
@@ -54210,7 +54717,7 @@ function normalizePiModelCatalog(nativeModels, effectiveModel, thinkingLevels, e
54210
54717
 
54211
54718
  // packages/adapters/pi/dist/pi-history.js
54212
54719
  var piHarnessId = harnessIdSchema.parse("pi");
54213
- function isRecord17(value) {
54720
+ function isRecord19(value) {
54214
54721
  return typeof value === "object" && value !== null && !Array.isArray(value);
54215
54722
  }
54216
54723
  function textContent(value) {
@@ -54218,12 +54725,12 @@ function textContent(value) {
54218
54725
  return value;
54219
54726
  if (!Array.isArray(value))
54220
54727
  return "";
54221
- return value.filter((part) => isRecord17(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
54728
+ return value.filter((part) => isRecord19(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
54222
54729
  }
54223
54730
  function thinkingContent(value) {
54224
54731
  if (!Array.isArray(value))
54225
54732
  return "";
54226
- return value.filter((part) => isRecord17(part) && part.type === "thinking" && typeof part.thinking === "string").map((part) => part.thinking).join("");
54733
+ return value.filter((part) => isRecord19(part) && part.type === "thinking" && typeof part.thinking === "string").map((part) => part.thinking).join("");
54227
54734
  }
54228
54735
  function validatedEntry(value) {
54229
54736
  if (typeof value.id !== "string" || value.id.length === 0 || value.parentId !== null && typeof value.parentId !== "string" || typeof value.type !== "string") {
@@ -54254,7 +54761,7 @@ function activePiEntries(history) {
54254
54761
  return reversed.reverse();
54255
54762
  }
54256
54763
  function message(entry) {
54257
- return entry.type === "message" && isRecord17(entry.message) ? entry.message : null;
54764
+ return entry.type === "message" && isRecord19(entry.message) ? entry.message : null;
54258
54765
  }
54259
54766
  function messageRole(entry) {
54260
54767
  const value = message(entry)?.role;
@@ -54316,7 +54823,7 @@ function snapshotItems(entries, outcome) {
54316
54823
  let projectedText = false;
54317
54824
  let projectedReasoning = false;
54318
54825
  for (const [ordinal, part] of content.entries()) {
54319
- if (!isRecord17(part))
54826
+ if (!isRecord19(part))
54320
54827
  continue;
54321
54828
  if (part.type === "thinking" && !projectedReasoning && reasoning.length > 0) {
54322
54829
  const item2 = {
@@ -54584,14 +55091,14 @@ function withNodeRuntimeOnPath2(environment, runtimeExecutable = process.execPat
54584
55091
  }
54585
55092
 
54586
55093
  // packages/adapters/pi/dist/pi-usage.js
54587
- function isRecord18(value) {
55094
+ function isRecord20(value) {
54588
55095
  return typeof value === "object" && value !== null && !Array.isArray(value);
54589
55096
  }
54590
55097
  function nonNegativeSafeInteger2(value) {
54591
55098
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
54592
55099
  }
54593
55100
  function optionalPiCacheHitRatePercent(value) {
54594
- if (!isRecord18(value) || value.role !== "assistant" || !isRecord18(value.usage))
55101
+ if (!isRecord20(value) || value.role !== "assistant" || !isRecord20(value.usage))
54595
55102
  return null;
54596
55103
  const input = nonNegativeSafeInteger2(value.usage.input);
54597
55104
  const cacheRead = nonNegativeSafeInteger2(value.usage.cacheRead);
@@ -54604,20 +55111,20 @@ function optionalPiCacheHitRatePercent(value) {
54604
55111
  function latestPiCacheHitRatePercent(history) {
54605
55112
  let latest = null;
54606
55113
  for (const entry of activePiEntries(history)) {
54607
- if (entry.type === "message" && isRecord18(entry.message) && entry.message.role === "assistant") {
55114
+ if (entry.type === "message" && isRecord20(entry.message) && entry.message.role === "assistant") {
54608
55115
  latest = optionalPiCacheHitRatePercent(entry.message);
54609
55116
  }
54610
55117
  }
54611
55118
  return latest;
54612
55119
  }
54613
55120
  function responseData(response, operation) {
54614
- if (!isRecord18(response.data)) {
55121
+ if (!isRecord20(response.data)) {
54615
55122
  throw new Error(`Pi RPC ${operation} response has no data`);
54616
55123
  }
54617
55124
  return response.data;
54618
55125
  }
54619
55126
  function contextUsage(value) {
54620
- if (!isRecord18(value))
55127
+ if (!isRecord20(value))
54621
55128
  throw new Error("Pi RPC context Usage is invalid");
54622
55129
  return parseHostUsage({
54623
55130
  contextUsedTokens: value.tokens,
@@ -54627,15 +55134,15 @@ function contextUsage(value) {
54627
55134
  function parsePiSessionUsage(response) {
54628
55135
  const data = responseData(response, "Session stats");
54629
55136
  const tokens = data.tokens;
54630
- if (tokens !== void 0 && !isRecord18(tokens)) {
55137
+ if (tokens !== void 0 && !isRecord20(tokens)) {
54631
55138
  throw new Error("Pi RPC Session stats tokens are invalid");
54632
55139
  }
54633
55140
  return parseHostUsage({
54634
- ...isRecord18(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
54635
- ...isRecord18(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
54636
- ...isRecord18(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
54637
- ...isRecord18(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
54638
- ...isRecord18(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
55141
+ ...isRecord20(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
55142
+ ...isRecord20(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
55143
+ ...isRecord20(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
55144
+ ...isRecord20(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
55145
+ ...isRecord20(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
54639
55146
  ...data.cost !== void 0 ? { totalCostUsd: data.cost } : {},
54640
55147
  ...data.contextUsage !== void 0 ? contextUsage(data.contextUsage) : {}
54641
55148
  });
@@ -54658,7 +55165,7 @@ function optionalPiStateContextUsage(value) {
54658
55165
  import { open, realpath } from "node:fs/promises";
54659
55166
  var MAX_SESSION_HEADER_BYTES = 64 * 1024;
54660
55167
  var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
54661
- function isRecord19(value) {
55168
+ function isRecord21(value) {
54662
55169
  return typeof value === "object" && value !== null && !Array.isArray(value);
54663
55170
  }
54664
55171
  async function readPiSessionHeader(sessionFile) {
@@ -54678,7 +55185,7 @@ async function readPiSessionHeader(sessionFile) {
54678
55185
  } catch {
54679
55186
  throw new Error("Pi Session header is not valid JSON");
54680
55187
  }
54681
- if (!isRecord19(parsed) || parsed.type !== "session" || typeof parsed.id !== "string" || parsed.id.length === 0 || typeof parsed.cwd !== "string" || parsed.cwd.length === 0) {
55188
+ if (!isRecord21(parsed) || parsed.type !== "session" || typeof parsed.id !== "string" || parsed.id.length === 0 || typeof parsed.cwd !== "string" || parsed.cwd.length === 0) {
54682
55189
  throw new Error("Pi Session header is invalid");
54683
55190
  }
54684
55191
  return { type: "session", id: parsed.id, cwd: parsed.cwd };
@@ -54705,9 +55212,11 @@ async function verifyPiSessionCwd(input) {
54705
55212
  // packages/adapters/pi/dist/pi-rpc-session.js
54706
55213
  var PiRpcFaultError = class extends Error {
54707
55214
  kind;
54708
- constructor(kind, message3) {
55215
+ diagnostic;
55216
+ constructor(kind, message3, diagnostic) {
54709
55217
  super(message3);
54710
55218
  this.kind = kind;
55219
+ this.diagnostic = diagnostic;
54711
55220
  this.name = "PiRpcFaultError";
54712
55221
  }
54713
55222
  };
@@ -54720,7 +55229,7 @@ var PiRpcUnsupportedCommandError = class extends Error {
54720
55229
  }
54721
55230
  };
54722
55231
  var textDecoder = new TextDecoder("utf-8", { fatal: true });
54723
- function isRecord20(value) {
55232
+ function isRecord22(value) {
54724
55233
  return typeof value === "object" && value !== null && !Array.isArray(value);
54725
55234
  }
54726
55235
  function message2(value) {
@@ -54732,13 +55241,13 @@ function nonBlankString2(value) {
54732
55241
  function parseNativeModel(value, context) {
54733
55242
  if (value === null || value === void 0)
54734
55243
  return null;
54735
- if (!isRecord20(value) || !nonBlankString2(value.provider) || !nonBlankString2(value.id)) {
55244
+ if (!isRecord22(value) || !nonBlankString2(value.provider) || !nonBlankString2(value.id)) {
54736
55245
  throw new PiRpcFaultError("protocolError", `Pi RPC returned an invalid ${context} Model`);
54737
55246
  }
54738
55247
  return { provider: value.provider, id: value.id };
54739
55248
  }
54740
55249
  function sessionStateData(response) {
54741
- const data = isRecord20(response.data) ? response.data : null;
55250
+ const data = isRecord22(response.data) ? response.data : null;
54742
55251
  if (!data)
54743
55252
  throw new PiRpcFaultError("protocolError", "Pi RPC state response has no data");
54744
55253
  return data;
@@ -54770,13 +55279,13 @@ function parseSessionStreaming(response) {
54770
55279
  return isStreaming;
54771
55280
  }
54772
55281
  function parseSessionHistory(response) {
54773
- const data = isRecord20(response.data) ? response.data : null;
55282
+ const data = isRecord22(response.data) ? response.data : null;
54774
55283
  if (!data || !Array.isArray(data.entries)) {
54775
55284
  throw new PiRpcFaultError("protocolError", "Pi RPC entries response has no Entries");
54776
55285
  }
54777
55286
  const entries = data.entries.map((entry) => {
54778
55287
  const parsed = jsonValueSchema.safeParse(entry);
54779
- if (!parsed.success || !isRecord20(parsed.data)) {
55288
+ if (!parsed.success || !isRecord22(parsed.data)) {
54780
55289
  throw new PiRpcFaultError("protocolError", "Pi RPC entries response contains an invalid Entry");
54781
55290
  }
54782
55291
  return parsed.data;
@@ -54787,7 +55296,7 @@ function parseSessionHistory(response) {
54787
55296
  return { entries, leafId: data.leafId };
54788
55297
  }
54789
55298
  function parseAvailableThinkingLevels(response) {
54790
- const data = isRecord20(response.data) ? response.data : null;
55299
+ const data = isRecord22(response.data) ? response.data : null;
54791
55300
  if (!data || !Array.isArray(data.levels) || data.levels.length === 0) {
54792
55301
  throw new PiRpcFaultError("protocolError", "Pi RPC Thinking catalog response has no levels");
54793
55302
  }
@@ -54804,35 +55313,35 @@ function parseAvailableThinkingLevels(response) {
54804
55313
  return levels;
54805
55314
  }
54806
55315
  function parseAvailableModels(response) {
54807
- const data = isRecord20(response.data) ? response.data : null;
55316
+ const data = isRecord22(response.data) ? response.data : null;
54808
55317
  if (!data || !Array.isArray(data.models)) {
54809
55318
  throw new PiRpcFaultError("protocolError", "Pi RPC Model catalog response has no models");
54810
55319
  }
54811
55320
  return data.models.map((model) => {
54812
55321
  const parsed = parseNativeModel(model, "catalog");
54813
- if (!parsed || !isRecord20(model) || typeof model.reasoning !== "boolean") {
55322
+ if (!parsed || !isRecord22(model) || typeof model.reasoning !== "boolean") {
54814
55323
  throw new PiRpcFaultError("protocolError", "Pi RPC catalog contains a Model without reasoning capability");
54815
55324
  }
54816
55325
  return { ...parsed, reasoning: model.reasoning };
54817
55326
  });
54818
55327
  }
54819
55328
  function assistantText2(value) {
54820
- if (!isRecord20(value) || value.role !== "assistant" || !Array.isArray(value.content))
55329
+ if (!isRecord22(value) || value.role !== "assistant" || !Array.isArray(value.content))
54821
55330
  return null;
54822
- return value.content.filter((content) => isRecord20(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
55331
+ return value.content.filter((content) => isRecord22(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
54823
55332
  }
54824
55333
  function assistantMessageId(value) {
54825
- if (!isRecord20(value) || value.role !== "assistant")
55334
+ if (!isRecord22(value) || value.role !== "assistant")
54826
55335
  return null;
54827
55336
  return nonBlankString2(value.responseId) ? value.responseId : null;
54828
55337
  }
54829
55338
  function assistantReasoning(value) {
54830
- if (!isRecord20(value) || value.role !== "assistant" || !Array.isArray(value.content))
55339
+ if (!isRecord22(value) || value.role !== "assistant" || !Array.isArray(value.content))
54831
55340
  return null;
54832
- return value.content.filter((content) => isRecord20(content) && content.type === "thinking" && typeof content.thinking === "string").map((content) => content.thinking).join("");
55341
+ return value.content.filter((content) => isRecord22(content) && content.type === "thinking" && typeof content.thinking === "string").map((content) => content.thinking).join("");
54833
55342
  }
54834
55343
  function assistantFailure(value) {
54835
- if (!isRecord20(value) || value.role !== "assistant")
55344
+ if (!isRecord22(value) || value.role !== "assistant")
54836
55345
  return void 0;
54837
55346
  if (value.stopReason !== "error" && value.stopReason !== "aborted")
54838
55347
  return null;
@@ -54852,7 +55361,7 @@ function signalProcessTree2(child, signal) {
54852
55361
  try {
54853
55362
  process.kill(-child.pid, signal);
54854
55363
  } catch (error54) {
54855
- if (!isRecord20(error54) || error54.code !== "ESRCH")
55364
+ if (!isRecord22(error54) || error54.code !== "ESRCH")
54856
55365
  throw error54;
54857
55366
  }
54858
55367
  }
@@ -54921,6 +55430,8 @@ var PiRpcSession = class {
54921
55430
  #pending = /* @__PURE__ */ new Map();
54922
55431
  #state = null;
54923
55432
  #latestCacheHitRatePercent;
55433
+ #manualCompaction = null;
55434
+ #stderrTail = "";
54924
55435
  constructor(options, processAdapter = nodeProcessAdapter) {
54925
55436
  if (options.sessionFile && options.forkSessionFile) {
54926
55437
  throw new Error("Pi RPC cannot combine Session resume and Fork startup");
@@ -54941,6 +55452,9 @@ var PiRpcSession = class {
54941
55452
  throw new Error("Pi RPC Session has not started");
54942
55453
  return this.#state;
54943
55454
  }
55455
+ get stderrTail() {
55456
+ return this.#stderrTail;
55457
+ }
54944
55458
  async start() {
54945
55459
  if (this.#child || this.#closed)
54946
55460
  throw new Error("Pi RPC Session cannot be started twice");
@@ -54964,14 +55478,16 @@ var PiRpcSession = class {
54964
55478
  this.#fail(new PiRpcFaultError("protocolError", "Pi RPC stdout ended mid-frame"));
54965
55479
  }
54966
55480
  });
54967
- child.stderr.resume();
55481
+ child.stderr.on("data", (chunk) => {
55482
+ this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
55483
+ });
54968
55484
  child.once("error", (error54) => {
54969
- const kind = isRecord20(error54) && error54.code === "ENOENT" ? "notInstalled" : "unavailable";
54970
- this.#fail(new PiRpcFaultError(kind, `Pi RPC failed to start: ${error54.message}`));
55485
+ const kind = isRecord22(error54) && error54.code === "ENOENT" ? "notInstalled" : "unavailable";
55486
+ this.#fail(new PiRpcFaultError(kind, `Pi RPC failed to start: ${error54.message}`, this.stderrTail));
54971
55487
  });
54972
55488
  child.once("exit", (code, signal) => {
54973
55489
  if (!this.#closed) {
54974
- this.#fail(new PiRpcFaultError("processExited", `Pi RPC exited (code=${code}, signal=${signal})`));
55490
+ this.#fail(new PiRpcFaultError("processExited", `Pi RPC exited (code=${code}, signal=${signal})`, this.stderrTail));
54975
55491
  }
54976
55492
  });
54977
55493
  await Promise.race([
@@ -54999,6 +55515,25 @@ var PiRpcSession = class {
54999
55515
  throw error54;
55000
55516
  }
55001
55517
  }
55518
+ async compact(customInstructions, onEvent) {
55519
+ if (!this.#child || !this.#state || this.#closed || this.#failed) {
55520
+ throw new Error("Pi RPC Session is unavailable");
55521
+ }
55522
+ if (this.#activeTurn || this.#manualCompaction || this.#compactionActive) {
55523
+ throw new Error("Pi RPC Session already has an active operation");
55524
+ }
55525
+ const result = new Promise((resolve2, reject) => {
55526
+ this.#manualCompaction = { onEvent, resolve: resolve2, reject };
55527
+ });
55528
+ try {
55529
+ await this.#send("compact", customInstructions ? { customInstructions } : {});
55530
+ } catch (error54) {
55531
+ const pending = this.#manualCompaction;
55532
+ this.#manualCompaction = null;
55533
+ pending?.reject(error54 instanceof Error ? error54 : new Error(message2(error54)));
55534
+ }
55535
+ return result;
55536
+ }
55002
55537
  async getSessionUsage() {
55003
55538
  try {
55004
55539
  const usage = parsePiSessionUsage(await this.#send("get_session_stats", {}));
@@ -55218,7 +55753,7 @@ var PiRpcSession = class {
55218
55753
  this.#buffer = this.#buffer.subarray(newline3 + 1);
55219
55754
  try {
55220
55755
  const value = JSON.parse(textDecoder.decode(frame));
55221
- if (!isRecord20(value) || typeof value.type !== "string") {
55756
+ if (!isRecord22(value) || typeof value.type !== "string") {
55222
55757
  throw new PiRpcFaultError("protocolError", "Pi RPC returned an invalid envelope");
55223
55758
  }
55224
55759
  this.#handle(value);
@@ -55238,9 +55773,10 @@ var PiRpcSession = class {
55238
55773
  if (value.type === "compaction_start") {
55239
55774
  this.#compactionActive = true;
55240
55775
  this.#compactionTurn = this.#activeTurn;
55241
- this.#compactionTurn?.onEvent({ type: "compaction.started" });
55776
+ const onEvent = this.#activeTurn?.onEvent ?? this.#manualCompaction?.onEvent;
55777
+ onEvent?.({ type: "compaction.started" });
55242
55778
  for (const pending of this.#pending.values()) {
55243
- if (pending.command !== "prompt" || !pending.timeout)
55779
+ if (pending.command !== "prompt" && pending.command !== "compact" || !pending.timeout)
55244
55780
  continue;
55245
55781
  clearTimeout(pending.timeout);
55246
55782
  pending.timeout = null;
@@ -55252,13 +55788,23 @@ var PiRpcSession = class {
55252
55788
  const compactionTurn = this.#compactionTurn;
55253
55789
  this.#compactionTurn = null;
55254
55790
  for (const [id2, pending] of this.#pending) {
55255
- if (pending.command === "prompt")
55791
+ if (pending.command === "prompt" || pending.command === "compact") {
55256
55792
  this.#armCommandTimeout(id2, pending);
55793
+ }
55257
55794
  }
55258
- compactionTurn?.onEvent({
55795
+ const outcome = value.aborted === true ? "cancelled" : isRecord22(value.result) ? "succeeded" : "failed";
55796
+ const event = {
55259
55797
  type: "compaction.completed",
55260
- outcome: value.aborted === true ? "cancelled" : isRecord20(value.result) ? "succeeded" : "failed",
55798
+ outcome,
55261
55799
  ...nonBlankString2(value.errorMessage) ? { errorMessage: value.errorMessage } : {}
55800
+ };
55801
+ compactionTurn?.onEvent(event);
55802
+ const manual = this.#manualCompaction;
55803
+ this.#manualCompaction = null;
55804
+ manual?.onEvent(event);
55805
+ manual?.resolve({
55806
+ outcome,
55807
+ ...event.errorMessage ? { errorMessage: event.errorMessage } : {}
55262
55808
  });
55263
55809
  return;
55264
55810
  }
@@ -55277,7 +55823,7 @@ var PiRpcSession = class {
55277
55823
  this.#startAssistantMessage(active, value.message);
55278
55824
  return;
55279
55825
  }
55280
- if (value.type === "message_update" && isRecord20(value.assistantMessageEvent)) {
55826
+ if (value.type === "message_update" && isRecord22(value.assistantMessageEvent)) {
55281
55827
  const event = value.assistantMessageEvent;
55282
55828
  if (event.type === "text_delta" && typeof event.delta === "string") {
55283
55829
  const messageId = this.#ensureAssistantMessage(active, value.message);
@@ -55592,7 +56138,7 @@ var PiRpcSession = class {
55592
56138
  });
55593
56139
  }
55594
56140
  #armCommandTimeout(id2, pending) {
55595
- if (pending.timeout || this.#pending.get(id2) !== pending || pending.command === "prompt" && this.#compactionActive) {
56141
+ if (pending.timeout || this.#pending.get(id2) !== pending || (pending.command === "prompt" || pending.command === "compact") && this.#compactionActive) {
55596
56142
  return;
55597
56143
  }
55598
56144
  pending.timeout = setTimeout(() => {
@@ -55657,6 +56203,9 @@ var PiRpcSession = class {
55657
56203
  pending.reject(error54);
55658
56204
  }
55659
56205
  this.#pending.clear();
56206
+ const manual = this.#manualCompaction;
56207
+ this.#manualCompaction = null;
56208
+ manual?.reject(error54);
55660
56209
  this.#rejectActiveTurn(error54);
55661
56210
  }
55662
56211
  #fail(error54) {
@@ -55670,8 +56219,19 @@ var PiRpcSession = class {
55670
56219
 
55671
56220
  // packages/adapters/pi/dist/pi-adapter.js
55672
56221
  var piHarnessId2 = harnessIdSchema.parse("pi");
56222
+ var piCommandCatalog = harnessCommandCatalogSchema.parse({
56223
+ commands: [
56224
+ {
56225
+ id: "pi.compact",
56226
+ invocation: "/compact",
56227
+ label: "Compact context",
56228
+ description: "Compact the current conversation context",
56229
+ argumentMode: "text"
56230
+ }
56231
+ ]
56232
+ });
55673
56233
  var DEFAULT_TOOL_OUTPUT_LIMIT3 = 64e3;
55674
- function isRecord21(value) {
56234
+ function isRecord23(value) {
55675
56235
  return typeof value === "object" && value !== null && !Array.isArray(value);
55676
56236
  }
55677
56237
  function errorMessage(error54) {
@@ -55699,7 +56259,8 @@ function normalizedError2(error54, fallbackCode) {
55699
56259
  return {
55700
56260
  code: error54.kind,
55701
56261
  message: error54.message,
55702
- retryable: error54.kind !== "notInstalled"
56262
+ retryable: error54.kind !== "notInstalled",
56263
+ ...error54.diagnostic ? { stderrTail: error54.diagnostic } : {}
55703
56264
  };
55704
56265
  }
55705
56266
  return {
@@ -55745,7 +56306,7 @@ function nativeModelForHistory(state) {
55745
56306
  return nativeModelFromState(state);
55746
56307
  }
55747
56308
  function sessionFileFromRef(ref) {
55748
- if (ref.harnessId !== piHarnessId2 || !isRecord21(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
56309
+ if (ref.harnessId !== piHarnessId2 || !isRecord23(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
55749
56310
  throw new Error("Pi Native Session Ref has no resumable Session file");
55750
56311
  }
55751
56312
  return ref.locator.sessionFile;
@@ -55760,9 +56321,9 @@ function toolFailure2(toolName) {
55760
56321
  function nativeText(value) {
55761
56322
  if (typeof value === "string")
55762
56323
  return value;
55763
- if (!isRecord21(value) || !Array.isArray(value.content))
56324
+ if (!isRecord23(value) || !Array.isArray(value.content))
55764
56325
  return "";
55765
- return value.content.filter((content) => isRecord21(content) && content.type === "text" && typeof content.text === "string").map(({ text }) => text).join("");
56326
+ return value.content.filter((content) => isRecord23(content) && content.type === "text" && typeof content.text === "string").map(({ text }) => text).join("");
55766
56327
  }
55767
56328
  function boundedOutput(value, limit) {
55768
56329
  const text = nativeText(value);
@@ -55778,10 +56339,10 @@ function outputText(output) {
55778
56339
  return output?.content.filter((content) => content.type === "text").map(({ text }) => text).join("") ?? "";
55779
56340
  }
55780
56341
  function stringField3(value, key) {
55781
- return isRecord21(value) && typeof value[key] === "string" ? value[key] : void 0;
56342
+ return isRecord23(value) && typeof value[key] === "string" ? value[key] : void 0;
55782
56343
  }
55783
56344
  function numberField2(value, key) {
55784
- if (!isRecord21(value))
56345
+ if (!isRecord23(value))
55785
56346
  return void 0;
55786
56347
  const field = value[key];
55787
56348
  return typeof field === "number" || field === null ? field : void 0;
@@ -55790,7 +56351,7 @@ function stripDiffPrefix(path21) {
55790
56351
  return path21.startsWith("a/") || path21.startsWith("b/") ? path21.slice(2) : path21;
55791
56352
  }
55792
56353
  function reliableFileChange(result) {
55793
- if (!isRecord21(result) || !isRecord21(result.details) || typeof result.details.patch !== "string") {
56354
+ if (!isRecord23(result) || !isRecord23(result.details) || typeof result.details.patch !== "string") {
55794
56355
  return null;
55795
56356
  }
55796
56357
  const patch = result.details.patch;
@@ -55817,6 +56378,7 @@ function delay3(milliseconds) {
55817
56378
  var PiHarnessSession = class {
55818
56379
  harnessId = piHarnessId2;
55819
56380
  capabilities;
56381
+ commands;
55820
56382
  initialState;
55821
56383
  initialUsage;
55822
56384
  outputs;
@@ -55855,6 +56417,10 @@ var PiHarnessSession = class {
55855
56417
  },
55856
56418
  history: { fork: true, forkAcrossCwd: true, rollbackLastTurn: true }
55857
56419
  };
56420
+ this.commands = {
56421
+ list: async () => ({ ok: true, value: piCommandCatalog }),
56422
+ execute: (command) => this.#executeHarnessCommand(command)
56423
+ };
55858
56424
  this.#transport = options.startedTransport ?? null;
55859
56425
  this.initialState = options.startedTransport ? harnessStateFromPi(options.startedTransport.state, options.startedThinkingLevels ?? null) : {};
55860
56426
  this.initialUsage = options.initialUsage ?? null;
@@ -56238,6 +56804,112 @@ var PiHarnessSession = class {
56238
56804
  return { ok: false, error: normalized };
56239
56805
  }
56240
56806
  }
56807
+ async #executeHarnessCommand(command) {
56808
+ if (command.commandId !== "pi.compact") {
56809
+ return {
56810
+ ok: false,
56811
+ error: {
56812
+ code: "unsupported",
56813
+ message: `Pi does not expose Harness command '${command.commandId}'`,
56814
+ retryable: false
56815
+ }
56816
+ };
56817
+ }
56818
+ if (this.#acceptingTurn || this.#active || this.#configuring) {
56819
+ return {
56820
+ ok: false,
56821
+ error: {
56822
+ code: "sessionBusy",
56823
+ message: "Pi Session already has an active operation",
56824
+ retryable: true
56825
+ }
56826
+ };
56827
+ }
56828
+ const arguments_2 = command.arguments;
56829
+ const customInstructions = arguments_2?.text;
56830
+ if (customInstructions !== void 0 && typeof customInstructions !== "string") {
56831
+ return {
56832
+ ok: false,
56833
+ error: {
56834
+ code: "invalidRequest",
56835
+ message: "Pi compact command argument 'text' must be a string",
56836
+ retryable: false
56837
+ }
56838
+ };
56839
+ }
56840
+ if (arguments_2 && Object.keys(arguments_2).some((key) => key !== "text")) {
56841
+ return {
56842
+ ok: false,
56843
+ error: {
56844
+ code: "invalidRequest",
56845
+ message: "Pi compact command has an unknown argument",
56846
+ retryable: false
56847
+ }
56848
+ };
56849
+ }
56850
+ this.#acceptingTurn = true;
56851
+ try {
56852
+ let transport;
56853
+ try {
56854
+ transport = await this.#ensureTransport();
56855
+ } catch (error54) {
56856
+ return { ok: false, error: normalizedError2(error54, "unavailable") };
56857
+ }
56858
+ const turnCommand = {
56859
+ type: "turn.start",
56860
+ turnId: command.turnId,
56861
+ input: []
56862
+ };
56863
+ let resolveCompletion = () => void 0;
56864
+ const completion = new Promise((resolve2) => {
56865
+ resolveCompletion = resolve2;
56866
+ });
56867
+ const active = {
56868
+ command: turnCommand,
56869
+ agentItem: null,
56870
+ agentMessageId: null,
56871
+ compactionItem: null,
56872
+ sawAssistantMessage: false,
56873
+ reasoningItem: null,
56874
+ tools: /* @__PURE__ */ new Map(),
56875
+ interactions: /* @__PURE__ */ new Map(),
56876
+ interactionByNativeId: /* @__PURE__ */ new Map(),
56877
+ cancellationRequested: false,
56878
+ beforeNativeTurnKeys: /* @__PURE__ */ new Set(),
56879
+ completion,
56880
+ resolveCompletion
56881
+ };
56882
+ this.#active = active;
56883
+ this.#event({ type: "turn.started", turnId: command.turnId });
56884
+ void transport.compact(customInstructions, (event) => this.#handleTurnEvent(active, event)).then((result) => {
56885
+ if (result.outcome === "succeeded") {
56886
+ this.#completeTurn(active, { status: "succeeded" });
56887
+ } else if (result.outcome === "cancelled") {
56888
+ this.#completeTurn(active, {
56889
+ status: "cancelled",
56890
+ reason: "Context compaction was cancelled"
56891
+ });
56892
+ } else {
56893
+ this.#completeTurn(active, {
56894
+ status: "failed",
56895
+ error: {
56896
+ code: "nativeFailure",
56897
+ message: result.errorMessage ?? "Pi context compaction failed",
56898
+ retryable: true
56899
+ }
56900
+ });
56901
+ }
56902
+ }).catch((error54) => {
56903
+ this.#completeTurn(active, {
56904
+ status: "failed",
56905
+ error: normalizedError2(error54, "nativeFailure")
56906
+ });
56907
+ });
56908
+ return { ok: true, value: { turnId: command.turnId } };
56909
+ } finally {
56910
+ this.#acceptingTurn = false;
56911
+ }
56912
+ }
56241
56913
  async #ensureTransport() {
56242
56914
  if (this.#transport)
56243
56915
  return this.#transport;
@@ -56783,11 +57455,16 @@ var PiAdapter = class {
56783
57455
  });
56784
57456
  }
56785
57457
  async #inspectCwd(cwd) {
57458
+ const startedAt = Date.now();
57459
+ let stage = "spawn";
56786
57460
  const transport = this.#createTransport({ cwd, onFault: () => void 0 });
56787
57461
  this.#inspections.add(transport);
56788
57462
  try {
57463
+ stage = "startup";
56789
57464
  await transport.start();
57465
+ stage = "model-catalog";
56790
57466
  const models = await transport.getAvailableModels();
57467
+ stage = "capabilities";
56791
57468
  const thinkingLevels = await transport.getAvailableThinkingLevels();
56792
57469
  this.#thinkingSelectionSupported = thinkingLevels !== null;
56793
57470
  const catalog = normalizePiModelCatalog(models, nativeModelFromState(transport.state), thinkingLevels, transport.state.thinkingLevel);
@@ -56809,7 +57486,12 @@ var PiAdapter = class {
56809
57486
  const normalized = normalizedError2(error54, "unavailable");
56810
57487
  return {
56811
57488
  status: normalized.code === "notInstalled" ? "notInstalled" : "error",
56812
- error: normalized
57489
+ error: {
57490
+ ...normalized,
57491
+ stage,
57492
+ durationMs: Date.now() - startedAt,
57493
+ ...normalized.stderrTail || !transport.stderrTail ? {} : { stderrTail: transport.stderrTail }
57494
+ }
56813
57495
  };
56814
57496
  } finally {
56815
57497
  this.#inspections.delete(transport);
@@ -57700,7 +58382,7 @@ var packageMetadata5 = {
57700
58382
  var TITLE_MAX_LENGTH = 120;
57701
58383
  var DESCRIPTION_MAX_LENGTH = 500;
57702
58384
  var SERVER_NAME_MAX_LENGTH = 80;
57703
- function isRecord22(value) {
58385
+ function isRecord24(value) {
57704
58386
  return typeof value === "object" && value !== null && !Array.isArray(value);
57705
58387
  }
57706
58388
  function boundedText(value, field, maxLength) {
@@ -57744,7 +58426,7 @@ function responseError(message3) {
57744
58426
  function responsePersist(value) {
57745
58427
  if (value === void 0 || value === null)
57746
58428
  return null;
57747
- if (!isRecord22(value) || Object.keys(value).length !== 1 || value.persist !== "session" && value.persist !== "always") {
58429
+ if (!isRecord24(value) || Object.keys(value).length !== 1 || value.persist !== "session" && value.persist !== "always") {
57748
58430
  throw responseError("contains malformed persist metadata");
57749
58431
  }
57750
58432
  return value.persist;
@@ -57787,7 +58469,7 @@ function projectCodexApprovalRequest(input) {
57787
58469
  },
57788
58470
  denyResponse,
57789
58471
  parseResponse(result) {
57790
- if (!isRecord22(result) || typeof result.action !== "string") {
58472
+ if (!isRecord24(result) || typeof result.action !== "string") {
57791
58473
  throw responseError("missing action");
57792
58474
  }
57793
58475
  if (Object.keys(result).some((key) => key !== "action" && key !== "content" && key !== "_meta")) {
@@ -57795,7 +58477,7 @@ function projectCodexApprovalRequest(input) {
57795
58477
  }
57796
58478
  const selectedPersist = responsePersist(result._meta);
57797
58479
  if (result.action === "accept") {
57798
- if ("content" in result && (!isRecord22(result.content) || Object.keys(result.content).length !== 0)) {
58480
+ if ("content" in result && (!isRecord24(result.content) || Object.keys(result.content).length !== 0)) {
57799
58481
  throw responseError("contains non-empty accepted content");
57800
58482
  }
57801
58483
  if (selectedPersist === "session") {
@@ -57822,7 +58504,7 @@ function projectCodexApprovalRequest(input) {
57822
58504
  }
57823
58505
 
57824
58506
  // packages/protocol-core/dist/codex-question.js
57825
- function isRecord23(value) {
58507
+ function isRecord25(value) {
57826
58508
  return typeof value === "object" && value !== null && !Array.isArray(value);
57827
58509
  }
57828
58510
  function responseError2(message3) {
@@ -57891,7 +58573,7 @@ function projectCodexQuestionRequest(input) {
57891
58573
  }
57892
58574
  },
57893
58575
  parseResponse(result) {
57894
- if (!isRecord23(result) || !isRecord23(result.answers)) {
58576
+ if (!isRecord25(result) || !isRecord25(result.answers)) {
57895
58577
  throw responseError2("missing answers object");
57896
58578
  }
57897
58579
  const rawAnswers = result.answers;
@@ -57904,7 +58586,7 @@ function projectCodexQuestionRequest(input) {
57904
58586
  const question = interaction.questions.find(({ id: id2 }) => id2 === questionId);
57905
58587
  if (!question)
57906
58588
  throw responseError2("contains an unknown Question ID");
57907
- if (!isRecord23(answerValue) || !Array.isArray(answerValue.answers)) {
58589
+ if (!isRecord25(answerValue) || !Array.isArray(answerValue.answers)) {
57908
58590
  throw responseError2("answer entry has no answers array");
57909
58591
  }
57910
58592
  const values = answerValue.answers;
@@ -58514,7 +59196,7 @@ var CodexTurnProjector = class {
58514
59196
  };
58515
59197
 
58516
59198
  // packages/protocol-core/dist/thread-fork.js
58517
- function isRecord24(value) {
59199
+ function isRecord26(value) {
58518
59200
  return typeof value === "object" && value !== null && !Array.isArray(value);
58519
59201
  }
58520
59202
  function optionalText(params, name, options = {}) {
@@ -58537,7 +59219,7 @@ function optionalBoolean(params, name) {
58537
59219
  function decodeThreadForkRequest(request) {
58538
59220
  if (request.method !== "thread/fork")
58539
59221
  return null;
58540
- if (!isRecord24(request.params))
59222
+ if (!isRecord26(request.params))
58541
59223
  throw new Error("thread/fork params must be an object");
58542
59224
  const params = request.params;
58543
59225
  const threadId2 = optionalText(params, "threadId");
@@ -58573,7 +59255,7 @@ function decodeThreadForkRequest(request) {
58573
59255
  function decodeThreadRollbackRequest(request) {
58574
59256
  if (request.method !== "thread/rollback")
58575
59257
  return null;
58576
- if (!isRecord24(request.params))
59258
+ if (!isRecord26(request.params))
58577
59259
  throw new Error("thread/rollback params must be an object");
58578
59260
  const { threadId: threadId2, numTurns } = request.params;
58579
59261
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -58667,13 +59349,13 @@ var THREAD_SOURCE_KINDS = /* @__PURE__ */ new Set([
58667
59349
  "subAgentOther",
58668
59350
  "unknown"
58669
59351
  ]);
58670
- function isRecord25(value) {
59352
+ function isRecord27(value) {
58671
59353
  return typeof value === "object" && value !== null && !Array.isArray(value);
58672
59354
  }
58673
59355
  function paramsObject(request, method) {
58674
59356
  if (request.params === void 0 && method === "thread/list")
58675
59357
  return {};
58676
- if (!isRecord25(request.params))
59358
+ if (!isRecord27(request.params))
58677
59359
  throw new Error(`${method} params must be an object`);
58678
59360
  return request.params;
58679
59361
  }
@@ -58745,7 +59427,7 @@ function cursorPayload(value) {
58745
59427
  };
58746
59428
  }
58747
59429
  function parseCursorPayload(value) {
58748
- if (!isRecord25(value) || value.formatVersion !== 1)
59430
+ if (!isRecord27(value) || value.formatVersion !== 1)
58749
59431
  throw new Error("Host cursor is invalid");
58750
59432
  const { queryFingerprint: fingerprint, sortDirection: sortDirection2, officialCursor, officialDone } = value;
58751
59433
  const { externalAnchor: externalAnchor2, externalDone } = value;
@@ -58754,7 +59436,7 @@ function parseCursorPayload(value) {
58754
59436
  }
58755
59437
  let anchor = null;
58756
59438
  if (externalAnchor2 !== null) {
58757
- if (!isRecord25(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
59439
+ if (!isRecord27(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
58758
59440
  throw new Error("Host cursor is invalid");
58759
59441
  }
58760
59442
  anchor = {
@@ -58874,7 +59556,7 @@ function decodeThreadMetadataUpdateRequest(request) {
58874
59556
  if (params.gitInfo === null) {
58875
59557
  gitInfo = null;
58876
59558
  } else if (params.gitInfo !== void 0) {
58877
- if (!isRecord25(params.gitInfo)) {
59559
+ if (!isRecord27(params.gitInfo)) {
58878
59560
  throw new Error("thread/metadata/update params.gitInfo must be an object or null");
58879
59561
  }
58880
59562
  gitInfo = {};
@@ -58902,7 +59584,7 @@ function optionalCursor(value, name) {
58902
59584
  return value;
58903
59585
  }
58904
59586
  function decodeOfficialThreadListPage(value) {
58905
- if (!isRecord25(value) || !Array.isArray(value.data) || value.data.some((row) => !isRecord25(row))) {
59587
+ if (!isRecord27(value) || !Array.isArray(value.data) || value.data.some((row) => !isRecord27(row))) {
58906
59588
  throw new Error("Official thread/list response is invalid");
58907
59589
  }
58908
59590
  return {
@@ -60131,6 +60813,12 @@ var ExternalThreadRuntime = class {
60131
60813
  const effectiveModel = input.requestedModel ?? initialState.effectiveModel;
60132
60814
  const effectiveThinkingOptionId = input.requestedThinkingOptionId ?? initialState.effectiveThinkingOptionId;
60133
60815
  const effectivePermissionModeId = input.requestedPermissionModeId ?? initialState.effectivePermissionModeId;
60816
+ const observerState = {
60817
+ ...initialState,
60818
+ ...effectiveModel ? { effectiveModel } : {},
60819
+ ...effectiveThinkingOptionId ? { effectiveThinkingOptionId } : {},
60820
+ ...effectivePermissionModeId ? { effectivePermissionModeId } : {}
60821
+ };
60134
60822
  const externalThread = {
60135
60823
  id: input.record.hostThreadId,
60136
60824
  cwd: input.record.cwd,
@@ -60142,7 +60830,7 @@ var ExternalThreadRuntime = class {
60142
60830
  ...effectivePermissionModeId ? { requestedPermissionModeId: effectivePermissionModeId } : {},
60143
60831
  record: input.record,
60144
60832
  sessionId: input.sessionId,
60145
- stateObserver: new SessionStateObserver(initialState),
60833
+ stateObserver: new SessionStateObserver(observerState),
60146
60834
  thread: input.thread,
60147
60835
  transportModelId: input.record.transportModelId,
60148
60836
  turns: input.turns,
@@ -60153,6 +60841,7 @@ var ExternalThreadRuntime = class {
60153
60841
  usageTurnId: null,
60154
60842
  projectedTurns: /* @__PURE__ */ new Map(),
60155
60843
  responseGates: /* @__PURE__ */ new Map(),
60844
+ ephemeralTurnIds: /* @__PURE__ */ new Set(),
60156
60845
  persistenceError: null,
60157
60846
  ignoredInteractionIds: /* @__PURE__ */ new Set()
60158
60847
  };
@@ -60308,7 +60997,7 @@ var ExternalThreadRuntime = class {
60308
60997
  import { randomUUID as randomUUID8 } from "node:crypto";
60309
60998
  var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
60310
60999
  var MAX_RETIRED_IDS = 1024;
60311
- function isRecord26(value) {
61000
+ function isRecord28(value) {
60312
61001
  return typeof value === "object" && value !== null && !Array.isArray(value);
60313
61002
  }
60314
61003
  var OfficialRequestBroker = class {
@@ -60351,7 +61040,7 @@ var OfficialRequestBroker = class {
60351
61040
  });
60352
61041
  }
60353
61042
  handle(value) {
60354
- if (!isRecord26(value) || typeof value.id !== "string") return false;
61043
+ if (!isRecord28(value) || typeof value.id !== "string") return false;
60355
61044
  const pending = this.#pending.get(value.id);
60356
61045
  if (!pending) return this.#retired.has(value.id);
60357
61046
  clearTimeout(pending.timeout);
@@ -60380,11 +61069,11 @@ var OfficialRequestBroker = class {
60380
61069
  };
60381
61070
 
60382
61071
  // packages/host-runtime/src/route-observation.ts
60383
- function isRecord27(value) {
61072
+ function isRecord29(value) {
60384
61073
  return typeof value === "object" && value !== null && !Array.isArray(value);
60385
61074
  }
60386
61075
  function classifyThreadPurpose(request) {
60387
- return isRecord27(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
61076
+ return isRecord29(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
60388
61077
  }
60389
61078
  var RequestRouteObservationTracker = class {
60390
61079
  #nextCreateOrdinal = 0;
@@ -60409,13 +61098,13 @@ var RequestRouteObservationTracker = class {
60409
61098
  this.#createByThreadId.set(threadId2, tracked);
60410
61099
  }
60411
61100
  bindOfficialResponse(response) {
60412
- if (!isRecord27(response) || !("id" in response)) return;
61101
+ if (!isRecord29(response) || !("id" in response)) return;
60413
61102
  const tracked = this.#pendingByRequestId.get(response.id);
60414
61103
  if (!tracked) return;
60415
61104
  this.#pendingByRequestId.delete(response.id);
60416
61105
  const result = response.result;
60417
- const thread = isRecord27(result) ? result.thread : null;
60418
- if (isRecord27(thread) && typeof thread.id === "string") {
61106
+ const thread = isRecord29(result) ? result.thread : null;
61107
+ if (isRecord29(thread) && typeof thread.id === "string") {
60419
61108
  this.#createByThreadId.set(thread.id, tracked);
60420
61109
  }
60421
61110
  }
@@ -60581,11 +61270,11 @@ var OfficialThreadListError = class extends Error {
60581
61270
  }
60582
61271
  rpcError;
60583
61272
  };
60584
- function isRecord28(value) {
61273
+ function isRecord30(value) {
60585
61274
  return typeof value === "object" && value !== null && !Array.isArray(value);
60586
61275
  }
60587
61276
  function officialThreadListPageFromResponse(response) {
60588
- if (isRecord28(response.error)) {
61277
+ if (isRecord30(response.error)) {
60589
61278
  if (!Number.isSafeInteger(response.error.code) || typeof response.error.message !== "string") {
60590
61279
  throw new Error("Official thread/list error response is invalid");
60591
61280
  }
@@ -60745,14 +61434,14 @@ async function aggregateThreadList(input) {
60745
61434
  }
60746
61435
 
60747
61436
  // packages/host-runtime/src/app-server-host.ts
60748
- function isRecord29(value) {
61437
+ function isRecord31(value) {
60749
61438
  return typeof value === "object" && value !== null && !Array.isArray(value);
60750
61439
  }
60751
61440
  function isCreditsAdapter(adapter) {
60752
61441
  return typeof adapter.credits === "function" && typeof adapter.refreshCredits === "function";
60753
61442
  }
60754
61443
  function projectAccountCredits(value) {
60755
- if (!isRecord29(value)) return null;
61444
+ if (!isRecord31(value)) return null;
60756
61445
  const rest = { ...value };
60757
61446
  delete rest.fetchedAt;
60758
61447
  const parsed = accountCreditsSnapshotSchema.safeParse(rest);
@@ -60852,12 +61541,12 @@ function classifyCreateRequestRoute(request, defaultAgent2) {
60852
61541
  };
60853
61542
  }
60854
61543
  function requestObject(request) {
60855
- if (!isRecord29(request.params)) throw new Error(`${request.method} params must be an object`);
61544
+ if (!isRecord31(request.params)) throw new Error(`${request.method} params must be an object`);
60856
61545
  return request.params;
60857
61546
  }
60858
61547
  function requestText(params) {
60859
61548
  if (!Array.isArray(params.input)) throw new Error("turn/start input must be an array");
60860
- const text = params.input.filter((item) => isRecord29(item) && item.type === "text").map((item) => item.text).filter((value) => typeof value === "string").join("\n");
61549
+ const text = params.input.filter((item) => isRecord31(item) && item.type === "text").map((item) => item.text).filter((value) => typeof value === "string").join("\n");
60861
61550
  if (!text) throw new Error("turn/start must contain text input");
60862
61551
  return text;
60863
61552
  }
@@ -61046,6 +61735,14 @@ var AppServerHost = class {
61046
61735
  await this.#selectThreadPermissionMode(request);
61047
61736
  continue;
61048
61737
  }
61738
+ if (request.method === "codexhost/thread/commands/inspect") {
61739
+ await this.#inspectThreadCommands(request);
61740
+ continue;
61741
+ }
61742
+ if (request.method === "codexhost/thread/command/execute") {
61743
+ await this.#executeThreadCommand(request);
61744
+ continue;
61745
+ }
61049
61746
  if (request.method === "thread/list") {
61050
61747
  let listRequest;
61051
61748
  try {
@@ -61131,7 +61828,7 @@ var AppServerHost = class {
61131
61828
  continue;
61132
61829
  }
61133
61830
  if (request.method === "thread/fork") {
61134
- const params = isRecord29(request.params) ? request.params : {};
61831
+ const params = isRecord31(request.params) ? request.params : {};
61135
61832
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
61136
61833
  if (resolution.kind === "error") {
61137
61834
  await this.#writer.json(
@@ -61154,7 +61851,7 @@ var AppServerHost = class {
61154
61851
  }
61155
61852
  }
61156
61853
  if (request.method === "thread/rollback") {
61157
- const params = isRecord29(request.params) ? request.params : {};
61854
+ const params = isRecord31(request.params) ? request.params : {};
61158
61855
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
61159
61856
  if (resolution.kind === "error") {
61160
61857
  await this.#writer.json(
@@ -61294,7 +61991,7 @@ var AppServerHost = class {
61294
61991
  continue;
61295
61992
  }
61296
61993
  }
61297
- if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord29(request.params) && typeof request.params.threadId === "string") {
61994
+ if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord31(request.params) && typeof request.params.threadId === "string") {
61298
61995
  const location = await this.#locateExternalThread(request.params.threadId);
61299
61996
  if (await this.#writeResolutionError(request, location)) continue;
61300
61997
  if (location.kind === "external") {
@@ -61540,6 +62237,156 @@ var AppServerHost = class {
61540
62237
  );
61541
62238
  }
61542
62239
  }
62240
+ async #inspectThreadCommands(request) {
62241
+ const params = threadCommandsInspectParamsSchema.safeParse(request.params);
62242
+ if (!params.success) {
62243
+ await this.#writer.json(
62244
+ rpcError(request, -32602, "Invalid Thread command inspection params")
62245
+ );
62246
+ return;
62247
+ }
62248
+ const resolution = await this.#resolveExternalThread(params.data.threadId);
62249
+ if (await this.#writeResolutionError(request, resolution)) return;
62250
+ if (resolution.kind !== "external" || !resolution.thread.session.commands) {
62251
+ await this.#writer.json(rpcEnvelope(request, { result: { commands: [] } }));
62252
+ return;
62253
+ }
62254
+ const result = await resolution.thread.session.commands.list();
62255
+ if (!result.ok) {
62256
+ await this.#writer.json(rpcError(request, -32078, result.error.message));
62257
+ return;
62258
+ }
62259
+ try {
62260
+ await this.#writer.json(
62261
+ rpcEnvelope(request, {
62262
+ result: jsonValueSchema.parse(harnessCommandCatalogSchema.parse(result.value))
62263
+ })
62264
+ );
62265
+ } catch (error54) {
62266
+ await this.#writer.json(
62267
+ rpcError(request, -32078, `Harness command catalog is invalid: ${errorMessage3(error54)}`)
62268
+ );
62269
+ }
62270
+ }
62271
+ async #executeThreadCommand(request) {
62272
+ const params = threadCommandExecuteParamsSchema.safeParse(request.params);
62273
+ if (!params.success) {
62274
+ await this.#writer.json(rpcError(request, -32602, "Invalid Thread command parameters"));
62275
+ return;
62276
+ }
62277
+ const resolution = await this.#resolveExternalThread(params.data.threadId);
62278
+ if (await this.#writeResolutionError(request, resolution)) return;
62279
+ if (resolution.kind !== "external") {
62280
+ await this.#writer.json(rpcError(request, -32078, "Thread is not externally owned"));
62281
+ return;
62282
+ }
62283
+ const thread = resolution.thread;
62284
+ if (thread.running) {
62285
+ await this.#writer.json(
62286
+ rpcError(request, -32072, "External Thread already has an active operation")
62287
+ );
62288
+ return;
62289
+ }
62290
+ const commands = thread.session.commands;
62291
+ if (!commands) {
62292
+ await this.#writer.json(
62293
+ rpcError(request, -32078, "External Harness does not expose commands")
62294
+ );
62295
+ return;
62296
+ }
62297
+ const catalog = await commands.list();
62298
+ if (!catalog.ok) {
62299
+ await this.#writer.json(rpcError(request, -32078, catalog.error.message));
62300
+ return;
62301
+ }
62302
+ if (!catalog.value.commands.some(({ id: id2 }) => id2 === params.data.commandId)) {
62303
+ await this.#writer.json(
62304
+ rpcError(
62305
+ request,
62306
+ -32078,
62307
+ `External Harness does not expose command '${params.data.commandId}'`
62308
+ )
62309
+ );
62310
+ return;
62311
+ }
62312
+ try {
62313
+ await this.#startExternalCommand(
62314
+ request,
62315
+ thread,
62316
+ params.data.commandId,
62317
+ params.data.arguments,
62318
+ params.data.turnId,
62319
+ "command"
62320
+ );
62321
+ } catch (error54) {
62322
+ this.#diagnose(error54);
62323
+ await this.#writer.json(
62324
+ rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error54)}`)
62325
+ );
62326
+ }
62327
+ }
62328
+ async #startExternalCommand(request, thread, commandId, arguments_2, requestedTurnId, responseKind) {
62329
+ const commands = thread.session.commands;
62330
+ if (!commands) {
62331
+ await this.#writer.json(
62332
+ rpcError(request, -32078, "External Harness does not expose commands")
62333
+ );
62334
+ return;
62335
+ }
62336
+ if (thread.running) {
62337
+ await this.#writer.json(
62338
+ rpcError(request, -32072, "External Thread already has an active operation")
62339
+ );
62340
+ return;
62341
+ }
62342
+ const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
62343
+ const projection = {
62344
+ projector: new CodexTurnProjector({
62345
+ threadId: thread.id,
62346
+ turnId,
62347
+ cwd: thread.cwd,
62348
+ startedAtMs: Date.now()
62349
+ })
62350
+ };
62351
+ const gate = turnProjectionGate();
62352
+ thread.running = true;
62353
+ thread.activeTurnId = turnId;
62354
+ thread.projectedTurns.set(turnId, projection);
62355
+ thread.responseGates.set(turnId, gate);
62356
+ thread.ephemeralTurnIds.add(turnId);
62357
+ let result;
62358
+ try {
62359
+ result = await commands.execute({
62360
+ turnId,
62361
+ commandId,
62362
+ ...arguments_2 ? { arguments: arguments_2 } : {}
62363
+ });
62364
+ } catch (error54) {
62365
+ thread.running = false;
62366
+ thread.activeTurnId = null;
62367
+ thread.projectedTurns.delete(turnId);
62368
+ thread.responseGates.delete(turnId);
62369
+ thread.ephemeralTurnIds.delete(turnId);
62370
+ gate.resolve();
62371
+ throw error54;
62372
+ }
62373
+ if (!result.ok) {
62374
+ thread.running = false;
62375
+ thread.activeTurnId = null;
62376
+ thread.projectedTurns.delete(turnId);
62377
+ thread.responseGates.delete(turnId);
62378
+ thread.ephemeralTurnIds.delete(turnId);
62379
+ gate.resolve();
62380
+ await this.#writer.json(rpcError(request, -32073, result.error.message));
62381
+ return;
62382
+ }
62383
+ try {
62384
+ const response = responseKind === "command" ? jsonValueSchema.parse(threadCommandExecuteResultSchema.parse(result.value)) : { turn: projection.projector.pendingTurn() };
62385
+ await this.#writer.json(rpcEnvelope(request, { result: response }));
62386
+ } finally {
62387
+ gate.resolve();
62388
+ }
62389
+ }
61543
62390
  async #selectThreadModel(request) {
61544
62391
  const params = threadModelSelectParamsSchema.safeParse(request.params);
61545
62392
  if (!params.success) {
@@ -62117,10 +62964,10 @@ var AppServerHost = class {
62117
62964
  ...typeof params.serviceTier === "string" ? { serviceTier: params.serviceTier } : {}
62118
62965
  });
62119
62966
  try {
62120
- if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord29(params.initialTurnsPage)) {
62967
+ if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord31(params.initialTurnsPage)) {
62121
62968
  throw new ExternalHistoryRequestError("initialTurnsPage must be an object");
62122
62969
  }
62123
- const initialPageParams = isRecord29(params.initialTurnsPage) ? params.initialTurnsPage : null;
62970
+ const initialPageParams = isRecord31(params.initialTurnsPage) ? params.initialTurnsPage : null;
62124
62971
  const initialTurnsPage = initialPageParams ? listExternalTurns(turns, initialPageParams) : null;
62125
62972
  const paginated = thread.record.historyMode === "paginated";
62126
62973
  const turnsBackwardsCursor = paginated ? listExternalTurns(turns, { limit: 1, itemsView: "notLoaded" }).backwardsCursor : null;
@@ -62180,6 +63027,36 @@ var AppServerHost = class {
62180
63027
  await this.#writer.json(rpcError(request, -32602, errorMessage3(error54)));
62181
63028
  return;
62182
63029
  }
63030
+ if (thread.session.commands) {
63031
+ const catalog = await thread.session.commands.list();
63032
+ if (!catalog.ok) {
63033
+ await this.#writer.json(rpcError(request, -32073, catalog.error.message));
63034
+ return;
63035
+ }
63036
+ const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
63037
+ if (text === command.invocation) return true;
63038
+ return command.argumentMode === "text" && text.startsWith(`${command.invocation} `);
63039
+ });
63040
+ if (matched) {
63041
+ const argumentText = text.slice(matched.invocation.length).trimStart();
63042
+ try {
63043
+ await this.#startExternalCommand(
63044
+ request,
63045
+ thread,
63046
+ matched.id,
63047
+ argumentText.length > 0 ? { text: argumentText } : void 0,
63048
+ void 0,
63049
+ "turn"
63050
+ );
63051
+ } catch (error54) {
63052
+ this.#diagnose(error54);
63053
+ await this.#writer.json(
63054
+ rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error54)}`)
63055
+ );
63056
+ }
63057
+ return;
63058
+ }
63059
+ }
62183
63060
  const turnId = hostTurnIdSchema.parse(randomUUID9());
62184
63061
  const startedAtMs = Date.now();
62185
63062
  const projection = {
@@ -62301,7 +63178,8 @@ var AppServerHost = class {
62301
63178
  await this.#resolveDesktopApproval(event.interactionId);
62302
63179
  await this.#resolveDesktopQuestion(event.interactionId);
62303
63180
  }
62304
- if (event.type === "turn.completed") {
63181
+ const ephemeralTurn = event.type === "turn.completed" && thread.ephemeralTurnIds.has(event.turnId);
63182
+ if (event.type === "turn.completed" && !ephemeralTurn) {
62305
63183
  const persistenceError = await this.#persistTerminalIdentity(thread, event);
62306
63184
  if (persistenceError) {
62307
63185
  event = {
@@ -62325,10 +63203,14 @@ var AppServerHost = class {
62325
63203
  if (event.type === "turn.completed") {
62326
63204
  if (!result.completedTurn) throw new Error("Turn projector returned no completed Turn");
62327
63205
  const completedAt = Math.floor(Date.now() / 1e3);
62328
- thread.turns.push(result.completedTurn);
63206
+ if (ephemeralTurn) {
63207
+ thread.ephemeralTurnIds.delete(event.turnId);
63208
+ } else {
63209
+ thread.turns.push(result.completedTurn);
63210
+ thread.thread.updatedAt = completedAt;
63211
+ thread.thread.recencyAt = completedAt;
63212
+ }
62329
63213
  thread.historyHydrated = false;
62330
- thread.thread.updatedAt = completedAt;
62331
- thread.thread.recencyAt = completedAt;
62332
63214
  thread.running = false;
62333
63215
  thread.activeTurnId = null;
62334
63216
  thread.projectedTurns.delete(event.turnId);
@@ -62372,7 +63254,7 @@ var AppServerHost = class {
62372
63254
  }
62373
63255
  }
62374
63256
  async #handleDesktopApprovalResponse(value) {
62375
- if (!isRecord29(value) || !isHostApprovalRequestId(value.id)) return false;
63257
+ if (!isRecord31(value) || !isHostApprovalRequestId(value.id)) return false;
62376
63258
  const pending = this.#pendingDesktopApprovals.get(value.id);
62377
63259
  if (!pending) return true;
62378
63260
  this.#pendingDesktopApprovals.delete(value.id);
@@ -62494,7 +63376,7 @@ var AppServerHost = class {
62494
63376
  }
62495
63377
  }
62496
63378
  async #handleDesktopQuestionResponse(value) {
62497
- if (!isRecord29(value) || !isHostQuestionRequestId(value.id)) return false;
63379
+ if (!isRecord31(value) || !isHostQuestionRequestId(value.id)) return false;
62498
63380
  const pending = this.#pendingDesktopQuestions.get(value.id);
62499
63381
  if (!pending) return true;
62500
63382
  this.#pendingDesktopQuestions.delete(value.id);