open-tag 0.0.3 → 0.0.5

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.
@@ -5522,7 +5522,7 @@ function date(params) {
5522
5522
  return /* @__PURE__ */ _coercedDate(ZodDate, params);
5523
5523
  }
5524
5524
  //#endregion
5525
- //#region ../../packages/shared/dist/task-DaUY_qJd.mjs
5525
+ //#region ../../packages/shared/dist/task-AnMGJdep.mjs
5526
5526
  const RUNTIME_INSTRUCTIONS_MAX_BYTES = 24576;
5527
5527
  const RUNTIME_DEFAULT_MAX_DURATION_MS = 18e5;
5528
5528
  const RUNTIME_MAX_DURATION_MS = 864e5;
@@ -5901,7 +5901,35 @@ const PROVIDER_CLI_VALIDATION_RETRY_REASONS = [
5901
5901
  ];
5902
5902
  _enum(PROVIDER_CLI_VALIDATION_RETRY_REASONS);
5903
5903
  const ProviderCliValidationResultReasonSchema = _enum([...INTEGRATION_CREDENTIAL_EXECUTION_REASONS, ...PROVIDER_CLI_VALIDATION_RETRY_REASONS]);
5904
+ /** Allowlisted artifact failure reasons that may leave the machine. */
5905
+ const PROVIDER_CLI_ARTIFACT_PUBLIC_REASONS = [
5906
+ "unsupported_platform",
5907
+ "global_bin_unavailable",
5908
+ "integrity_failed",
5909
+ "version_incompatible"
5910
+ ];
5911
+ const ProviderCliArtifactPublicReasonSchema = _enum(PROVIDER_CLI_ARTIFACT_PUBLIC_REASONS);
5912
+ const ProviderCliPublicFailureReasonSchema = _enum([...INTEGRATION_CREDENTIAL_EXECUTION_REASONS, ...PROVIDER_CLI_ARTIFACT_PUBLIC_REASONS]);
5904
5913
  const PROVIDER_READINESS_V1_HEADER = "x-opentag-provider-readiness";
5914
+ const PROVIDER_CLI_REASON_V2_HEADER = "x-opentag-provider-cli-reason";
5915
+ const PROVIDER_CLI_ALWAYS_MANUAL_ARTIFACT_REASONS = /* @__PURE__ */ new Set([
5916
+ "unsupported_platform",
5917
+ "global_bin_unavailable",
5918
+ "integrity_failed"
5919
+ ]);
5920
+ /** Map a local diagnostic code onto the public artifact allowlist. Unknown codes stay unpublished. */
5921
+ function publicProviderCliArtifactReason(code) {
5922
+ if (code === "unsupported_platform" || code === "global_bin_unavailable" || code === "integrity_failed" || code === "version_incompatible") return code;
5923
+ }
5924
+ /**
5925
+ * Manual failures need a user or release change. `version_incompatible` is manual only after a
5926
+ * final ensure: an inspection may still be repaired by installing a supported managed artifact.
5927
+ */
5928
+ function providerCliArtifactFailureIsManual(input) {
5929
+ if (!input.reason) return false;
5930
+ if (PROVIDER_CLI_ALWAYS_MANUAL_ARTIFACT_REASONS.has(input.reason)) return true;
5931
+ return input.reason === "version_incompatible" && input.stage === "ensure";
5932
+ }
5905
5933
  const ComputerConnectCodeModeSchema = _enum(["create", "repair"]);
5906
5934
  /**
5907
5935
  * Exchange identifies the local installation, not an existing Computer. The Server decides create vs
@@ -6039,7 +6067,8 @@ const ComputerProviderReadinessCollectionSchema = array(object({
6039
6067
  const ComputerImCliReadinessCollectionSchema = array(object({
6040
6068
  provider: ImCliProviderSchema,
6041
6069
  status: ImCliReadinessStatusSchema,
6042
- observedAt: string().datetime().nullable()
6070
+ observedAt: string().datetime().nullable(),
6071
+ reason: ProviderCliArtifactPublicReasonSchema.optional()
6043
6072
  }).strict()).max(IM_CLI_PROVIDERS.length).superRefine((observations, context) => {
6044
6073
  const seen = /* @__PURE__ */ new Set();
6045
6074
  for (const [index, observation] of observations.entries()) {
@@ -6259,7 +6288,7 @@ const ProviderCliHandoffProgressSchema = object({
6259
6288
  "checking_credentials",
6260
6289
  "needs_attention"
6261
6290
  ]),
6262
- reason: IntegrationCredentialExecutionReasonSchema.optional()
6291
+ reason: ProviderCliPublicFailureReasonSchema.optional()
6263
6292
  }).strict();
6264
6293
  /**
6265
6294
  * The machine-readable identity a cross-Provider messaging start fails with: unbind this exact current binding,
@@ -6406,6 +6435,7 @@ const ImBindingDiagnosticsSchema = object({
6406
6435
  "ready",
6407
6436
  "unavailable"
6408
6437
  ]),
6438
+ providerCliReason: ProviderCliArtifactPublicReasonSchema.optional(),
6409
6439
  credentialExecutionReadiness: IntegrationCredentialExecutionStatusSchema,
6410
6440
  credentialExecutionReason: IntegrationCredentialExecutionReasonSchema.optional(),
6411
6441
  credentialGeneration: number().int().min(0),
@@ -7003,6 +7033,7 @@ const MeResponseSchema = object({
7003
7033
  user: UserProfileSchema,
7004
7034
  setupCompletedAt: string().datetime().nullable()
7005
7035
  }).strict();
7036
+ object({ authenticated: boolean() }).strict();
7006
7037
  /** Not `.trim()`: leading and trailing spaces are part of a password, and silently removing them changes the secret. */
7007
7038
  const PasswordSchema = string().min(12).max(128);
7008
7039
  const EmailAddressSchema = string().trim().toLowerCase().email().max(320);
@@ -7094,6 +7125,7 @@ const ErrorCodeSchema = _enum([
7094
7125
  "RUNTIME_REGISTER_TIMEOUT",
7095
7126
  "SESSION_CURSOR_INVALID",
7096
7127
  "SESSION_PROOF_INVALID",
7128
+ "TASK_NOT_QUEUED",
7097
7129
  "INTERNAL_ERROR",
7098
7130
  "RATE_LIMITED",
7099
7131
  "RESOURCE_NOT_FOUND",
@@ -7173,6 +7205,7 @@ const HTTP_PATHS = {
7173
7205
  authConnectExchange: `${API_V1_PREFIX}/auth/connect/exchange`,
7174
7206
  computerConnectExchange: `${API_V1_PREFIX}/computer/connect/exchange`,
7175
7207
  authBrowserLogout: `${API_V1_PREFIX}/auth/browser/logout`,
7208
+ authBrowserSessionStatus: `${API_V1_PREFIX}/auth/browser/session-status`,
7176
7209
  authDevCallback: `${API_V1_PREFIX}/auth/dev/callback`,
7177
7210
  authEmailSignIn: `${API_V1_PREFIX}/auth/email/sign-in`,
7178
7211
  authEmailSignUp: `${API_V1_PREFIX}/auth/email/sign-up`,
@@ -7457,7 +7490,7 @@ const RUNTIME_CLIENT_CAPABILITY_OFFERS = {
7457
7490
  },
7458
7491
  [RUNTIME_CAPABILITY.providerCliReconcile]: {
7459
7492
  min: 1,
7460
- max: 1
7493
+ max: 2
7461
7494
  },
7462
7495
  [RUNTIME_CAPABILITY.sessionCollaboration]: {
7463
7496
  min: 2,
@@ -8343,6 +8376,7 @@ const TaskStatusSchema = _enum([
8343
8376
  "running",
8344
8377
  "completed",
8345
8378
  "failed",
8379
+ "cancelled",
8346
8380
  "expired",
8347
8381
  "ended",
8348
8382
  "idle"
@@ -8382,6 +8416,7 @@ object({
8382
8416
  nextCursor: string().min(1).nullable()
8383
8417
  }).strict();
8384
8418
  object({ task: TaskSummarySchema }).strict();
8419
+ object({ task: TaskSummarySchema }).strict();
8385
8420
  const TaskTurnSchema = object({
8386
8421
  deliveryId: string().uuid(),
8387
8422
  attention: ImAttentionSchema,
@@ -9307,8 +9342,15 @@ const ProviderCliArtifactStatusFrameSchema = object({
9307
9342
  "checking",
9308
9343
  "ready",
9309
9344
  "unavailable"
9310
- ])
9311
- }).strict();
9345
+ ]),
9346
+ reason: ProviderCliArtifactPublicReasonSchema.optional()
9347
+ }).strict().superRefine((frame, context) => {
9348
+ if (frame.status !== "unavailable" && frame.reason !== void 0) context.addIssue({
9349
+ code: "custom",
9350
+ path: ["reason"],
9351
+ message: "An artifact reason is only valid on unavailable"
9352
+ });
9353
+ });
9312
9354
  const IntegrationCliValidationGrantMaterialSchema = discriminatedUnion("provider", [object({
9313
9355
  provider: literal("feishu"),
9314
9356
  appId: runtimeByteString(512, "Feishu App ID exceeds the 512-byte limit", 1),
@@ -19611,7 +19653,8 @@ var OpenTagApi = class {
19611
19653
  listAccountComputers(accessToken, options) {
19612
19654
  return this.#request(HTTP_PATHS.accountComputers, ListAccountComputersResponseSchema, { headers: {
19613
19655
  authorization: `Bearer ${accessToken}`,
19614
- [PROVIDER_READINESS_V1_HEADER]: "1"
19656
+ [PROVIDER_READINESS_V1_HEADER]: "1",
19657
+ [PROVIDER_CLI_REASON_V2_HEADER]: "2"
19615
19658
  } }, options);
19616
19659
  }
19617
19660
  createAgent(accessToken, input, options) {
@@ -19720,7 +19763,10 @@ var OpenTagApi = class {
19720
19763
  }, options);
19721
19764
  }
19722
19765
  getImBindingDiagnostics(accessToken, imBindingId, options) {
19723
- return this.#request(imBindingDiagnosticsPath(imBindingId), ImBindingDiagnosticsSchema, { headers: { authorization: `Bearer ${accessToken}` } }, options);
19766
+ return this.#request(imBindingDiagnosticsPath(imBindingId), ImBindingDiagnosticsSchema, { headers: {
19767
+ authorization: `Bearer ${accessToken}`,
19768
+ [PROVIDER_CLI_REASON_V2_HEADER]: "2"
19769
+ } }, options);
19724
19770
  }
19725
19771
  disableImBinding(accessToken, imBindingId, options) {
19726
19772
  return this.#requestNoContent(imBindingDisablePath(imBindingId), {
@@ -19887,7 +19933,8 @@ function resolveOpenTagHomeLayout(home = resolveOpenTagHome()) {
19887
19933
  return {
19888
19934
  config,
19889
19935
  contextTreeBin: join(resolvedHome, "context-tree", "bin"),
19890
- contextTreeConfigFile: join(config, "context-tree.json"),
19936
+ contextTreeConfigDir: join(config, "context-tree"),
19937
+ contextTreeConfigFile: join(config, "context-tree", "config.json"),
19891
19938
  contextTreePreparationFile: join(state, "context-tree-preparation.json"),
19892
19939
  daemonState: join(state, "daemon"),
19893
19940
  data,
@@ -20336,6 +20383,16 @@ async function checkServerHealth(serverUrl, fetchImpl = fetch, timeoutMs = SERVE
20336
20383
  clearTimeout(timeout);
20337
20384
  }
20338
20385
  }
20386
+ /** Compose all environment layers before giving Session tools first place on PATH. */
20387
+ function composeRuntimeEnvironment(environment, workspaceEnvironment, pathPrepend) {
20388
+ const composed = {
20389
+ ...environment,
20390
+ ...workspaceEnvironment
20391
+ };
20392
+ const current = composed.PATH;
20393
+ if (pathPrepend && current !== pathPrepend && !current?.startsWith(`${pathPrepend}${delimiter}`)) composed.PATH = current ? `${pathPrepend}${delimiter}${current}` : pathPrepend;
20394
+ return composed;
20395
+ }
20339
20396
  /**
20340
20397
  * Spawn errnos that mean "the machine could not run the check right now", not
20341
20398
  * "the binary is broken or absent". These map to `temporarily_unavailable` and
@@ -21431,14 +21488,11 @@ var ClaudeCodeAgentRuntimeFactory = class {
21431
21488
  const environment = claudeCodeAgentRuntimeEnvironment(options.process?.env);
21432
21489
  const command = options.process?.command ?? "claude";
21433
21490
  const prefix = options.process?.args ?? [];
21434
- this.#createProcess = options.createProcess ?? ((cwd, args, workspaceEnvironment) => new ClaudeCodeProcess({
21491
+ this.#createProcess = options.createProcess ?? ((cwd, args, workspaceEnvironment, pathPrepend) => new ClaudeCodeProcess({
21435
21492
  command,
21436
21493
  args: [...prefix, ...args],
21437
21494
  cwd,
21438
- env: {
21439
- ...environment,
21440
- ...workspaceEnvironment
21441
- },
21495
+ env: composeRuntimeEnvironment(environment, workspaceEnvironment, pathPrepend),
21442
21496
  maxLineBytes: options.process?.maxLineBytes,
21443
21497
  maxStderrBytes: options.process?.maxStderrBytes,
21444
21498
  spawnProcess: options.process?.spawnProcess
@@ -21508,7 +21562,7 @@ var ClaudeCodeAgentRuntimeFactory = class {
21508
21562
  return new ClaudeCodeAgentRuntime({
21509
21563
  binding,
21510
21564
  configuration: request.configuration,
21511
- createProcess: (args) => this.#createProcess(request.workspace.cwd, args, request.workspace.environment),
21565
+ createProcess: (args) => this.#createProcess(request.workspace.cwd, args, request.workspace.environment, request.workspace.pathPrepend),
21512
21566
  emptyNativeToolAllowList: isEmptyNativeToolAllowList(request.policy),
21513
21567
  eventSink: request.eventSink,
21514
21568
  hostedTools: request.hostedTools,
@@ -22935,21 +22989,18 @@ var CodexAgentRuntimeFactory = class {
22935
22989
  this.#clientVersion = options.clientVersion;
22936
22990
  const environment = options.process?.env ?? codexAgentRuntimeEnvironment();
22937
22991
  const command = options.process?.command ?? "codex";
22938
- const createDefaultClient = (cwd, workspaceEnvironment, expectedCodexHome = options.process?.expectedCodexHome) => new CodexAppServerProcess({
22992
+ const createDefaultClient = (cwd, workspaceEnvironment, pathPrepend, expectedCodexHome = options.process?.expectedCodexHome) => new CodexAppServerProcess({
22939
22993
  command,
22940
22994
  args: options.process?.args ?? [...CODEX_AGENT_RUNTIME_APP_SERVER_ARGS],
22941
22995
  cwd,
22942
- env: {
22943
- ...environment,
22944
- ...workspaceEnvironment
22945
- },
22996
+ env: composeRuntimeEnvironment(environment, workspaceEnvironment, pathPrepend),
22946
22997
  expectedCodexHome,
22947
22998
  maxLineBytes: options.process?.maxLineBytes,
22948
22999
  requestTimeoutMs: options.process?.requestTimeoutMs,
22949
23000
  spawnProcess: options.process?.spawnProcess
22950
23001
  });
22951
23002
  this.#createClient = options.createClient ?? createDefaultClient;
22952
- const createProbeClient = options.createClient ?? ((cwd, probeEnvironment) => createDefaultClient(cwd, probeEnvironment, probeEnvironment?.CODEX_HOME));
23003
+ const createProbeClient = options.createClient ?? ((cwd, probeEnvironment) => createDefaultClient(cwd, probeEnvironment, void 0, probeEnvironment?.CODEX_HOME));
22953
23004
  this.#probeRunner = options.probeRunner ?? (async (signal) => {
22954
23005
  const local = await probeCodex(command, environment, signal);
22955
23006
  if (!local.credential) return {
@@ -23103,7 +23154,7 @@ var CodexAgentRuntimeFactory = class {
23103
23154
  const expectedThreadId = parsedBinding?.threadId;
23104
23155
  const requestedHostedToolsHash = request.hostedTools ? hostedToolsHash(request.hostedTools.definitions) : void 0;
23105
23156
  if (mode === "resume" && parsedBinding?.hostedToolsHash !== requestedHostedToolsHash) throw new AgentRuntimeError("binding_incompatible", "Codex binding hosted tools cannot change during exact resume");
23106
- const client = this.#createClient(request.workspace.cwd, request.workspace.environment);
23157
+ const client = this.#createClient(request.workspace.cwd, request.workspace.environment, request.workspace.pathPrepend);
23107
23158
  try {
23108
23159
  if (request.hostedTools && typeof client.setDynamicToolHandler !== "function") throw new AgentRuntimeError("configuration_invalid", "Codex App Server transport does not support hosted dynamic tools");
23109
23160
  await client.initialize(this.#clientVersion);
@@ -26555,6 +26606,7 @@ function renderAgentHome(agentHome) {
26555
26606
  "- `worktrees/<unique-task-key>/` — agent-managed checkouts for source access and code work. Concurrent code tasks each use a distinct worktree (and a distinct branch when editing). Keep later operations for the same task in its own worktree. No two code tasks edit one checkout.",
26556
26607
  "- `files/<unique-task-key>/` — non-repository task artifacts, created only when needed.",
26557
26608
  "",
26609
+ "OpenTag provides the bundled `context-tree` command. If it cannot run, report a runtime setup problem; do not install it globally.",
26558
26610
  "Context Tree stays the separately configured shared tree managed by its matching CLI and skills. When running Context Tree project commands from a task subdirectory, pass `--project-path \"<Agent Home>\"` to use the connected Home; do not create or reconnect a tree just because the task cwd changed. Follow the matching skill write protocol. Do not invent an independent Git policy for Tree writes.",
26559
26611
  ""
26560
26612
  ];
@@ -26611,6 +26663,17 @@ var ClientRuntimeProviderStartError = class extends Error {
26611
26663
  this.name = "ClientRuntimeProviderStartError";
26612
26664
  }
26613
26665
  };
26666
+ /**
26667
+ * The manager has no prepared runtime entry for a Session. The fixed code identifies this
26668
+ * local readiness failure in logs without including paths, credentials, or cause content.
26669
+ */
26670
+ var SessionRuntimeNotPreparedError = class extends Error {
26671
+ code = "session_runtime_not_prepared";
26672
+ constructor() {
26673
+ super("The Session Agent Runtime has not been prepared");
26674
+ this.name = "SessionRuntimeNotPreparedError";
26675
+ }
26676
+ };
26614
26677
  var SessionRuntimeManager = class {
26615
26678
  #bindingStore;
26616
26679
  #cliCommand;
@@ -26623,7 +26686,6 @@ var SessionRuntimeManager = class {
26623
26686
  #proofManager;
26624
26687
  #slackConfigWritableRoot;
26625
26688
  #providerCliLaunchPath;
26626
- #inheritedPath;
26627
26689
  #workspace;
26628
26690
  #sessions = /* @__PURE__ */ new Map();
26629
26691
  #prepares = /* @__PURE__ */ new Set();
@@ -26638,11 +26700,10 @@ var SessionRuntimeManager = class {
26638
26700
  if (options.contextTree) this.#contextTree = options.contextTree;
26639
26701
  this.#ensureProviderReady = options.ensureProviderReady;
26640
26702
  this.#providers = options.providers;
26641
- this.#home = options.home ?? "";
26703
+ this.#home = options.home;
26642
26704
  this.#providerEnvironmentPath = options.providerEnvironmentPath;
26643
26705
  this.#slackConfigWritableRoot = options.slackConfigWritableRoot;
26644
26706
  this.#providerCliLaunchPath = options.providerCliLaunchPath;
26645
- this.#inheritedPath = options.inheritedPath ?? process.env.PATH;
26646
26707
  this.#proofManager = options.proofManager ?? {
26647
26708
  cleanup: async () => void 0,
26648
26709
  materialize: async () => {
@@ -26665,7 +26726,7 @@ var SessionRuntimeManager = class {
26665
26726
  }
26666
26727
  requiresSessionPreparation(request) {
26667
26728
  const current = this.#sessions.get(request.sessionId);
26668
- if (!current) return false;
26729
+ if (!current) return true;
26669
26730
  return current.proofId !== request.sessionCliProof?.proofId;
26670
26731
  }
26671
26732
  prepareSession(request, hashes) {
@@ -26731,7 +26792,7 @@ var SessionRuntimeManager = class {
26731
26792
  async ensureRuntime(sessionId, signal) {
26732
26793
  this.#assertOpen();
26733
26794
  const managed = this.#sessions.get(sessionId);
26734
- if (!managed) throw new Error("The Session Agent Runtime has not been prepared");
26795
+ if (!managed) throw new SessionRuntimeNotPreparedError();
26735
26796
  await this.#ensureProviderReady(managed.providerId, signal);
26736
26797
  this.#assertOpen();
26737
26798
  if (managed.runtime && managed.runtime.state.phase !== "closed") return managed.runtime;
@@ -26753,7 +26814,7 @@ var SessionRuntimeManager = class {
26753
26814
  }
26754
26815
  sessionKind(sessionId) {
26755
26816
  const managed = this.#sessions.get(sessionId);
26756
- if (!managed) throw new Error("The Session Agent Runtime has not been prepared");
26817
+ if (!managed) throw new SessionRuntimeNotPreparedError();
26757
26818
  return managed.sessionKind;
26758
26819
  }
26759
26820
  async #startRuntime(managed) {
@@ -26773,6 +26834,7 @@ var SessionRuntimeManager = class {
26773
26834
  await managed.eventSink?.(event);
26774
26835
  };
26775
26836
  const contextTree = await prepareContextTree(this.#contextTree, managed.cwd);
26837
+ const configurationRoots = await prepareConfigurationRoots(resolveOpenTagHomeLayout(this.#home));
26776
26838
  const common = {
26777
26839
  eventSink,
26778
26840
  systemPrompt: renderManagedSystemPrompt(managed.snapshot, {
@@ -26786,15 +26848,17 @@ var SessionRuntimeManager = class {
26786
26848
  }),
26787
26849
  workspace: {
26788
26850
  cwd: managed.cwd,
26851
+ ...visibleProviderCliPath(managed, this.#providerCliLaunchPath),
26789
26852
  environment: {
26790
26853
  ...this.#home ? { OPENTAG_HOME: this.#home } : {},
26791
26854
  ...managed.proofPath ? { OPENTAG_SESSION_PROOF_FILE: managed.proofPath } : {},
26792
- ...managed.sessionKind === "visible" ? {
26793
- OPENTAG_PROVIDER_ENV_FILE: this.#providerEnvironmentPath(managed.binding.sessionId),
26794
- ...visibleProviderCliPath(managed.binding.sessionId, this.#providerCliLaunchPath, this.#inheritedPath)
26795
- } : {}
26855
+ ...managed.sessionKind === "visible" ? { OPENTAG_PROVIDER_ENV_FILE: this.#providerEnvironmentPath(managed.binding.sessionId) } : {}
26796
26856
  },
26797
- writableRoots: [...visibleSlackWritableRoots(managed.sessionKind, managed.cwd, managed.binding.sessionId, this.#slackConfigWritableRoot), ...contextTree.writableRoots]
26857
+ writableRoots: [
26858
+ ...visibleSlackWritableRoots(managed.sessionKind, managed.cwd, managed.binding.sessionId, this.#slackConfigWritableRoot),
26859
+ ...configurationRoots,
26860
+ ...contextTree.writableRoots
26861
+ ]
26798
26862
  },
26799
26863
  policy: provider.policy(managed.snapshot),
26800
26864
  configuration: {
@@ -26867,7 +26931,7 @@ var SessionRuntimeManager = class {
26867
26931
  cwd(sessionId) {
26868
26932
  this.#assertOpen();
26869
26933
  const managed = this.#sessions.get(sessionId);
26870
- if (!managed) throw new Error("The Session Agent Runtime has not been prepared");
26934
+ if (!managed) throw new SessionRuntimeNotPreparedError();
26871
26935
  return managed.cwd;
26872
26936
  }
26873
26937
  observe(sessionId, sink) {
@@ -26915,13 +26979,6 @@ var SessionRuntimeManager = class {
26915
26979
  if (this.#closing) throw new Error("The Session Runtime manager is closing");
26916
26980
  }
26917
26981
  };
26918
- function visibleProviderCliPath(sessionId, resolveLaunchPath, inheritedPath, pathDelimiter = delimiter) {
26919
- const launchPath = resolveLaunchPath?.(sessionId);
26920
- if (!launchPath) return {};
26921
- if (!inheritedPath) return { PATH: launchPath };
26922
- if (inheritedPath === launchPath || inheritedPath.startsWith(`${launchPath}${pathDelimiter}`)) return { PATH: inheritedPath };
26923
- return { PATH: `${launchPath}${pathDelimiter}${inheritedPath}` };
26924
- }
26925
26982
  /**
26926
26983
  * Resolve Context Tree for one Agent Workspace into the two things a Provider Runtime needs.
26927
26984
  *
@@ -26963,6 +27020,21 @@ async function waitForStart(start, signal) {
26963
27020
  signal.removeEventListener("abort", onAbort);
26964
27021
  }
26965
27022
  }
27023
+ function visibleProviderCliPath(managed, resolveLaunchPath) {
27024
+ return managed.sessionKind === "visible" ? { pathPrepend: resolveLaunchPath?.(managed.binding.sessionId) } : {};
27025
+ }
27026
+ async function prepareConfigurationRoots(layout) {
27027
+ try {
27028
+ await mkdir(layout.contextTreeConfigDir, {
27029
+ mode: 448,
27030
+ recursive: true
27031
+ });
27032
+ return [layout.contextTreeConfigDir];
27033
+ } catch (error) {
27034
+ logger$13.warn({ code: error.code }, "Context Tree configuration directory could not be created");
27035
+ return [];
27036
+ }
27037
+ }
26966
27038
  var TurnTraceBuffer = class {
26967
27039
  #id;
26968
27040
  #maxBufferBytes;
@@ -27499,6 +27571,7 @@ function completionForResult(result, abortReason) {
27499
27571
  /** The specific pre-execution rejection code behind a typed Turn failure, for the Computer's log only. */
27500
27572
  function errorFieldsForLog(error) {
27501
27573
  if (error instanceof ImCredentialEnvironmentError || error instanceof ProviderCliTurnPlanError) return { errorCode: error.code };
27574
+ if (error instanceof SessionRuntimeNotPreparedError) return { errorCode: error.code };
27502
27575
  return {};
27503
27576
  }
27504
27577
  function completionForError(error, abortReason) {
@@ -27527,6 +27600,11 @@ function completionForError(error, abortReason) {
27527
27600
  executionEffects: "not_started",
27528
27601
  errorReason: "provider_start_failed"
27529
27602
  };
27603
+ if (error instanceof SessionRuntimeNotPreparedError) return {
27604
+ outcome: "failed",
27605
+ executionEffects: "not_started",
27606
+ errorReason: "provider_start_failed"
27607
+ };
27530
27608
  return {
27531
27609
  outcome: "unknown",
27532
27610
  executionEffects: "may_have_occurred",
@@ -28737,6 +28815,8 @@ var ContextTreeManager = class {
28737
28815
  #cooldown = /* @__PURE__ */ new Map();
28738
28816
  #inFlight = /* @__PURE__ */ new Map();
28739
28817
  #observedTarget = /* @__PURE__ */ new Map();
28818
+ #shimPreparation;
28819
+ #shimRetryAt = 0;
28740
28820
  #pending = Promise.resolve();
28741
28821
  constructor(options) {
28742
28822
  this.#home = resolve(options.home);
@@ -28762,8 +28842,15 @@ var ContextTreeManager = class {
28762
28842
  * connection from writing into a workspace still mid-migration.
28763
28843
  */
28764
28844
  async ensureAgent(cwd) {
28845
+ return this.#withinSessionStartBudget(this.#prepareAgent(cwd));
28846
+ }
28847
+ async #prepareAgent(cwd) {
28848
+ const executableFailure = !this.#package ? "PACKAGE_MISSING" : await this.#prepareShim() ? void 0 : "SHIM_UNAVAILABLE";
28765
28849
  const config = await this.readConfig();
28766
- if (!config) return { status: "unconfigured" };
28850
+ if (!config) return executableFailure ? {
28851
+ status: "unavailable",
28852
+ reason: executableFailure
28853
+ } : { status: "unconfigured" };
28767
28854
  const target = formatContextTreeTarget(config.target);
28768
28855
  if (this.#observedTarget.get(cwd) !== target) {
28769
28856
  this.#observedTarget.set(cwd, target);
@@ -28775,7 +28862,7 @@ var ContextTreeManager = class {
28775
28862
  const cooling = this.#cooldown.get(cwd);
28776
28863
  if (cooling?.target === target && cooling.until > Date.now()) return cooling.status;
28777
28864
  if (cooling) this.#cooldown.delete(cwd);
28778
- return this.#withinSessionStartBudget(this.#joinPreparation(cwd, config, target));
28865
+ return this.#joinPreparation(cwd, config, target, executableFailure);
28779
28866
  }
28780
28867
  async readConfig() {
28781
28868
  try {
@@ -28788,10 +28875,6 @@ var ContextTreeManager = class {
28788
28875
  async #ensureAgentOnce(cwd, config) {
28789
28876
  if (!this.#package) return this.#unavailable("PACKAGE_MISSING", config);
28790
28877
  if (!this.#codexHomeIsDefaultNamed) return this.#unavailable("CODEX_HOME_UNSUPPORTED", config);
28791
- if (!await this.#writeShim().catch((error) => {
28792
- this.#logger.warn({ err: describe(error) }, "Context Tree shim could not be created");
28793
- return false;
28794
- })) return this.#unavailable("SHIM_UNAVAILABLE", config);
28795
28878
  try {
28796
28879
  const treePath = (await this.#run(connectArguments(config.target, cwd), cwd, config.target.kind === "github")).tree?.path;
28797
28880
  if (typeof treePath !== "string" || treePath.length === 0) return this.#unavailable("CONNECT_FAILED", config);
@@ -28847,6 +28930,19 @@ var ContextTreeManager = class {
28847
28930
  * The shim pins the same Node.js runtime OpenTag uses, so a Session cannot resolve a different
28848
28931
  * one from the user's shell configuration.
28849
28932
  */
28933
+ #prepareShim() {
28934
+ if (this.#shimPreparation && Date.now() < this.#shimRetryAt) return this.#shimPreparation;
28935
+ if (this.#shimPreparation && this.#shimRetryAt === 0) return this.#shimPreparation;
28936
+ this.#shimRetryAt = 0;
28937
+ this.#shimPreparation = this.#writeShim().catch((error) => {
28938
+ this.#logger.warn({ err: describe(error) }, "Context Tree shim could not be created");
28939
+ return false;
28940
+ }).then((success) => {
28941
+ if (!success) this.#shimRetryAt = Date.now() + this.#failureCooldownMs;
28942
+ return success;
28943
+ });
28944
+ return this.#shimPreparation;
28945
+ }
28850
28946
  async #writeShim() {
28851
28947
  if (!this.#package) return false;
28852
28948
  if (this.#platform === "win32") {
@@ -28869,10 +28965,10 @@ var ContextTreeManager = class {
28869
28965
  reason
28870
28966
  };
28871
28967
  }
28872
- #joinPreparation(cwd, config, target) {
28968
+ #joinPreparation(cwd, config, target, executableFailure) {
28873
28969
  const current = this.#inFlight.get(cwd);
28874
28970
  if (current?.target === target) return current.promise;
28875
- const prepared = this.#serialize(() => this.#ensureAgentOnce(cwd, config)).catch((error) => {
28971
+ const prepared = this.#serialize(async () => executableFailure ? this.#unavailable(executableFailure, config) : this.#ensureAgentOnce(cwd, config)).catch((error) => {
28876
28972
  this.#logger.error({ err: describe(error) }, "Context Tree preparation raised an unexpected failure");
28877
28973
  return {
28878
28974
  status: "unavailable",
@@ -31313,7 +31409,6 @@ function isStorageOrPermissionError(error) {
31313
31409
  const code = error?.code;
31314
31410
  return code === "EACCES" || code === "EPERM" || code === "EROFS";
31315
31411
  }
31316
- const UNREPAIRABLE = /* @__PURE__ */ new Set(["unsupported_platform", "global_bin_unavailable"]);
31317
31412
  const GRANT_REPLAY_RETENTION_MS = 6e4;
31318
31413
  const logger$3 = createLogger("runtime-provider-cli-reconciler");
31319
31414
  /**
@@ -31360,10 +31455,11 @@ var ProviderCliReconciler = class {
31360
31455
  this.#closePromise ??= this.#performClose();
31361
31456
  return this.#closePromise;
31362
31457
  }
31363
- /** Re-inspect each published CLI so heartbeat freshness reflects current local state. */
31458
+ /** Re-inspect published CLIs and active requirement Providers without mutating repair state. */
31364
31459
  async refreshPublishedImCliReadiness() {
31365
31460
  if (this.#closed || this.#signal?.aborted) return;
31366
- await Promise.all([...this.#imCliPublished.keys()].map((provider) => this.#refreshImCli(provider)));
31461
+ const providers = /* @__PURE__ */ new Set([...this.#imCliPublished.keys(), ...[...this.#current.values()].map((requirement) => requirement.provider)]);
31462
+ await Promise.all([...providers].map((provider) => this.#refreshPassive(provider)));
31367
31463
  }
31368
31464
  async #performClose() {
31369
31465
  this.#closed = true;
@@ -31385,12 +31481,11 @@ var ProviderCliReconciler = class {
31385
31481
  * Return the exact selection already accepted by daemon readiness.
31386
31482
  *
31387
31483
  * An already-accepted selection that still matches the live CLI is admitted
31388
- * immediately. A never-accepted, already-healthy live CLI joins the in-flight
31389
- * provider reconcile and is admitted only when path, fingerprint, version, and
31390
- * generation stay identical across the wait. A provider that was accepted once
31391
- * and later failed or rotated is not treated as a fresh cold start. Caller
31392
- * cancellation interrupts inspect, reconcile wait, and publication wait without
31393
- * cancelling shared work or another waiter.
31484
+ * immediately. A never-accepted, already-healthy live CLI joins in-flight owner
31485
+ * work when present, otherwise confirms read-only if identity stays stable. A
31486
+ * provider that was accepted once and later failed or rotated is not treated as
31487
+ * a fresh cold start and does not start Run-triggered ensure. Caller cancellation
31488
+ * interrupts inspect and shared-work wait without cancelling other waiters.
31394
31489
  */
31395
31490
  async readySelectionForRun(provider, signal) {
31396
31491
  try {
@@ -31409,14 +31504,26 @@ var ProviderCliReconciler = class {
31409
31504
  if (this.#closed) return void 0;
31410
31505
  const accepted = this.#readySelection.get(provider);
31411
31506
  if (accepted && live && selectionsMatch(accepted, live)) return { ...live };
31412
- const initialConfirmation = accepted === void 0 && live !== void 0 && !this.#acceptedOnce.has(provider);
31413
- await this.#awaitReadiness(this.#publishCurrentProvider(provider, "checking"), signal);
31414
- const status = await this.#awaitReadiness(this.#reconcileProvider(provider), signal);
31507
+ if (!(accepted === void 0 && live !== void 0 && !this.#acceptedOnce.has(provider)) || !live) return void 0;
31508
+ const existing = this.#providerRepairJob(provider);
31509
+ if (existing) {
31510
+ const outcome = await this.#awaitReadiness(existing, signal);
31511
+ this.#throwIfReadinessAborted(signal);
31512
+ if (this.#closed || outcome.status !== "ready") return void 0;
31513
+ return this.#admitUnchangedInitialSelection(provider, live, signal);
31514
+ }
31515
+ return this.#confirmInitialSelection(provider, live, signal);
31516
+ }
31517
+ async #confirmInitialSelection(provider, live, signal) {
31518
+ const liveAfter = await this.#awaitReadiness(this.#inspectLiveSelection(provider), signal);
31415
31519
  this.#throwIfReadinessAborted(signal);
31416
31520
  if (this.#closed) return void 0;
31417
- await this.#awaitReadiness(this.#publishCurrentProvider(provider, status), signal);
31418
- if (!initialConfirmation || !live) return void 0;
31419
- return this.#admitUnchangedInitialSelection(provider, live, signal);
31521
+ if (!liveAfter || !selectionsMatch(live, liveAfter)) return void 0;
31522
+ const accepted = this.#readySelection.get(provider);
31523
+ if (this.#acceptedOnce.has(provider)) return accepted && selectionsMatch(accepted, liveAfter) ? { ...liveAfter } : void 0;
31524
+ this.#readySelection.set(provider, liveAfter);
31525
+ this.#acceptedOnce.add(provider);
31526
+ return { ...liveAfter };
31420
31527
  }
31421
31528
  async #admitUnchangedInitialSelection(provider, live, signal) {
31422
31529
  const acceptedAfter = this.#readySelection.get(provider);
@@ -31503,22 +31610,77 @@ var ProviderCliReconciler = class {
31503
31610
  });
31504
31611
  }
31505
31612
  async #prewarmProvider(provider, mode) {
31506
- if (mode === "inspect") return this.#refreshImCli(provider);
31613
+ if (mode === "inspect") {
31614
+ this.#publishImCli(provider, "checking");
31615
+ const status = (await this.#inspectProvider(provider))?.readiness ?? "unavailable";
31616
+ this.#publishImCli(provider, status);
31617
+ return status;
31618
+ }
31507
31619
  this.#publishImCli(provider, "checking");
31508
- const status = await this.#reconcileProvider(provider, "auto");
31509
- this.#publishImCli(provider, status);
31510
- return status;
31620
+ const outcome = await this.#reconcileProvider(provider, "auto");
31621
+ this.#publishImCli(provider, outcome.status);
31622
+ return outcome.status;
31623
+ }
31624
+ async #refreshPassive(provider) {
31625
+ const published = this.#imCliPublished.has(provider);
31626
+ const targets = [...this.#current.values()].filter((requirement) => requirement.provider === provider).map((requirement) => ({
31627
+ integrationId: requirement.integrationId,
31628
+ lastStatus: requirement.lastStatus,
31629
+ requestId: requirement.requestId
31630
+ }));
31631
+ const repairAtStart = this.#providerRepairJob(provider);
31632
+ const selectionAtStart = this.#readySelection.get(provider);
31633
+ const inspection = await this.#inspectProvider(provider);
31634
+ if (this.#closed || this.#signal?.aborted) return;
31635
+ const readiness = inspection?.readiness ?? "unavailable";
31636
+ if (published && this.#imCliPublished.has(provider)) this.#publishImCli(provider, readiness);
31637
+ if (this.#passiveOverlappedRepair(provider, targets, repairAtStart, selectionAtStart)) return;
31638
+ await this.#publishPassiveInspection(provider, inspection, targets, repairAtStart, selectionAtStart);
31639
+ }
31640
+ async #publishPassiveInspection(provider, inspection, targets, repairAtStart, selectionAtStart) {
31641
+ const liveTargets = targets.flatMap((target) => {
31642
+ const current = this.#current.get(target.integrationId);
31643
+ return current?.requestId === target.requestId ? [current] : [];
31644
+ });
31645
+ if (liveTargets.length === 0) return;
31646
+ if (inspection?.readiness === "ready") {
31647
+ const ready = await readySelectionFromInspect(this.#manager.layout, provider, inspection);
31648
+ if (this.#closed || this.#signal?.aborted) return;
31649
+ if (this.#passiveOverlappedRepair(provider, targets, repairAtStart, selectionAtStart)) return;
31650
+ const stillLive = liveTargets.filter((target) => this.#current.get(target.integrationId)?.requestId === target.requestId);
31651
+ if (ready) {
31652
+ this.#readySelection.set(provider, ready);
31653
+ this.#acceptedOnce.add(provider);
31654
+ } else this.#readySelection.delete(provider);
31655
+ await Promise.all(stillLive.map((requirement) => this.#publishArtifact(requirement, ready ? "ready" : "unavailable")));
31656
+ return;
31657
+ }
31658
+ const code = inspection?.diagnostic?.code;
31659
+ const publicReason = publicProviderCliArtifactReason(code);
31660
+ const inspectReason = providerCliArtifactFailureIsManual({
31661
+ reason: code,
31662
+ stage: "inspect"
31663
+ }) ? publicReason : void 0;
31664
+ await Promise.all(liveTargets.map((requirement) => {
31665
+ if (this.#current.get(requirement.integrationId)?.requestId !== requirement.requestId) return Promise.resolve();
31666
+ return this.#publishArtifact(requirement, "unavailable", requirement.lastStatus === "unavailable" ? requirement.lastReason ?? inspectReason : inspectReason);
31667
+ }));
31511
31668
  }
31512
- async #refreshImCli(provider) {
31513
- this.#publishImCli(provider, "checking");
31514
- const status = await this.#inspectImCli(provider);
31515
- this.#publishImCli(provider, status);
31516
- return status;
31669
+ #providerRepairJob(provider) {
31670
+ return this.#providerJobs.get(`${provider}:managed-only`) ?? this.#providerJobs.get(`${provider}:auto`);
31671
+ }
31672
+ #passiveOverlappedRepair(provider, targets, repairAtStart, selectionAtStart) {
31673
+ if (repairAtStart || this.#providerRepairJob(provider)) return true;
31674
+ if (this.#readySelection.get(provider) !== selectionAtStart) return true;
31675
+ return targets.some((target) => {
31676
+ const current = this.#current.get(target.integrationId);
31677
+ return current?.requestId === target.requestId && current.lastStatus !== target.lastStatus;
31678
+ });
31517
31679
  }
31518
- #inspectImCli(provider) {
31680
+ #inspectProvider(provider) {
31519
31681
  const existing = this.#inspectionJobs.get(provider);
31520
31682
  if (existing) return existing;
31521
- const job = this.#manager.inspect(provider).then((inspection) => inspection.readiness).catch(() => "unavailable").finally(() => {
31683
+ const job = this.#manager.inspect(provider).catch(() => void 0).finally(() => {
31522
31684
  if (this.#inspectionJobs.get(provider) === job) this.#inspectionJobs.delete(provider);
31523
31685
  });
31524
31686
  this.#inspectionJobs.set(provider, job);
@@ -31555,8 +31717,10 @@ var ProviderCliReconciler = class {
31555
31717
  };
31556
31718
  this.#current.set(frame.integrationId, tracked);
31557
31719
  await this.#publishArtifact(tracked, "checking");
31558
- const status = await this.#reconcileProvider(frame.provider);
31559
- await this.#publishCurrentProvider(frame.provider, status);
31720
+ const outcome = await this.#reconcileProvider(frame.provider);
31721
+ const current = this.#current.get(frame.integrationId);
31722
+ if (!current || current.requestId !== tracked.requestId) return;
31723
+ await this.#publishArtifact(current, outcome.status, outcome.reason);
31560
31724
  }
31561
31725
  async #reconcileProvider(provider, mode = "managed-only") {
31562
31726
  const key = `${provider}:${mode}`;
@@ -31572,22 +31736,32 @@ var ProviderCliReconciler = class {
31572
31736
  try {
31573
31737
  let inspection = await this.#manager.inspect(provider);
31574
31738
  if (inspection.readiness !== "ready") {
31575
- if (inspection.diagnostic && UNREPAIRABLE.has(inspection.diagnostic.code)) return "unavailable";
31576
- await this.#ensureConverging(provider, mode);
31739
+ if (providerCliArtifactFailureIsManual({
31740
+ reason: inspection.diagnostic?.code,
31741
+ stage: "inspect"
31742
+ })) {
31743
+ this.#readySelection.delete(provider);
31744
+ return unavailableOutcome(inspection.diagnostic?.code, "inspect");
31745
+ }
31746
+ const ensured = await this.#ensureConverging(provider, mode);
31577
31747
  inspection = await this.#manager.inspect(provider);
31748
+ if (inspection.readiness !== "ready") {
31749
+ this.#readySelection.delete(provider);
31750
+ return unavailableOutcome(ensured.diagnostic?.code ?? inspection.diagnostic?.code, "ensure");
31751
+ }
31578
31752
  }
31579
31753
  if (inspection.readiness === "ready") {
31580
31754
  const ready = await readySelectionFromInspect(this.#manager.layout, provider, inspection);
31581
31755
  if (!ready) {
31582
31756
  this.#readySelection.delete(provider);
31583
- return "unavailable";
31757
+ return { status: "unavailable" };
31584
31758
  }
31585
31759
  this.#readySelection.set(provider, ready);
31586
31760
  this.#acceptedOnce.add(provider);
31587
- return "ready";
31761
+ return { status: "ready" };
31588
31762
  }
31589
31763
  this.#readySelection.delete(provider);
31590
- return "unavailable";
31764
+ return unavailableOutcome(inspection.diagnostic?.code, "ensure");
31591
31765
  } catch (error) {
31592
31766
  logger$3.debug({
31593
31767
  code: "provider_reconcile_failed",
@@ -31595,7 +31769,7 @@ var ProviderCliReconciler = class {
31595
31769
  error: String(error)
31596
31770
  }, "Provider CLI reconciliation failed");
31597
31771
  this.#readySelection.delete(provider);
31598
- return "unavailable";
31772
+ return { status: "unavailable" };
31599
31773
  }
31600
31774
  }
31601
31775
  /**
@@ -31635,10 +31809,6 @@ var ProviderCliReconciler = class {
31635
31809
  wait.then(() => finish(), finish);
31636
31810
  });
31637
31811
  }
31638
- async #publishCurrentProvider(provider, status) {
31639
- const current = [...this.#current.values()].filter((requirement) => requirement.provider === provider);
31640
- await Promise.all(current.map((requirement) => this.#publishArtifact(requirement, status)));
31641
- }
31642
31812
  async #handleGrant(frame) {
31643
31813
  this.#pruneGrants();
31644
31814
  if (!this.#acceptsGrant(frame)) return;
@@ -31740,9 +31910,12 @@ var ProviderCliReconciler = class {
31740
31910
  this.#grants.clear();
31741
31911
  this.#current.clear();
31742
31912
  }
31743
- async #publishArtifact(frame, status) {
31913
+ async #publishArtifact(frame, status, reason) {
31744
31914
  const current = this.#current.get(frame.integrationId);
31745
31915
  if (!current || current.requestId !== frame.requestId) return;
31916
+ const publicReason = status === "unavailable" ? reason : void 0;
31917
+ if (current.lastPublishOk !== false && current.lastStatus === status && current.lastReason === publicReason) return;
31918
+ const includeReason = publicReason !== void 0 && this.#connection.capabilityVersion(RUNTIME_CAPABILITY.providerCliReconcile) === 2;
31746
31919
  const payload = {
31747
31920
  type: "provider-cli:artifact:status",
31748
31921
  requestId: frame.requestId,
@@ -31750,9 +31923,17 @@ var ProviderCliReconciler = class {
31750
31923
  agentId: frame.agentId,
31751
31924
  integrationId: frame.integrationId,
31752
31925
  credentialGeneration: frame.credentialGeneration,
31753
- status
31926
+ status,
31927
+ ...includeReason ? { reason: publicReason } : {}
31754
31928
  };
31755
- await this.#connection.send(payload, { priority: "result" });
31929
+ try {
31930
+ await this.#connection.send(payload, { priority: "result" });
31931
+ current.lastStatus = status;
31932
+ current.lastReason = publicReason;
31933
+ current.lastPublishOk = true;
31934
+ } catch {
31935
+ current.lastPublishOk = false;
31936
+ }
31756
31937
  }
31757
31938
  async #publishValidation(frame, result) {
31758
31939
  const payload = {
@@ -31810,6 +31991,18 @@ async function readySelectionFromInspect(layout, provider, inspection) {
31810
31991
  function selectionsMatch(left, right) {
31811
31992
  return left.fingerprint === right.fingerprint && left.generation === right.generation && left.path === right.path && left.version === right.version;
31812
31993
  }
31994
+ function unavailableOutcome(code, stage) {
31995
+ const publicReason = publicProviderCliArtifactReason(code);
31996
+ if (!publicReason) return { status: "unavailable" };
31997
+ if (stage === "inspect" && !providerCliArtifactFailureIsManual({
31998
+ reason: code,
31999
+ stage
32000
+ })) return { status: "unavailable" };
32001
+ return {
32002
+ status: "unavailable",
32003
+ reason: publicReason
32004
+ };
32005
+ }
31813
32006
  /**
31814
32007
  * Wait for shared work without cancelling it. One waiter's abort only stops that
31815
32008
  * waiter; the underlying job keeps running for everyone else.
@@ -36338,7 +36531,6 @@ async function createClientRuntime(connection, options) {
36338
36531
  providers,
36339
36532
  providerEnvironmentPath: (sessionId) => credentialEnvironment.pathForSession(sessionId),
36340
36533
  providerCliLaunchPath: (sessionId) => providerCliTurnPlans.sessionDir(sessionId),
36341
- inheritedPath: sourceEnvironment.PATH,
36342
36534
  slackConfigWritableRoot: (sessionId) => credentialEnvironment.activeSlackConfigDirForSession(sessionId),
36343
36535
  proofManager,
36344
36536
  workspace
@@ -37410,7 +37602,7 @@ function redactSecrets(value) {
37410
37602
  //#endregion
37411
37603
  //#region package.json
37412
37604
  var name = "open-tag";
37413
- var version = "0.0.3";
37605
+ var version = "0.0.5";
37414
37606
  //#endregion
37415
37607
  //#region src/build-info.ts
37416
37608
  const CHANNEL = "prod";
@@ -40734,6 +40926,7 @@ function formatImBindingDiagnostics(value) {
40734
40926
  `slackIdentityClosure\t${value.slackIdentityClosure ? `${value.slackIdentityClosure.status}${value.slackIdentityClosure.verifiedAt ? ` (${value.slackIdentityClosure.verifiedAt})` : ""}` : "-"}`,
40735
40927
  `agentRuntimeReadiness\t${value.agentRuntimeReadiness}`,
40736
40928
  `providerCliReadiness\t${value.providerCliReadiness}`,
40929
+ `providerCliReason\t${value.providerCliReason ?? "-"}`,
40737
40930
  `credentialExecutionReadiness\t${value.credentialExecutionReadiness}`,
40738
40931
  `credentialExecutionReason\t${value.credentialExecutionReason ?? "-"}`,
40739
40932
  `connection\t${value.connection ? `${value.connection.state} (observed ${value.connection.observedAt})` : "not applicable"}`,
@@ -42270,15 +42463,12 @@ function providerCliRepairCommand(provider) {
42270
42463
  const flag = provider === "all" ? "all" : providerCliLabel(provider);
42271
42464
  return `"$HOME/.local/bin/${channelConfig.binName}" provider-cli ensure --provider ${flag}`;
42272
42465
  }
42273
- const PROVIDER_CLI_MANUAL_REASONS = /* @__PURE__ */ new Set([
42274
- "global_bin_unavailable",
42275
- "integrity_failed",
42276
- "unsupported_platform",
42277
- "version_incompatible"
42278
- ]);
42279
42466
  /** False when repeating ensure cannot change the local fact without a user or release change. */
42280
- function providerCliCanAutoRepair(reason) {
42281
- return !PROVIDER_CLI_MANUAL_REASONS.has(reason);
42467
+ function providerCliCanAutoRepair(reason, stage = "ensure") {
42468
+ return !providerCliArtifactFailureIsManual({
42469
+ reason,
42470
+ stage
42471
+ });
42282
42472
  }
42283
42473
  /**
42284
42474
  * Failures that describe another OpenTag process holding the provider lock: transient, safe to
@@ -43390,7 +43580,7 @@ function resolveContextTreeAssets(deps = {}) {
43390
43580
  return deps.contextTreePackage ?? resolveContextTreePackage();
43391
43581
  }
43392
43582
  function contextTreeConfigPath(home) {
43393
- return join(home, "config", "context-tree.json");
43583
+ return join(home, "config", "context-tree", "config.json");
43394
43584
  }
43395
43585
  async function readContextTreeConfig(home) {
43396
43586
  let content;
@@ -45329,7 +45519,7 @@ function renderInspectionLines(inspection, nextAction) {
45329
45519
  function nextActionFor(inspection) {
45330
45520
  if (inspection.state === "ready") return void 0;
45331
45521
  const reason = inspection.diagnostic?.code ?? (inspection.readiness === "install" ? "not_installed" : "unavailable");
45332
- if (!providerCliCanAutoRepair(reason)) return void 0;
45522
+ if (!providerCliCanAutoRepair(reason, "inspect")) return void 0;
45333
45523
  return {
45334
45524
  provider: inspection.provider,
45335
45525
  command: providerCliRepairCommand(inspection.provider),
@@ -45910,4 +46100,4 @@ function createProgram(options = {}) {
45910
46100
  //#endregion
45911
46101
  export { CLI_PACKAGE_NAME as A, resolveOpenTagHomeLayout as B, channelConfig as C, formatAgentList as D, formatAgentCreated as E, executeCommand as F, presentCommand as I, toCommandError as L, CommandError as M, EXIT_CODES as N, CommanderError as O, commandExitCode as P, configureClientLoggerForService as R, resolveChannelEnvironment as S, formatAgentBound as T, runAgentCreate as _, runSessionList as a, selectComputer as b, runLogin as c, runProviderCliEnsure as d, formatComputerList as f, runAgentBind as g, runAgentShow as h, runSessionCreate as i, CLI_VERSION as j, CHANNEL as k, runDoctor as l, runAgentList as m, formatSessionCommandResult as n, runSessionSend as o, buildChildEnvironment as p, formatSessionList as r, runProviderCliInspect as s, createProgram as t, listComputers as u, runAgentDelete as v, formatAgent as w, resolveCommandContext as x, runAgentUpdate as y, resolveOpenTagHome as z };
45912
46102
 
45913
- //# sourceMappingURL=program-CY6rrPEk.mjs.map
46103
+ //# sourceMappingURL=program-CpPCcBDJ.mjs.map