@cleocode/adapters 2026.9.20 → 2026.9.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/cant-context.d.ts +7 -5
  2. package/dist/cant-context.d.ts.map +1 -1
  3. package/dist/index.js +505 -330
  4. package/dist/index.js.map +3 -3
  5. package/dist/providers/claude-code/adapter.d.ts.map +1 -1
  6. package/dist/providers/claude-code/spawn.d.ts +2 -2
  7. package/dist/providers/claude-code/spawn.d.ts.map +1 -1
  8. package/dist/providers/claude-sdk/spawn.d.ts +1 -1
  9. package/dist/providers/codex/adapter.d.ts.map +1 -1
  10. package/dist/providers/codex/spawn.d.ts +1 -1
  11. package/dist/providers/codex/spawn.d.ts.map +1 -1
  12. package/dist/providers/gemini-cli/adapter.d.ts.map +1 -1
  13. package/dist/providers/gemini-cli/spawn.d.ts +1 -1
  14. package/dist/providers/gemini-cli/spawn.d.ts.map +1 -1
  15. package/dist/providers/kimi/adapter.d.ts.map +1 -1
  16. package/dist/providers/kimi/spawn.d.ts.map +1 -1
  17. package/dist/providers/opencode/adapter.d.ts.map +1 -1
  18. package/dist/providers/opencode/spawn.d.ts +3 -2
  19. package/dist/providers/opencode/spawn.d.ts.map +1 -1
  20. package/dist/providers/pi/adapter.d.ts +1 -1
  21. package/dist/providers/pi/adapter.d.ts.map +1 -1
  22. package/dist/providers/pi/spawn.d.ts +3 -3
  23. package/dist/providers/pi/spawn.d.ts.map +1 -1
  24. package/dist/providers/shared/agent-spawn-wrapper.d.ts +5 -0
  25. package/dist/providers/shared/agent-spawn-wrapper.d.ts.map +1 -1
  26. package/dist/providers/shared/cli-spawn.d.ts +28 -0
  27. package/dist/providers/shared/cli-spawn.d.ts.map +1 -0
  28. package/dist/providers/shared/credentials.d.ts +2 -2
  29. package/dist/providers/shared/credentials.d.ts.map +1 -1
  30. package/dist/providers/shared/prompt-file.d.ts +32 -0
  31. package/dist/providers/shared/prompt-file.d.ts.map +1 -0
  32. package/package.json +5 -5
  33. package/src/__tests__/agent-spawn-wrapper-win32.test.ts +42 -0
  34. package/src/__tests__/cant-context.test.ts +89 -37
  35. package/src/__tests__/cli-spawn-win32.test.ts +105 -0
  36. package/src/__tests__/spawn-prompt-file.test.ts +37 -0
  37. package/src/cant-context.ts +11 -15
  38. package/src/providers/claude-code/adapter.ts +6 -11
  39. package/src/providers/claude-code/spawn.ts +11 -25
  40. package/src/providers/claude-sdk/spawn.ts +1 -1
  41. package/src/providers/codex/adapter.ts +6 -11
  42. package/src/providers/codex/spawn.ts +17 -31
  43. package/src/providers/gemini-cli/adapter.ts +6 -11
  44. package/src/providers/gemini-cli/spawn.ts +13 -18
  45. package/src/providers/kimi/adapter.ts +6 -11
  46. package/src/providers/kimi/spawn.ts +3 -11
  47. package/src/providers/opencode/__tests__/spawn-prompt-delivery.test.ts +123 -0
  48. package/src/providers/opencode/adapter.ts +6 -11
  49. package/src/providers/opencode/spawn.ts +23 -25
  50. package/src/providers/pi/adapter.ts +8 -18
  51. package/src/providers/pi/spawn.ts +15 -33
  52. package/src/providers/shared/__tests__/credentials-cleo-home.test.ts +42 -0
  53. package/src/providers/shared/agent-spawn-wrapper.ts +22 -2
  54. package/src/providers/shared/cli-spawn.ts +41 -0
  55. package/src/providers/shared/credentials.ts +6 -5
  56. package/src/providers/shared/prompt-file.ts +44 -0
package/dist/index.js CHANGED
@@ -28,9 +28,9 @@ __export(cant_context_exports, {
28
28
  });
29
29
  import { execFile } from "node:child_process";
30
30
  import { existsSync, readdirSync, readFileSync } from "node:fs";
31
- import { homedir } from "node:os";
32
31
  import { basename, join } from "node:path";
33
32
  import { promisify } from "node:util";
33
+ import { getCleoHome, getCleoPlatformPaths } from "@cleocode/paths";
34
34
  function discoverCantFiles(dir) {
35
35
  try {
36
36
  const entries = readdirSync(dir, { recursive: true, withFileTypes: true });
@@ -47,12 +47,9 @@ function discoverCantFiles(dir) {
47
47
  }
48
48
  }
49
49
  function resolveThreeTierPaths(projectDir) {
50
- const home = homedir();
51
- const xdgData = process.env["XDG_DATA_HOME"] ?? join(home, ".local", "share");
52
- const xdgConfig = process.env["XDG_CONFIG_HOME"] ?? join(home, ".config");
53
50
  return {
54
- global: join(xdgData, "cleo", "cant"),
55
- user: join(xdgConfig, "cleo", "cant"),
51
+ global: join(getCleoHome(), "cant"),
52
+ user: join(getCleoPlatformPaths().config, "cant"),
56
53
  project: join(projectDir, ".cleo", "cant")
57
54
  };
58
55
  }
@@ -139,9 +136,7 @@ function readIdentityFile(projectDir) {
139
136
  } catch {
140
137
  }
141
138
  }
142
- const home = homedir();
143
- const xdgData = process.env["XDG_DATA_HOME"] ?? join(home, ".local", "share");
144
- const globalPath = join(xdgData, "cleo", "CLEOOS-IDENTITY.md");
139
+ const globalPath = join(getCleoHome(), "CLEOOS-IDENTITY.md");
145
140
  if (existsSync(globalPath)) {
146
141
  try {
147
142
  const content = readFileSync(globalPath, "utf-8");
@@ -747,7 +742,17 @@ var init_acceptance_gate_schema = __esm({
747
742
  message: "Absent input requires both null digest and size"
748
743
  });
749
744
  })
750
- )
745
+ ),
746
+ tree: z.object({
747
+ headSha: z.string().regex(/^[0-9a-f]{40}$/),
748
+ clean: z.boolean(),
749
+ cwd: z.string().min(1).refine(
750
+ (v) => !/^(?:\/|[A-Za-z]:[\\/]|\\\\)/.test(v) && !v.split(/[\\/]/).includes(".."),
751
+ "Tree-relative cwd must be relative and stay inside the tree"
752
+ ),
753
+ inputsHash: z.string().regex(/^[a-f0-9]{64}$/),
754
+ baseSha: z.string().regex(/^[0-9a-f]{40}$/).optional()
755
+ }).strict().optional()
751
756
  }).strict().superRefine((binding, context) => {
752
757
  if (new Set(binding.artifacts.map(({ path }) => path)).size !== binding.artifacts.length)
753
758
  context.addIssue({
@@ -777,8 +782,18 @@ var init_acceptance_gate_schema = __esm({
777
782
  errorMessage: z.string().optional(),
778
783
  /** ISO 8601 timestamp. */
779
784
  checkedAt: z.string().datetime(),
780
- checkedBy: z.string().min(1)
785
+ checkedBy: z.string().min(1),
786
+ /** T12621: `executed` in this run, or an authenticated pass reused from the cache. */
787
+ source: z.enum(["executed", "cache"]).optional(),
788
+ /** T12621: creation time of the reused cache entry. */
789
+ cachedAt: z.string().datetime().optional()
781
790
  }).superRefine((result, context) => {
791
+ if (result.source === "cache" !== (result.cachedAt !== void 0))
792
+ context.addIssue({
793
+ code: "custom",
794
+ path: ["cachedAt"],
795
+ message: "A cached result carries its cache time, and only a cached result does"
796
+ });
782
797
  const binding = result.binding;
783
798
  if (binding) {
784
799
  if (binding.identity.actor !== result.checkedBy)
@@ -2778,7 +2793,8 @@ var init_tasks = __esm({
2778
2793
  }
2779
2794
  }
2780
2795
  },
2781
- removeRelates: { type: "array", items: { type: "string" } }
2796
+ removeRelates: { type: "array", items: { type: "string" } },
2797
+ expectedUpdatedAt: { type: "string", minLength: 1 }
2782
2798
  }
2783
2799
  };
2784
2800
  tasksUpdateInputContract = {
@@ -5735,6 +5751,13 @@ var init_operations_registry = __esm({
5735
5751
  required: false,
5736
5752
  description: "Disable automatic parent completion",
5737
5753
  cli: { flag: "no-auto-complete" }
5754
+ },
5755
+ {
5756
+ name: "expectedUpdatedAt",
5757
+ type: "string",
5758
+ required: false,
5759
+ description: "Optimistic-concurrency guard: fail with E_CONFLICT unless the task updatedAt still equals this value",
5760
+ cli: { flag: "expected-updated-at" }
5738
5761
  }
5739
5762
  ],
5740
5763
  inputSchema: tasksUpdateInputContract,
@@ -9513,6 +9536,42 @@ var init_operations_registry = __esm({
9513
9536
  }
9514
9537
  ]
9515
9538
  },
9539
+ {
9540
+ gateway: "mutate",
9541
+ domain: "nexus",
9542
+ operation: "projects.status",
9543
+ description: "nexus.projects.status (mutate) \u2014 probe and record git state of every project location on this device (bounded, parallel; no network unless fetch)",
9544
+ tier: 1,
9545
+ idempotent: true,
9546
+ sessionRequired: false,
9547
+ requiredParams: [],
9548
+ params: [
9549
+ {
9550
+ name: "fetch",
9551
+ type: "boolean",
9552
+ required: false,
9553
+ description: "Run git fetch per location first (network; off by default)"
9554
+ },
9555
+ {
9556
+ name: "concurrency",
9557
+ type: "number",
9558
+ required: false,
9559
+ description: "Locations probed at once (default 8, max 64)"
9560
+ },
9561
+ {
9562
+ name: "timeoutMs",
9563
+ type: "number",
9564
+ required: false,
9565
+ description: "Per-location git budget in ms (default 10000; 30000 with fetch)"
9566
+ },
9567
+ {
9568
+ name: "staleAfterMs",
9569
+ type: "number",
9570
+ required: false,
9571
+ description: "A fetch older than this marks remote state stale (default 24h)"
9572
+ }
9573
+ ]
9574
+ },
9516
9575
  {
9517
9576
  gateway: "mutate",
9518
9577
  domain: "nexus",
@@ -10688,7 +10747,13 @@ var init_operations_registry = __esm({
10688
10747
  },
10689
10748
  { name: "title", type: "string", required: false, description: "Override PR title" },
10690
10749
  { name: "body", type: "string", required: false, description: "Override PR body" },
10691
- { name: "base", type: "string", required: false, description: "PR base branch" }
10750
+ { name: "base", type: "string", required: false, description: "PR base branch" },
10751
+ {
10752
+ name: "taskId",
10753
+ type: "string",
10754
+ required: false,
10755
+ description: "Owning task id (T####) for the PR commit subject"
10756
+ }
10692
10757
  ]
10693
10758
  },
10694
10759
  {
@@ -10721,7 +10786,13 @@ var init_operations_registry = __esm({
10721
10786
  },
10722
10787
  { name: "title", type: "string", required: false, description: "Override PR title" },
10723
10788
  { name: "body", type: "string", required: false, description: "Override PR body" },
10724
- { name: "base", type: "string", required: false, description: "PR base branch" }
10789
+ { name: "base", type: "string", required: false, description: "PR base branch" },
10790
+ {
10791
+ name: "taskId",
10792
+ type: "string",
10793
+ required: false,
10794
+ description: "Owning task id (T####) for the PR commit subject"
10795
+ }
10725
10796
  ]
10726
10797
  },
10727
10798
  {
@@ -10927,7 +10998,7 @@ var init_operations_registry = __esm({
10927
10998
  type: "string",
10928
10999
  required: false,
10929
11000
  enum: DOCS_LIFECYCLE_STATUSES,
10930
- description: `Override the new lifecycle status. Defaults to "draft" on every update. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
11001
+ description: `Override the new lifecycle status. Defaults to "draft" on every update. Alone (no file or content) it changes only the lifecycle status. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
10931
11002
  },
10932
11003
  {
10933
11004
  name: "dryRun",
@@ -13237,7 +13308,7 @@ var init_errors = __esm({
13237
13308
 
13238
13309
  // packages/contracts/src/evidence-atom-schema.ts
13239
13310
  import { z as z10 } from "zod";
13240
- var EVIDENCE_ATOM_KINDS, PARSER_PREFIXES, KIND_BOUNDARY_REGEX, commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, AC_UUID_REGEX, AC_ALIAS_REGEX, SATISFIES_TASK_ID_REGEX, SATISFIES_VERSION_PIN_REGEX, satisfiesAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS, ATOM_EXAMPLES;
13311
+ var EVIDENCE_ATOM_KINDS, PARSER_PREFIXES, KIND_BOUNDARY_REGEX, commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, ciAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, AC_UUID_REGEX, AC_ALIAS_REGEX, SATISFIES_TASK_ID_REGEX, SATISFIES_VERSION_PIN_REGEX, satisfiesAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS, ATOM_EXAMPLES;
13241
13312
  var init_evidence_atom_schema = __esm({
13242
13313
  "packages/contracts/src/evidence-atom-schema.ts"() {
13243
13314
  "use strict";
@@ -13250,6 +13321,7 @@ var init_evidence_atom_schema = __esm({
13250
13321
  "note",
13251
13322
  "decision",
13252
13323
  "pr",
13324
+ "ci",
13253
13325
  "loc-drop",
13254
13326
  "callsite-coverage",
13255
13327
  "satisfies"
@@ -13286,7 +13358,13 @@ var init_evidence_atom_schema = __esm({
13286
13358
  });
13287
13359
  prAtomSchema = z10.object({
13288
13360
  kind: z10.literal("pr"),
13289
- prNumber: z10.number().int().positive("pr atom requires a positive integer PR number")
13361
+ prNumber: z10.number().int().positive("pr atom requires a positive integer PR number"),
13362
+ componentPrNumber: z10.number().int().positive().optional()
13363
+ });
13364
+ ciAtomSchema = z10.object({
13365
+ kind: z10.literal("ci"),
13366
+ prNumber: z10.number().int().positive("ci atom requires a positive integer PR number"),
13367
+ componentPrNumber: z10.number().int().positive().optional()
13290
13368
  });
13291
13369
  locDropAtomSchema = z10.object({
13292
13370
  kind: z10.literal("loc-drop"),
@@ -13325,6 +13403,7 @@ var init_evidence_atom_schema = __esm({
13325
13403
  noteAtomSchema,
13326
13404
  decisionAtomSchema,
13327
13405
  prAtomSchema,
13406
+ ciAtomSchema,
13328
13407
  locDropAtomSchema,
13329
13408
  callsiteCoverageAtomSchema,
13330
13409
  satisfiesAtomSchema
@@ -13339,8 +13418,8 @@ var init_evidence_atom_schema = __esm({
13339
13418
  ["pr", "files"]
13340
13419
  ]
13341
13420
  },
13342
- testsPassed: { oneOf: [["test-run"], ["tool"]] },
13343
- qaPassed: { oneOf: [["tool"]] },
13421
+ testsPassed: { oneOf: [["test-run"], ["tool"], ["ci"]] },
13422
+ qaPassed: { oneOf: [["tool"], ["ci"]] },
13344
13423
  documented: { oneOf: [["files"], ["url"]] },
13345
13424
  securityPassed: { oneOf: [["tool"], ["note"]] },
13346
13425
  cleanupDone: { oneOf: [["note"]] },
@@ -13355,6 +13434,7 @@ var init_evidence_atom_schema = __esm({
13355
13434
  note: "note:<short description>",
13356
13435
  decision: "decision:D-arch-001",
13357
13436
  pr: "pr:357",
13437
+ ci: "ci:357",
13358
13438
  "loc-drop": "loc-drop:<fromLines>:<toLines>",
13359
13439
  "callsite-coverage": "callsite-coverage:<symbolName>:<relativeSourcePath>",
13360
13440
  satisfies: "satisfies:T1234#AC2"
@@ -15163,6 +15243,13 @@ var init_peer = __esm({
15163
15243
  }
15164
15244
  });
15165
15245
 
15246
+ // packages/contracts/src/process-probe.ts
15247
+ var init_process_probe = __esm({
15248
+ "packages/contracts/src/process-probe.ts"() {
15249
+ "use strict";
15250
+ }
15251
+ });
15252
+
15166
15253
  // packages/contracts/src/release/evidence-atoms.ts
15167
15254
  import { z as z16 } from "zod";
15168
15255
  var parsedPrEvidenceAtomSchema, prEvidenceStateModifierSchema, ghPrViewSchema, PR_REQUIRED_WORKFLOWS;
@@ -15249,7 +15336,12 @@ var init_plan = __esm({
15249
15336
  "hotfix"
15250
15337
  ];
15251
15338
  IMPACT = ["major", "minor", "patch"];
15252
- RESOLVED_SOURCE = ["project-context", "language-default", "legacy-alias"];
15339
+ RESOLVED_SOURCE = [
15340
+ "project-context",
15341
+ "package-script",
15342
+ "language-default",
15343
+ "legacy-alias"
15344
+ ];
15253
15345
  ReleaseChannelSchema = z17.enum(RELEASE_CHANNEL);
15254
15346
  ReleaseSchemeSchema = z17.enum(RELEASE_SCHEME);
15255
15347
  ReleaseKindSchema = z17.enum(RELEASE_KIND);
@@ -17165,6 +17257,117 @@ var init_collection_keys = __esm({
17165
17257
  }
17166
17258
  });
17167
17259
 
17260
+ // packages/contracts/src/decide.ts
17261
+ import { z as z24 } from "zod";
17262
+ var DECISION_QUESTION_TYPES, DECISION_OUTCOME_SOURCES, DECISION_REQUEST_LIMITS, decisionQuestionTypeSchema, decisionOutcomeSourceSchema, decisionInstructionsSchema, unitIntervalSchema, decisionStateSchema, noulDecisionQuestionSchema, choiceDecisionQuestionSchema, scoreDecisionQuestionSchema, decisionQuestionSchema, decisionRequestSchema, noulDecisionAnswerSchema, choiceDecisionAnswerSchema, scoreDecisionAnswerSchema, decisionAnswerSchema, decisionOutcomeSchema, decisionProviderConfigSchema;
17263
+ var init_decide = __esm({
17264
+ "packages/contracts/src/decide.ts"() {
17265
+ "use strict";
17266
+ DECISION_QUESTION_TYPES = ["noul", "choice", "score"];
17267
+ DECISION_OUTCOME_SOURCES = ["provider", "cache", "fallback"];
17268
+ DECISION_REQUEST_LIMITS = {
17269
+ /**
17270
+ * Maximum size of `state`, in UTF-16 characters. A string state is measured
17271
+ * directly; a structured (object/array) state is measured on its
17272
+ * `JSON.stringify` serialization, which is what goes over the wire.
17273
+ */
17274
+ maxStateChars: 32e3,
17275
+ /** Minimum number of questions in one request. */
17276
+ minQuestions: 1,
17277
+ /** Maximum number of questions in one request. */
17278
+ maxQuestions: 32,
17279
+ /** Minimum number of options a `choice` question must offer. */
17280
+ minChoiceOptions: 2,
17281
+ /** Minimum number of levels on a `score` question's scale. */
17282
+ minScoreLevels: 2,
17283
+ /** Maximum number of levels on a `score` question's scale. */
17284
+ maxScoreLevels: 10
17285
+ };
17286
+ decisionQuestionTypeSchema = z24.enum(DECISION_QUESTION_TYPES);
17287
+ decisionOutcomeSourceSchema = z24.enum(DECISION_OUTCOME_SOURCES);
17288
+ decisionInstructionsSchema = z24.union([z24.string(), z24.record(z24.string(), z24.json())]);
17289
+ unitIntervalSchema = z24.number().min(0).max(1);
17290
+ decisionStateSchema = z24.union([z24.string(), z24.array(z24.json()), z24.record(z24.string(), z24.json())]).superRefine((state, context) => {
17291
+ const size = typeof state === "string" ? state.length : JSON.stringify(state).length;
17292
+ if (size > DECISION_REQUEST_LIMITS.maxStateChars) {
17293
+ context.addIssue({
17294
+ code: "custom",
17295
+ message: `state is ${size} characters; the limit is ${DECISION_REQUEST_LIMITS.maxStateChars}`
17296
+ });
17297
+ }
17298
+ });
17299
+ noulDecisionQuestionSchema = z24.object({
17300
+ type: z24.literal("noul"),
17301
+ instructions: decisionInstructionsSchema.optional(),
17302
+ criteria: z24.string().min(1)
17303
+ });
17304
+ choiceDecisionQuestionSchema = z24.object({
17305
+ type: z24.literal("choice"),
17306
+ instructions: decisionInstructionsSchema.optional(),
17307
+ criteria: z24.record(z24.string().min(1), z24.string()).refine((options) => Object.keys(options).length >= DECISION_REQUEST_LIMITS.minChoiceOptions, {
17308
+ message: `a choice question needs at least ${DECISION_REQUEST_LIMITS.minChoiceOptions} options`
17309
+ })
17310
+ });
17311
+ scoreDecisionQuestionSchema = z24.object({
17312
+ type: z24.literal("score"),
17313
+ instructions: decisionInstructionsSchema.optional(),
17314
+ criteria: z24.array(z24.string()).min(DECISION_REQUEST_LIMITS.minScoreLevels).max(DECISION_REQUEST_LIMITS.maxScoreLevels)
17315
+ });
17316
+ decisionQuestionSchema = z24.discriminatedUnion("type", [
17317
+ noulDecisionQuestionSchema,
17318
+ choiceDecisionQuestionSchema,
17319
+ scoreDecisionQuestionSchema
17320
+ ]);
17321
+ decisionRequestSchema = z24.object({
17322
+ model: z24.string().min(1).optional(),
17323
+ state: decisionStateSchema,
17324
+ questions: z24.record(z24.string().min(1), decisionQuestionSchema).refine(
17325
+ (questions) => {
17326
+ const count = Object.keys(questions).length;
17327
+ return count >= DECISION_REQUEST_LIMITS.minQuestions && count <= DECISION_REQUEST_LIMITS.maxQuestions;
17328
+ },
17329
+ {
17330
+ message: `a request needs ${DECISION_REQUEST_LIMITS.minQuestions}\u2013${DECISION_REQUEST_LIMITS.maxQuestions} questions`
17331
+ }
17332
+ )
17333
+ });
17334
+ noulDecisionAnswerSchema = z24.object({
17335
+ type: z24.literal("noul"),
17336
+ value: z24.boolean(),
17337
+ probability: unitIntervalSchema,
17338
+ confidence: unitIntervalSchema
17339
+ });
17340
+ choiceDecisionAnswerSchema = z24.object({
17341
+ type: z24.literal("choice"),
17342
+ value: z24.string().min(1),
17343
+ probabilities: z24.record(z24.string().min(1), unitIntervalSchema),
17344
+ confidence: unitIntervalSchema
17345
+ });
17346
+ scoreDecisionAnswerSchema = z24.object({
17347
+ type: z24.literal("score"),
17348
+ value: z24.number().int().nonnegative(),
17349
+ probabilities: z24.array(unitIntervalSchema).min(DECISION_REQUEST_LIMITS.minScoreLevels).max(DECISION_REQUEST_LIMITS.maxScoreLevels),
17350
+ confidence: unitIntervalSchema
17351
+ });
17352
+ decisionAnswerSchema = z24.discriminatedUnion("type", [
17353
+ noulDecisionAnswerSchema,
17354
+ choiceDecisionAnswerSchema,
17355
+ scoreDecisionAnswerSchema
17356
+ ]);
17357
+ decisionOutcomeSchema = z24.object({
17358
+ answers: z24.record(z24.string().min(1), decisionAnswerSchema),
17359
+ source: decisionOutcomeSourceSchema,
17360
+ requestId: z24.string().min(1).optional(),
17361
+ latencyMs: z24.number().nonnegative(),
17362
+ costUsd: z24.number().nonnegative().optional(),
17363
+ inputTokens: z24.number().int().nonnegative().optional()
17364
+ });
17365
+ decisionProviderConfigSchema = z24.object({
17366
+ baseUrl: z24.url()
17367
+ });
17368
+ }
17369
+ });
17370
+
17168
17371
  // packages/contracts/src/task-id.ts
17169
17372
  var init_task_id = __esm({
17170
17373
  "packages/contracts/src/task-id.ts"() {
@@ -17219,11 +17422,13 @@ var init_src = __esm({
17219
17422
  init_entities();
17220
17423
  init_operations();
17221
17424
  init_nexus_scope_map();
17425
+ init_nexus_user_profile();
17222
17426
  init_output_contracts_data();
17223
17427
  init_params();
17224
17428
  init_service();
17225
17429
  init_tasks();
17226
17430
  init_peer();
17431
+ init_process_probe();
17227
17432
  init_evidence_atoms();
17228
17433
  init_plan();
17229
17434
  init_render();
@@ -17243,20 +17448,21 @@ var init_src = __esm({
17243
17448
  init_workgraph();
17244
17449
  init_caamp_markers();
17245
17450
  init_collection_keys();
17451
+ init_decide();
17246
17452
  init_task_id();
17247
17453
  }
17248
17454
  });
17249
17455
 
17250
17456
  // packages/adapters/src/providers/shared/credentials.ts
17251
17457
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
17252
- import { homedir as homedir2 } from "node:os";
17458
+ import { homedir } from "node:os";
17253
17459
  import { join as join2 } from "node:path";
17460
+ import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
17254
17461
  function resolveCredentials(_provider) {
17255
17462
  const envKey = process.env["ANTHROPIC_API_KEY"];
17256
17463
  if (envKey?.trim()) return { apiKey: envKey.trim() };
17257
17464
  try {
17258
- const xdg = process.env["XDG_DATA_HOME"] ?? join2(homedir2(), ".local", "share");
17259
- const keyFile = join2(xdg, "cleo", "anthropic-key");
17465
+ const keyFile = join2(getCleoHome2(), "anthropic-key");
17260
17466
  if (existsSync2(keyFile)) {
17261
17467
  const stored = readFileSync2(keyFile, "utf-8").trim();
17262
17468
  if (stored) return { apiKey: stored };
@@ -17264,7 +17470,7 @@ function resolveCredentials(_provider) {
17264
17470
  } catch {
17265
17471
  }
17266
17472
  try {
17267
- const credPath = join2(homedir2(), ".claude", ".credentials.json");
17473
+ const credPath = join2(homedir(), ".claude", ".credentials.json");
17268
17474
  if (!existsSync2(credPath)) return { apiKey: null };
17269
17475
  const raw = readFileSync2(credPath, "utf-8");
17270
17476
  const cred = parseClaudeCodeCredentials(raw);
@@ -31263,7 +31469,7 @@ function resolveRef(ref, ctx) {
31263
31469
  function convertBaseSchema(schema, ctx) {
31264
31470
  if (schema.not !== void 0) {
31265
31471
  if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) {
31266
- return z24.never();
31472
+ return z25.never();
31267
31473
  }
31268
31474
  throw new Error("not is not supported in Zod (except { not: {} } for never)");
31269
31475
  }
@@ -31285,7 +31491,7 @@ function convertBaseSchema(schema, ctx) {
31285
31491
  return ctx.refs.get(refPath);
31286
31492
  }
31287
31493
  if (ctx.processing.has(refPath)) {
31288
- return z24.lazy(() => {
31494
+ return z25.lazy(() => {
31289
31495
  if (!ctx.refs.has(refPath)) {
31290
31496
  throw new Error(`Circular reference not resolved: ${refPath}`);
31291
31497
  }
@@ -31302,25 +31508,25 @@ function convertBaseSchema(schema, ctx) {
31302
31508
  if (schema.enum !== void 0) {
31303
31509
  const enumValues = schema.enum;
31304
31510
  if (ctx.version === "openapi-3.0" && schema.nullable === true && enumValues.length === 1 && enumValues[0] === null) {
31305
- return z24.null();
31511
+ return z25.null();
31306
31512
  }
31307
31513
  if (enumValues.length === 0) {
31308
- return z24.never();
31514
+ return z25.never();
31309
31515
  }
31310
31516
  if (enumValues.length === 1) {
31311
- return z24.literal(enumValues[0]);
31517
+ return z25.literal(enumValues[0]);
31312
31518
  }
31313
31519
  if (enumValues.every((v) => typeof v === "string")) {
31314
- return z24.enum(enumValues);
31520
+ return z25.enum(enumValues);
31315
31521
  }
31316
- const literalSchemas = enumValues.map((v) => z24.literal(v));
31522
+ const literalSchemas = enumValues.map((v) => z25.literal(v));
31317
31523
  if (literalSchemas.length < 2) {
31318
31524
  return literalSchemas[0];
31319
31525
  }
31320
- return z24.union([literalSchemas[0], literalSchemas[1], ...literalSchemas.slice(2)]);
31526
+ return z25.union([literalSchemas[0], literalSchemas[1], ...literalSchemas.slice(2)]);
31321
31527
  }
31322
31528
  if (schema.const !== void 0) {
31323
- return z24.literal(schema.const);
31529
+ return z25.literal(schema.const);
31324
31530
  }
31325
31531
  const type = schema.type;
31326
31532
  if (Array.isArray(type)) {
@@ -31329,68 +31535,68 @@ function convertBaseSchema(schema, ctx) {
31329
31535
  return convertBaseSchema(typeSchema, ctx);
31330
31536
  });
31331
31537
  if (typeSchemas.length === 0) {
31332
- return z24.never();
31538
+ return z25.never();
31333
31539
  }
31334
31540
  if (typeSchemas.length === 1) {
31335
31541
  return typeSchemas[0];
31336
31542
  }
31337
- return z24.union(typeSchemas);
31543
+ return z25.union(typeSchemas);
31338
31544
  }
31339
31545
  if (!type) {
31340
- return z24.any();
31546
+ return z25.any();
31341
31547
  }
31342
31548
  let zodSchema2;
31343
31549
  switch (type) {
31344
31550
  case "string": {
31345
- let stringSchema = z24.string();
31551
+ let stringSchema = z25.string();
31346
31552
  if (schema.format) {
31347
31553
  const format = schema.format;
31348
31554
  if (format === "email") {
31349
- stringSchema = stringSchema.check(z24.email());
31555
+ stringSchema = stringSchema.check(z25.email());
31350
31556
  } else if (format === "uri" || format === "uri-reference") {
31351
- stringSchema = stringSchema.check(z24.url());
31557
+ stringSchema = stringSchema.check(z25.url());
31352
31558
  } else if (format === "uuid" || format === "guid") {
31353
- stringSchema = stringSchema.check(z24.uuid());
31559
+ stringSchema = stringSchema.check(z25.uuid());
31354
31560
  } else if (format === "date-time") {
31355
- stringSchema = stringSchema.check(z24.iso.datetime());
31561
+ stringSchema = stringSchema.check(z25.iso.datetime());
31356
31562
  } else if (format === "date") {
31357
- stringSchema = stringSchema.check(z24.iso.date());
31563
+ stringSchema = stringSchema.check(z25.iso.date());
31358
31564
  } else if (format === "time") {
31359
- stringSchema = stringSchema.check(z24.iso.time());
31565
+ stringSchema = stringSchema.check(z25.iso.time());
31360
31566
  } else if (format === "duration") {
31361
- stringSchema = stringSchema.check(z24.iso.duration());
31567
+ stringSchema = stringSchema.check(z25.iso.duration());
31362
31568
  } else if (format === "ipv4") {
31363
- stringSchema = stringSchema.check(z24.ipv4());
31569
+ stringSchema = stringSchema.check(z25.ipv4());
31364
31570
  } else if (format === "ipv6") {
31365
- stringSchema = stringSchema.check(z24.ipv6());
31571
+ stringSchema = stringSchema.check(z25.ipv6());
31366
31572
  } else if (format === "mac") {
31367
- stringSchema = stringSchema.check(z24.mac());
31573
+ stringSchema = stringSchema.check(z25.mac());
31368
31574
  } else if (format === "cidr") {
31369
- stringSchema = stringSchema.check(z24.cidrv4());
31575
+ stringSchema = stringSchema.check(z25.cidrv4());
31370
31576
  } else if (format === "cidr-v6") {
31371
- stringSchema = stringSchema.check(z24.cidrv6());
31577
+ stringSchema = stringSchema.check(z25.cidrv6());
31372
31578
  } else if (format === "base64") {
31373
- stringSchema = stringSchema.check(z24.base64());
31579
+ stringSchema = stringSchema.check(z25.base64());
31374
31580
  } else if (format === "base64url") {
31375
- stringSchema = stringSchema.check(z24.base64url());
31581
+ stringSchema = stringSchema.check(z25.base64url());
31376
31582
  } else if (format === "e164") {
31377
- stringSchema = stringSchema.check(z24.e164());
31583
+ stringSchema = stringSchema.check(z25.e164());
31378
31584
  } else if (format === "jwt") {
31379
- stringSchema = stringSchema.check(z24.jwt());
31585
+ stringSchema = stringSchema.check(z25.jwt());
31380
31586
  } else if (format === "emoji") {
31381
- stringSchema = stringSchema.check(z24.emoji());
31587
+ stringSchema = stringSchema.check(z25.emoji());
31382
31588
  } else if (format === "nanoid") {
31383
- stringSchema = stringSchema.check(z24.nanoid());
31589
+ stringSchema = stringSchema.check(z25.nanoid());
31384
31590
  } else if (format === "cuid") {
31385
- stringSchema = stringSchema.check(z24.cuid());
31591
+ stringSchema = stringSchema.check(z25.cuid());
31386
31592
  } else if (format === "cuid2") {
31387
- stringSchema = stringSchema.check(z24.cuid2());
31593
+ stringSchema = stringSchema.check(z25.cuid2());
31388
31594
  } else if (format === "ulid") {
31389
- stringSchema = stringSchema.check(z24.ulid());
31595
+ stringSchema = stringSchema.check(z25.ulid());
31390
31596
  } else if (format === "xid") {
31391
- stringSchema = stringSchema.check(z24.xid());
31597
+ stringSchema = stringSchema.check(z25.xid());
31392
31598
  } else if (format === "ksuid") {
31393
- stringSchema = stringSchema.check(z24.ksuid());
31599
+ stringSchema = stringSchema.check(z25.ksuid());
31394
31600
  }
31395
31601
  }
31396
31602
  if (typeof schema.minLength === "number") {
@@ -31407,7 +31613,7 @@ function convertBaseSchema(schema, ctx) {
31407
31613
  }
31408
31614
  case "number":
31409
31615
  case "integer": {
31410
- let numberSchema = type === "integer" ? z24.number().int() : z24.number();
31616
+ let numberSchema = type === "integer" ? z25.number().int() : z25.number();
31411
31617
  if (typeof schema.minimum === "number") {
31412
31618
  numberSchema = numberSchema.min(schema.minimum);
31413
31619
  }
@@ -31431,11 +31637,11 @@ function convertBaseSchema(schema, ctx) {
31431
31637
  break;
31432
31638
  }
31433
31639
  case "boolean": {
31434
- zodSchema2 = z24.boolean();
31640
+ zodSchema2 = z25.boolean();
31435
31641
  break;
31436
31642
  }
31437
31643
  case "null": {
31438
- zodSchema2 = z24.null();
31644
+ zodSchema2 = z25.null();
31439
31645
  break;
31440
31646
  }
31441
31647
  case "object": {
@@ -31448,14 +31654,14 @@ function convertBaseSchema(schema, ctx) {
31448
31654
  }
31449
31655
  if (schema.propertyNames) {
31450
31656
  const keySchema = convertSchema(schema.propertyNames, ctx);
31451
- const valueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object" ? convertSchema(schema.additionalProperties, ctx) : z24.any();
31657
+ const valueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object" ? convertSchema(schema.additionalProperties, ctx) : z25.any();
31452
31658
  if (Object.keys(shape).length === 0) {
31453
- zodSchema2 = z24.record(keySchema, valueSchema);
31659
+ zodSchema2 = z25.record(keySchema, valueSchema);
31454
31660
  break;
31455
31661
  }
31456
- const objectSchema2 = z24.object(shape).passthrough();
31457
- const recordSchema = z24.looseRecord(keySchema, valueSchema);
31458
- zodSchema2 = z24.intersection(objectSchema2, recordSchema);
31662
+ const objectSchema2 = z25.object(shape).passthrough();
31663
+ const recordSchema = z25.looseRecord(keySchema, valueSchema);
31664
+ zodSchema2 = z25.intersection(objectSchema2, recordSchema);
31459
31665
  break;
31460
31666
  }
31461
31667
  if (schema.patternProperties) {
@@ -31464,28 +31670,28 @@ function convertBaseSchema(schema, ctx) {
31464
31670
  const looseRecords = [];
31465
31671
  for (const pattern of patternKeys) {
31466
31672
  const patternValue = convertSchema(patternProps[pattern], ctx);
31467
- const keySchema = z24.string().regex(new RegExp(pattern));
31468
- looseRecords.push(z24.looseRecord(keySchema, patternValue));
31673
+ const keySchema = z25.string().regex(new RegExp(pattern));
31674
+ looseRecords.push(z25.looseRecord(keySchema, patternValue));
31469
31675
  }
31470
31676
  const schemasToIntersect = [];
31471
31677
  if (Object.keys(shape).length > 0) {
31472
- schemasToIntersect.push(z24.object(shape).passthrough());
31678
+ schemasToIntersect.push(z25.object(shape).passthrough());
31473
31679
  }
31474
31680
  schemasToIntersect.push(...looseRecords);
31475
31681
  if (schemasToIntersect.length === 0) {
31476
- zodSchema2 = z24.object({}).passthrough();
31682
+ zodSchema2 = z25.object({}).passthrough();
31477
31683
  } else if (schemasToIntersect.length === 1) {
31478
31684
  zodSchema2 = schemasToIntersect[0];
31479
31685
  } else {
31480
- let result = z24.intersection(schemasToIntersect[0], schemasToIntersect[1]);
31686
+ let result = z25.intersection(schemasToIntersect[0], schemasToIntersect[1]);
31481
31687
  for (let i = 2; i < schemasToIntersect.length; i++) {
31482
- result = z24.intersection(result, schemasToIntersect[i]);
31688
+ result = z25.intersection(result, schemasToIntersect[i]);
31483
31689
  }
31484
31690
  zodSchema2 = result;
31485
31691
  }
31486
31692
  break;
31487
31693
  }
31488
- const objectSchema = z24.object(shape);
31694
+ const objectSchema = z25.object(shape);
31489
31695
  if (schema.additionalProperties === false) {
31490
31696
  zodSchema2 = objectSchema.strict();
31491
31697
  } else if (typeof schema.additionalProperties === "object") {
@@ -31502,33 +31708,33 @@ function convertBaseSchema(schema, ctx) {
31502
31708
  const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
31503
31709
  const rest = items && typeof items === "object" && !Array.isArray(items) ? convertSchema(items, ctx) : void 0;
31504
31710
  if (rest) {
31505
- zodSchema2 = z24.tuple(tupleItems).rest(rest);
31711
+ zodSchema2 = z25.tuple(tupleItems).rest(rest);
31506
31712
  } else {
31507
- zodSchema2 = z24.tuple(tupleItems);
31713
+ zodSchema2 = z25.tuple(tupleItems);
31508
31714
  }
31509
31715
  if (typeof schema.minItems === "number") {
31510
- zodSchema2 = zodSchema2.check(z24.minLength(schema.minItems));
31716
+ zodSchema2 = zodSchema2.check(z25.minLength(schema.minItems));
31511
31717
  }
31512
31718
  if (typeof schema.maxItems === "number") {
31513
- zodSchema2 = zodSchema2.check(z24.maxLength(schema.maxItems));
31719
+ zodSchema2 = zodSchema2.check(z25.maxLength(schema.maxItems));
31514
31720
  }
31515
31721
  } else if (Array.isArray(items)) {
31516
31722
  const tupleItems = items.map((item) => convertSchema(item, ctx));
31517
31723
  const rest = schema.additionalItems && typeof schema.additionalItems === "object" ? convertSchema(schema.additionalItems, ctx) : void 0;
31518
31724
  if (rest) {
31519
- zodSchema2 = z24.tuple(tupleItems).rest(rest);
31725
+ zodSchema2 = z25.tuple(tupleItems).rest(rest);
31520
31726
  } else {
31521
- zodSchema2 = z24.tuple(tupleItems);
31727
+ zodSchema2 = z25.tuple(tupleItems);
31522
31728
  }
31523
31729
  if (typeof schema.minItems === "number") {
31524
- zodSchema2 = zodSchema2.check(z24.minLength(schema.minItems));
31730
+ zodSchema2 = zodSchema2.check(z25.minLength(schema.minItems));
31525
31731
  }
31526
31732
  if (typeof schema.maxItems === "number") {
31527
- zodSchema2 = zodSchema2.check(z24.maxLength(schema.maxItems));
31733
+ zodSchema2 = zodSchema2.check(z25.maxLength(schema.maxItems));
31528
31734
  }
31529
31735
  } else if (items !== void 0) {
31530
31736
  const element = convertSchema(items, ctx);
31531
- let arraySchema = z24.array(element);
31737
+ let arraySchema = z25.array(element);
31532
31738
  if (typeof schema.minItems === "number") {
31533
31739
  arraySchema = arraySchema.min(schema.minItems);
31534
31740
  }
@@ -31537,7 +31743,7 @@ function convertBaseSchema(schema, ctx) {
31537
31743
  }
31538
31744
  zodSchema2 = arraySchema;
31539
31745
  } else {
31540
- zodSchema2 = z24.array(z24.any());
31746
+ zodSchema2 = z25.array(z25.any());
31541
31747
  }
31542
31748
  break;
31543
31749
  }
@@ -31554,37 +31760,37 @@ function convertBaseSchema(schema, ctx) {
31554
31760
  }
31555
31761
  function convertSchema(schema, ctx) {
31556
31762
  if (typeof schema === "boolean") {
31557
- return schema ? z24.any() : z24.never();
31763
+ return schema ? z25.any() : z25.never();
31558
31764
  }
31559
31765
  let baseSchema = convertBaseSchema(schema, ctx);
31560
31766
  const hasExplicitType = schema.type || schema.enum !== void 0 || schema.const !== void 0;
31561
31767
  if (schema.anyOf && Array.isArray(schema.anyOf)) {
31562
31768
  const options = schema.anyOf.map((s) => convertSchema(s, ctx));
31563
- const anyOfUnion = z24.union(options);
31564
- baseSchema = hasExplicitType ? z24.intersection(baseSchema, anyOfUnion) : anyOfUnion;
31769
+ const anyOfUnion = z25.union(options);
31770
+ baseSchema = hasExplicitType ? z25.intersection(baseSchema, anyOfUnion) : anyOfUnion;
31565
31771
  }
31566
31772
  if (schema.oneOf && Array.isArray(schema.oneOf)) {
31567
31773
  const options = schema.oneOf.map((s) => convertSchema(s, ctx));
31568
- const oneOfUnion = z24.xor(options);
31569
- baseSchema = hasExplicitType ? z24.intersection(baseSchema, oneOfUnion) : oneOfUnion;
31774
+ const oneOfUnion = z25.xor(options);
31775
+ baseSchema = hasExplicitType ? z25.intersection(baseSchema, oneOfUnion) : oneOfUnion;
31570
31776
  }
31571
31777
  if (schema.allOf && Array.isArray(schema.allOf)) {
31572
31778
  if (schema.allOf.length === 0) {
31573
- baseSchema = hasExplicitType ? baseSchema : z24.any();
31779
+ baseSchema = hasExplicitType ? baseSchema : z25.any();
31574
31780
  } else {
31575
31781
  let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0], ctx);
31576
31782
  const startIdx = hasExplicitType ? 0 : 1;
31577
31783
  for (let i = startIdx; i < schema.allOf.length; i++) {
31578
- result = z24.intersection(result, convertSchema(schema.allOf[i], ctx));
31784
+ result = z25.intersection(result, convertSchema(schema.allOf[i], ctx));
31579
31785
  }
31580
31786
  baseSchema = result;
31581
31787
  }
31582
31788
  }
31583
31789
  if (schema.nullable === true && ctx.version === "openapi-3.0") {
31584
- baseSchema = z24.nullable(baseSchema);
31790
+ baseSchema = z25.nullable(baseSchema);
31585
31791
  }
31586
31792
  if (schema.readOnly === true) {
31587
- baseSchema = z24.readonly(baseSchema);
31793
+ baseSchema = z25.readonly(baseSchema);
31588
31794
  }
31589
31795
  const extraMeta = {};
31590
31796
  const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
@@ -31611,7 +31817,7 @@ function convertSchema(schema, ctx) {
31611
31817
  }
31612
31818
  function fromJSONSchema(schema, params) {
31613
31819
  if (typeof schema === "boolean") {
31614
- return schema ? z24.any() : z24.never();
31820
+ return schema ? z25.any() : z25.never();
31615
31821
  }
31616
31822
  const version2 = detectVersion(schema, params?.defaultTarget);
31617
31823
  const defs = schema.$defs || schema.definitions || {};
@@ -31625,14 +31831,14 @@ function fromJSONSchema(schema, params) {
31625
31831
  };
31626
31832
  return convertSchema(schema, ctx);
31627
31833
  }
31628
- var z24, RECOGNIZED_KEYS;
31834
+ var z25, RECOGNIZED_KEYS;
31629
31835
  var init_from_json_schema = __esm({
31630
31836
  "node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/from-json-schema.js"() {
31631
31837
  init_registries();
31632
31838
  init_checks2();
31633
31839
  init_iso();
31634
31840
  init_schemas2();
31635
- z24 = {
31841
+ z25 = {
31636
31842
  ...schemas_exports2,
31637
31843
  ...checks_exports2,
31638
31844
  iso: iso_exports
@@ -43141,7 +43347,7 @@ var init_spawn = __esm({
43141
43347
  *
43142
43348
  * Uses 3-tier key resolution so the provider works with:
43143
43349
  * - `ANTHROPIC_API_KEY` environment variable (explicit)
43144
- * - `~/.local/share/cleo/anthropic-key` (user-stored via cleo config)
43350
+ * - `<getCleoHome()>/anthropic-key` (user-stored via cleo config)
43145
43351
  * - Claude Code OAuth token (zero-config for Claude Code users)
43146
43352
  *
43147
43353
  * @returns `true` when any Anthropic credential is available
@@ -43272,10 +43478,10 @@ var init_spawn = __esm({
43272
43478
  });
43273
43479
 
43274
43480
  // packages/adapters/src/providers/claude-code/paths.ts
43275
- import { homedir as homedir3 } from "node:os";
43481
+ import { homedir as homedir2 } from "node:os";
43276
43482
  import { join as join3 } from "node:path";
43277
43483
  function claudeSettingsPath() {
43278
- return new ClaudeCodePathProvider().getSettingsPath() ?? join3(homedir3(), ".claude", "settings.json");
43484
+ return new ClaudeCodePathProvider().getSettingsPath() ?? join3(homedir2(), ".claude", "settings.json");
43279
43485
  }
43280
43486
  function isPlainObject2(value) {
43281
43487
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -43327,7 +43533,7 @@ var init_paths = __esm({
43327
43533
  ClaudeCodePathProvider = class {
43328
43534
  /** Get the provider's root configuration directory. */
43329
43535
  getProviderDir() {
43330
- return process.env["CLAUDE_HOME"] ?? join3(homedir3(), ".claude");
43536
+ return process.env["CLAUDE_HOME"] ?? join3(homedir2(), ".claude");
43331
43537
  }
43332
43538
  /** Get the path to the provider's settings file, or null if unavailable. */
43333
43539
  getSettingsPath() {
@@ -43339,7 +43545,7 @@ var init_paths = __esm({
43339
43545
  }
43340
43546
  /** Get the path to the provider's memory database, or null if unsupported. */
43341
43547
  getMemoryDbPath() {
43342
- return process.env["CLAUDE_MEM_DB"] ?? join3(homedir3(), ".claude-mem", "claude-mem.db");
43548
+ return process.env["CLAUDE_MEM_DB"] ?? join3(homedir2(), ".claude-mem", "claude-mem.db");
43343
43549
  }
43344
43550
  };
43345
43551
  CLEO_HOOK_MARKER = "# cleo-hook";
@@ -43349,7 +43555,7 @@ var init_paths = __esm({
43349
43555
  // packages/adapters/src/providers/claude-code/context-monitor.ts
43350
43556
  import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "node:fs";
43351
43557
  import { mkdir } from "node:fs/promises";
43352
- import { homedir as homedir4 } from "node:os";
43558
+ import { homedir as homedir3 } from "node:os";
43353
43559
  import { dirname, join as join4 } from "node:path";
43354
43560
  import { resolveLegacyCleoDir } from "@cleocode/paths";
43355
43561
  function getContextStatusFromPercentage(percentage) {
@@ -43435,7 +43641,7 @@ var init_context_monitor = __esm({
43435
43641
  if (cmd.includes("context-monitor.sh") || cmd.includes("cleo-statusline") || cmd.includes(".context-state.json") || cmd.includes("context-states")) {
43436
43642
  return "configured";
43437
43643
  }
43438
- const scriptPath = cmd.startsWith("~") ? cmd.replace("~", homedir4()) : cmd;
43644
+ const scriptPath = cmd.startsWith("~") ? cmd.replace("~", homedir3()) : cmd;
43439
43645
  if (existsSync3(scriptPath)) {
43440
43646
  try {
43441
43647
  const content = readFileSync3(scriptPath, "utf-8");
@@ -43884,12 +44090,12 @@ var init_hook_template_installer = __esm({
43884
44090
 
43885
44091
  // packages/adapters/src/providers/claude-code/install.ts
43886
44092
  import { copyFileSync as copyFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "node:fs";
43887
- import { homedir as homedir5 } from "node:os";
44093
+ import { homedir as homedir4 } from "node:os";
43888
44094
  import { dirname as dirname3, join as join7 } from "node:path";
43889
44095
  import { fileURLToPath as fileURLToPath2 } from "node:url";
43890
44096
  import { ensureProviderInstructionFile, updateJsonConfigFile as updateJsonConfigFile2 } from "@cleocode/caamp";
43891
44097
  function getClaudeConfigDir() {
43892
- return process.env["CLAUDE_HOME"] ?? join7(homedir5(), ".claude");
44098
+ return process.env["CLAUDE_HOME"] ?? join7(homedir4(), ".claude");
43893
44099
  }
43894
44100
  function getAdapterCommandsDir() {
43895
44101
  const thisDir = dirname3(fileURLToPath2(import.meta.url));
@@ -44116,6 +44322,7 @@ var init_install = __esm({
44116
44322
  // packages/adapters/src/providers/shared/agent-spawn-wrapper.ts
44117
44323
  import { spawnSync } from "node:child_process";
44118
44324
  import { readFileSync as readFileSync5 } from "node:fs";
44325
+ import { resolveSpawnInvocation } from "@cleocode/paths";
44119
44326
  function hasSystemdRun() {
44120
44327
  if (_systemdRunAvailable !== void 0) return _systemdRunAvailable;
44121
44328
  if (process.platform !== "linux") {
@@ -44138,12 +44345,21 @@ function readMemTotalBytes() {
44138
44345
  }
44139
44346
  function buildAgentSpawnArgs(command, args, scopeId) {
44140
44347
  if (!hasSystemdRun()) {
44141
- if (!_demotionLogged) {
44348
+ if (!_demotionLogged && process.platform === "linux" && process.env["CLEO_DEBUG"]) {
44142
44349
  _demotionLogged = true;
44143
44350
  process.stderr.write(
44144
44351
  "[cleo:agent-spawn-wrapper] systemd-run unavailable \u2014 falling back to plain pgid (detached) spawn; no cgroup containment\n"
44145
44352
  );
44146
44353
  }
44354
+ if (process.platform === "win32") {
44355
+ const inv = resolveSpawnInvocation(command, args);
44356
+ return {
44357
+ command: inv.file,
44358
+ args: inv.args,
44359
+ ...inv.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {},
44360
+ ownership: { mode: "pgid" }
44361
+ };
44362
+ }
44147
44363
  return {
44148
44364
  command: "sh",
44149
44365
  args: ["-c", 'ulimit -c 0; exec "$@"', "sh", command, ...args],
@@ -44201,6 +44417,25 @@ var init_agent_spawn_wrapper = __esm({
44201
44417
  }
44202
44418
  });
44203
44419
 
44420
+ // packages/adapters/src/providers/shared/prompt-file.ts
44421
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
44422
+ import { tmpdir } from "node:os";
44423
+ import { dirname as dirname4, join as join8 } from "node:path";
44424
+ async function writeSpawnPromptFile(prefix, prompt) {
44425
+ const dir = await mkdtemp(join8(tmpdir(), `cleo-${prefix}-`));
44426
+ const file2 = join8(dir, "prompt.txt");
44427
+ await writeFile(file2, prompt, "utf-8");
44428
+ return file2;
44429
+ }
44430
+ async function removeSpawnPromptFile(file2) {
44431
+ await rm(dirname4(file2), { recursive: true, force: true }).catch(() => void 0);
44432
+ }
44433
+ var init_prompt_file = __esm({
44434
+ "packages/adapters/src/providers/shared/prompt-file.ts"() {
44435
+ "use strict";
44436
+ }
44437
+ });
44438
+
44204
44439
  // packages/adapters/src/providers/claude-code/suite-reaper.ts
44205
44440
  import { spawnSync as spawnSync2 } from "node:child_process";
44206
44441
  async function reapAgentSuite(ownership) {
@@ -44296,32 +44531,26 @@ var init_suite_reaper = __esm({
44296
44531
  });
44297
44532
 
44298
44533
  // packages/adapters/src/providers/claude-code/spawn.ts
44299
- import { exec, spawn as nodeSpawn } from "node:child_process";
44300
- import { unlink, writeFile } from "node:fs/promises";
44301
- import { promisify as promisify2 } from "node:util";
44302
- var execAsync, ClaudeCodeSpawnProvider;
44534
+ import { spawn as nodeSpawn } from "node:child_process";
44535
+ import { findOnPath } from "@cleocode/paths";
44536
+ var ClaudeCodeSpawnProvider;
44303
44537
  var init_spawn2 = __esm({
44304
44538
  "packages/adapters/src/providers/claude-code/spawn.ts"() {
44305
44539
  "use strict";
44306
44540
  init_src();
44307
44541
  init_agent_spawn_wrapper();
44542
+ init_prompt_file();
44308
44543
  init_suite_reaper();
44309
- execAsync = promisify2(exec);
44310
44544
  ClaudeCodeSpawnProvider = class {
44311
44545
  /** Map of instance IDs to tracked process info. */
44312
44546
  processMap = /* @__PURE__ */ new Map();
44313
44547
  /**
44314
44548
  * Check if the Claude CLI is available in PATH.
44315
44549
  *
44316
- * @returns true if `claude` is found via `which`
44550
+ * @returns true if `claude` is found on PATH (PATHEXT-aware on Windows)
44317
44551
  */
44318
44552
  async canSpawn() {
44319
- try {
44320
- await execAsync("which claude");
44321
- return true;
44322
- } catch {
44323
- return false;
44324
- }
44553
+ return findOnPath("claude") !== null;
44325
44554
  }
44326
44555
  /**
44327
44556
  * Spawn a subagent via Claude CLI.
@@ -44351,8 +44580,7 @@ var init_spawn2 = __esm({
44351
44580
  });
44352
44581
  } catch {
44353
44582
  }
44354
- tmpFile = `/tmp/claude-spawn-${instanceId}.txt`;
44355
- await writeFile(tmpFile, enrichedPrompt, "utf-8");
44583
+ tmpFile = await writeSpawnPromptFile("claude-spawn", enrichedPrompt);
44356
44584
  const claudeArgs = [
44357
44585
  "--print",
44358
44586
  "--dangerously-skip-permissions",
@@ -44364,7 +44592,9 @@ var init_spawn2 = __esm({
44364
44592
  const isSystemd = spawnBuild.ownership.mode === "systemd";
44365
44593
  const spawnOpts = {
44366
44594
  detached: !isSystemd,
44367
- stdio: ["ignore", "pipe", "pipe"]
44595
+ stdio: ["ignore", "pipe", "pipe"],
44596
+ // win32 `.cmd` shim routed through cmd.exe: keep its quoting (T12618).
44597
+ ...spawnBuild.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
44368
44598
  };
44369
44599
  if (context.workingDirectory) {
44370
44600
  spawnOpts.cwd = context.workingDirectory;
@@ -44391,10 +44621,7 @@ var init_spawn2 = __esm({
44391
44621
  const capturedTmpFile = tmpFile;
44392
44622
  child.on("exit", async () => {
44393
44623
  this.processMap.delete(instanceId);
44394
- try {
44395
- await unlink(capturedTmpFile);
44396
- } catch {
44397
- }
44624
+ await removeSpawnPromptFile(capturedTmpFile);
44398
44625
  });
44399
44626
  return {
44400
44627
  instanceId,
@@ -44409,10 +44636,7 @@ var init_spawn2 = __esm({
44409
44636
  } catch (error48) {
44410
44637
  console.error(`[ClaudeCodeSpawnProvider] Failed to spawn: ${getErrorMessage(error48)}`);
44411
44638
  if (tmpFile) {
44412
- try {
44413
- await unlink(tmpFile);
44414
- } catch {
44415
- }
44639
+ await removeSpawnPromptFile(tmpFile);
44416
44640
  }
44417
44641
  return {
44418
44642
  instanceId,
@@ -44497,7 +44721,7 @@ var init_spawn2 = __esm({
44497
44721
 
44498
44722
  // packages/adapters/src/providers/claude-code/task-sync.ts
44499
44723
  import { readFile as readFile2, stat } from "node:fs/promises";
44500
- import { join as join8 } from "node:path";
44724
+ import { join as join9 } from "node:path";
44501
44725
  function parseTaskId(content) {
44502
44726
  const match = content.match(/^\[T(\d+)\]/);
44503
44727
  return match ? `T${match[1]}` : null;
@@ -44518,7 +44742,7 @@ function mapStatus(twStatus) {
44518
44742
  }
44519
44743
  }
44520
44744
  function getTodoWriteFilePath(projectDir) {
44521
- return join8(projectDir, ".cleo", "sync", "todowrite-state.json");
44745
+ return join9(projectDir, ".cleo", "sync", "todowrite-state.json");
44522
44746
  }
44523
44747
  var ClaudeCodeTaskSyncProvider;
44524
44748
  var init_task_sync = __esm({
@@ -44589,12 +44813,11 @@ var init_transport = __esm({
44589
44813
  });
44590
44814
 
44591
44815
  // packages/adapters/src/providers/claude-code/adapter.ts
44592
- import { exec as exec2 } from "node:child_process";
44593
44816
  import { existsSync as existsSync7 } from "node:fs";
44594
- import { homedir as homedir6 } from "node:os";
44595
- import { join as join9 } from "node:path";
44596
- import { promisify as promisify3 } from "node:util";
44597
- var execAsync2, ClaudeCodeAdapter;
44817
+ import { homedir as homedir5 } from "node:os";
44818
+ import { join as join10 } from "node:path";
44819
+ import { findOnPath as findOnPath2 } from "@cleocode/paths";
44820
+ var ClaudeCodeAdapter;
44598
44821
  var init_adapter = __esm({
44599
44822
  "packages/adapters/src/providers/claude-code/adapter.ts"() {
44600
44823
  "use strict";
@@ -44606,7 +44829,6 @@ var init_adapter = __esm({
44606
44829
  init_spawn2();
44607
44830
  init_task_sync();
44608
44831
  init_transport();
44609
- execAsync2 = promisify3(exec2);
44610
44832
  ClaudeCodeAdapter = class {
44611
44833
  /** Unique provider identifier. */
44612
44834
  id = "claude-code";
@@ -44742,14 +44964,11 @@ var init_adapter = __esm({
44742
44964
  };
44743
44965
  }
44744
44966
  let cliAvailable = false;
44745
- try {
44746
- const { stdout } = await execAsync2("which claude");
44747
- cliAvailable = stdout.trim().length > 0;
44748
- details.cliPath = stdout.trim();
44749
- } catch {
44750
- details.cliAvailable = false;
44751
- }
44752
- const claudeConfigDir = join9(homedir6(), ".claude");
44967
+ const resolvedCli = findOnPath2("claude");
44968
+ cliAvailable = resolvedCli !== null;
44969
+ if (resolvedCli) details.cliPath = resolvedCli;
44970
+ else details.cliAvailable = false;
44971
+ const claudeConfigDir = join10(homedir5(), ".claude");
44753
44972
  const configExists = existsSync7(claudeConfigDir);
44754
44973
  details.configDirExists = configExists;
44755
44974
  const entrypointSet = process.env.CLAUDE_CODE_ENTRYPOINT !== void 0;
@@ -44780,10 +44999,10 @@ var init_adapter = __esm({
44780
44999
 
44781
45000
  // packages/adapters/src/providers/claude-code/statusline.ts
44782
45001
  import { existsSync as existsSync8, readFileSync as readFileSync6 } from "node:fs";
44783
- import { homedir as homedir7 } from "node:os";
44784
- import { join as join10 } from "node:path";
45002
+ import { homedir as homedir6 } from "node:os";
45003
+ import { join as join11 } from "node:path";
44785
45004
  function getClaudeSettingsPath() {
44786
- return process.env["CLAUDE_SETTINGS"] ?? join10(process.env["CLAUDE_HOME"] ?? join10(homedir7(), ".claude"), "settings.json");
45005
+ return process.env["CLAUDE_SETTINGS"] ?? join11(process.env["CLAUDE_HOME"] ?? join11(homedir6(), ".claude"), "settings.json");
44787
45006
  }
44788
45007
  function checkStatuslineIntegration() {
44789
45008
  const settingsPath = getClaudeSettingsPath();
@@ -44797,7 +45016,7 @@ function checkStatuslineIntegration() {
44797
45016
  if (cmd.includes("context-monitor.sh") || cmd.includes("cleo-statusline") || cmd.includes(".context-state.json") || cmd.includes("context-states")) {
44798
45017
  return "configured";
44799
45018
  }
44800
- const scriptPath = cmd.startsWith("~") ? cmd.replace("~", homedir7()) : cmd;
45019
+ const scriptPath = cmd.startsWith("~") ? cmd.replace("~", homedir6()) : cmd;
44801
45020
  if (existsSync8(scriptPath)) {
44802
45021
  try {
44803
45022
  const content = readFileSync6(scriptPath, "utf-8");
@@ -44814,7 +45033,7 @@ function getStatuslineConfig(cleoHome) {
44814
45033
  return {
44815
45034
  statusLine: {
44816
45035
  type: "command",
44817
- command: join10(cleoHome, "lib", "session", "context-monitor.sh")
45036
+ command: join11(cleoHome, "lib", "session", "context-monitor.sh")
44818
45037
  }
44819
45038
  };
44820
45039
  }
@@ -44879,6 +45098,23 @@ var init_paths2 = __esm({
44879
45098
  }
44880
45099
  });
44881
45100
 
45101
+ // packages/adapters/src/providers/shared/cli-spawn.ts
45102
+ import { spawn } from "node:child_process";
45103
+ import { resolveSpawnInvocation as resolveSpawnInvocation2 } from "@cleocode/paths";
45104
+ function spawnCli(command, args, options) {
45105
+ const inv = resolveSpawnInvocation2(command, args);
45106
+ return spawn(
45107
+ inv.file,
45108
+ inv.args,
45109
+ inv.windowsVerbatimArguments ? { ...options, windowsVerbatimArguments: true } : options
45110
+ );
45111
+ }
45112
+ var init_cli_spawn = __esm({
45113
+ "packages/adapters/src/providers/shared/cli-spawn.ts"() {
45114
+ "use strict";
45115
+ }
45116
+ });
45117
+
44882
45118
  // packages/adapters/src/providers/cursor/hooks.ts
44883
45119
  var PROVIDER_ID2, CURSOR_EVENT_MAP, CursorHookProvider;
44884
45120
  var init_hooks2 = __esm({
@@ -45034,7 +45270,7 @@ var init_hooks2 = __esm({
45034
45270
 
45035
45271
  // packages/adapters/src/providers/cursor/install.ts
45036
45272
  import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
45037
- import { join as join16 } from "node:path";
45273
+ import { join as join17 } from "node:path";
45038
45274
  import {
45039
45275
  ensureProviderInstructionFile as ensureProviderInstructionFile3,
45040
45276
  ensureProviderRuleFile,
@@ -45105,11 +45341,11 @@ var init_install2 = __esm({
45105
45341
  * Checks for .cursor/rules/cleo.mdc or .cursorrules with CLEO references.
45106
45342
  */
45107
45343
  async isInstalled() {
45108
- const mdcPath = join16(process.cwd(), ".cursor", "rules", "cleo.mdc");
45344
+ const mdcPath = join17(process.cwd(), ".cursor", "rules", "cleo.mdc");
45109
45345
  if (existsSync11(mdcPath)) {
45110
45346
  return true;
45111
45347
  }
45112
- const rulesPath = join16(process.cwd(), ".cursorrules");
45348
+ const rulesPath = join17(process.cwd(), ".cursorrules");
45113
45349
  if (existsSync11(rulesPath)) {
45114
45350
  try {
45115
45351
  const content = readFileSync7(rulesPath, "utf-8");
@@ -45157,7 +45393,7 @@ var init_install2 = __esm({
45157
45393
  onlyIfExists: true
45158
45394
  }),
45159
45395
  await ensureProviderRuleFile("cursor", projectDir, {
45160
- relativePath: join16(".cursor", "rules", "cleo.mdc"),
45396
+ relativePath: join17(".cursor", "rules", "cleo.mdc"),
45161
45397
  preamble: CLEO_MDC_FRONTMATTER
45162
45398
  })
45163
45399
  ];
@@ -45168,10 +45404,10 @@ var init_install2 = __esm({
45168
45404
  */
45169
45405
  getUpdatedFileList(projectDir) {
45170
45406
  const files = [];
45171
- if (existsSync11(join16(projectDir, ".cursorrules"))) {
45172
- files.push(join16(projectDir, ".cursorrules"));
45407
+ if (existsSync11(join17(projectDir, ".cursorrules"))) {
45408
+ files.push(join17(projectDir, ".cursorrules"));
45173
45409
  }
45174
- files.push(join16(projectDir, ".cursor", "rules", "cleo.mdc"));
45410
+ files.push(join17(projectDir, ".cursor", "rules", "cleo.mdc"));
45175
45411
  return files;
45176
45412
  }
45177
45413
  /**
@@ -45193,7 +45429,7 @@ var init_install2 = __esm({
45193
45429
  * @task T1013
45194
45430
  */
45195
45431
  async installHookTemplates(projectDir) {
45196
- const hooksDir = join16(projectDir, ".cursor", "hooks");
45432
+ const hooksDir = join17(projectDir, ".cursor", "hooks");
45197
45433
  let templates;
45198
45434
  try {
45199
45435
  templates = installProviderHookTemplates({
@@ -45205,7 +45441,7 @@ var init_install2 = __esm({
45205
45441
  }
45206
45442
  const hooksJsonEntryAdded = await this.registerPreCompactHook(
45207
45443
  projectDir,
45208
- join16(hooksDir, "precompact.sh")
45444
+ join17(hooksDir, "precompact.sh")
45209
45445
  );
45210
45446
  if (templates.installedFiles.length === 0 && !hooksJsonEntryAdded) {
45211
45447
  return null;
@@ -45226,7 +45462,7 @@ var init_install2 = __esm({
45226
45462
  * @task T1013
45227
45463
  */
45228
45464
  async registerPreCompactHook(projectDir, shimPath) {
45229
- const hooksJsonPath = join16(projectDir, ".cursor", "hooks.json");
45465
+ const hooksJsonPath = join17(projectDir, ".cursor", "hooks.json");
45230
45466
  return updateJsonConfigFile3(hooksJsonPath, (config2) => {
45231
45467
  const hooks = config2.hooks ?? {};
45232
45468
  if (!isRecord(hooks)) {
@@ -45256,7 +45492,7 @@ var init_install2 = __esm({
45256
45492
 
45257
45493
  // packages/adapters/src/providers/cursor/adapter.ts
45258
45494
  import { existsSync as existsSync12 } from "node:fs";
45259
- import { join as join17 } from "node:path";
45495
+ import { join as join18 } from "node:path";
45260
45496
  var CursorAdapter;
45261
45497
  var init_adapter2 = __esm({
45262
45498
  "packages/adapters/src/providers/cursor/adapter.ts"() {
@@ -45350,14 +45586,14 @@ var init_adapter2 = __esm({
45350
45586
  }
45351
45587
  let configExists = false;
45352
45588
  if (this.projectDir) {
45353
- const cursorConfigDir = join17(this.projectDir, ".cursor");
45589
+ const cursorConfigDir = join18(this.projectDir, ".cursor");
45354
45590
  configExists = existsSync12(cursorConfigDir);
45355
45591
  details.configDirExists = configExists;
45356
45592
  }
45357
45593
  const editorEnvSet = process.env.CURSOR_EDITOR !== void 0;
45358
45594
  details.editorEnvSet = editorEnvSet;
45359
45595
  if (this.projectDir) {
45360
- const legacyRulesExist = existsSync12(join17(this.projectDir, ".cursorrules"));
45596
+ const legacyRulesExist = existsSync12(join18(this.projectDir, ".cursorrules"));
45361
45597
  details.legacyRulesExist = legacyRulesExist;
45362
45598
  }
45363
45599
  const healthy = configExists || editorEnvSet;
@@ -45562,7 +45798,7 @@ var init_hooks3 = __esm({
45562
45798
 
45563
45799
  // packages/adapters/src/providers/opencode/install.ts
45564
45800
  import { existsSync as existsSync17, mkdirSync as mkdirSync3, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
45565
- import { join as join23 } from "node:path";
45801
+ import { join as join24 } from "node:path";
45566
45802
  import { ensureProviderInstructionFile as ensureProviderInstructionFile6 } from "@cleocode/caamp";
45567
45803
  var OpenCodeInstallProvider;
45568
45804
  var init_install3 = __esm({
@@ -45587,7 +45823,7 @@ var init_install3 = __esm({
45587
45823
  });
45588
45824
  const instructionFileUpdated = instructResult.action !== "intact";
45589
45825
  if (instructionFileUpdated) {
45590
- details.instructionFile = join23(projectDir, instructResult.instructFile);
45826
+ details.instructionFile = join24(projectDir, instructResult.instructFile);
45591
45827
  }
45592
45828
  const hookResult = this.installHookTemplates(projectDir);
45593
45829
  if (hookResult) {
@@ -45660,8 +45896,8 @@ var init_install3 = __esm({
45660
45896
  * @task T1013
45661
45897
  */
45662
45898
  installHookTemplates(projectDir) {
45663
- const pluginsDir = join23(projectDir, ".opencode", "plugins");
45664
- const hooksDir = join23(pluginsDir, "hooks");
45899
+ const pluginsDir = join24(projectDir, ".opencode", "plugins");
45900
+ const hooksDir = join24(pluginsDir, "hooks");
45665
45901
  let templates;
45666
45902
  try {
45667
45903
  templates = installProviderHookTemplates({
@@ -45673,7 +45909,7 @@ var init_install3 = __esm({
45673
45909
  }
45674
45910
  let pluginWritten = false;
45675
45911
  try {
45676
- pluginWritten = this.writePrecompactPlugin(pluginsDir, join23(hooksDir, "precompact.sh"));
45912
+ pluginWritten = this.writePrecompactPlugin(pluginsDir, join24(hooksDir, "precompact.sh"));
45677
45913
  } catch {
45678
45914
  }
45679
45915
  if (templates.installedFiles.length === 0 && !pluginWritten) {
@@ -45697,7 +45933,7 @@ var init_install3 = __esm({
45697
45933
  * @task T1013
45698
45934
  */
45699
45935
  writePrecompactPlugin(pluginsDir, shimPath) {
45700
- const pluginPath = join23(pluginsDir, "cleo-precompact.js");
45936
+ const pluginPath = join24(pluginsDir, "cleo-precompact.js");
45701
45937
  const generated = [
45702
45938
  "// CLEO PreCompact plugin for OpenCode (generated by @cleocode/adapters).",
45703
45939
  "// Bridges the canonical CAAMP `PreCompact` event",
@@ -45740,10 +45976,9 @@ var init_install3 = __esm({
45740
45976
  });
45741
45977
 
45742
45978
  // packages/adapters/src/providers/opencode/spawn.ts
45743
- import { exec as exec9, spawn as nodeSpawn4 } from "node:child_process";
45744
45979
  import { mkdir as mkdir2, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
45745
- import { join as join24 } from "node:path";
45746
- import { promisify as promisify10 } from "node:util";
45980
+ import { join as join25 } from "node:path";
45981
+ import { findOnPath as findOnPath9 } from "@cleocode/paths";
45747
45982
  function buildOpenCodeAgentMarkdown(description, instructions) {
45748
45983
  const normalizedDesc = description.replace(/\s+/g, " ").trim();
45749
45984
  return [
@@ -45758,8 +45993,8 @@ function buildOpenCodeAgentMarkdown(description, instructions) {
45758
45993
  ].join("\n");
45759
45994
  }
45760
45995
  async function ensureSubagentDefinition(workingDirectory, enrichedInstructions) {
45761
- const agentDir = join24(workingDirectory, ".opencode", "agent");
45762
- const agentPath = join24(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
45996
+ const agentDir = join25(workingDirectory, ".opencode", "agent");
45997
+ const agentPath = join25(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
45763
45998
  const description = "CLEO task executor with protocol compliance and CANT context.";
45764
45999
  const instructions = enrichedInstructions ?? [
45765
46000
  "# CLEO Subagent",
@@ -45782,12 +46017,12 @@ async function ensureSubagentDefinition(workingDirectory, enrichedInstructions)
45782
46017
  }
45783
46018
  return OPENCODE_SUBAGENT_NAME;
45784
46019
  }
45785
- var execAsync9, OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
46020
+ var OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
45786
46021
  var init_spawn3 = __esm({
45787
46022
  "packages/adapters/src/providers/opencode/spawn.ts"() {
45788
46023
  "use strict";
46024
+ init_cli_spawn();
45789
46025
  init_paths2();
45790
- execAsync9 = promisify10(exec9);
45791
46026
  OPENCODE_SUBAGENT_NAME = "cleo-subagent";
45792
46027
  OPENCODE_FALLBACK_AGENT = "general";
45793
46028
  OpenCodeSpawnProvider = class {
@@ -45796,15 +46031,10 @@ var init_spawn3 = __esm({
45796
46031
  /**
45797
46032
  * Check if the OpenCode CLI is available in PATH.
45798
46033
  *
45799
- * @returns true if `opencode` is found via `which`
46034
+ * @returns true if `opencode` is found on PATH (PATHEXT-aware on Windows)
45800
46035
  */
45801
46036
  async canSpawn() {
45802
- try {
45803
- await execAsync9("which opencode");
45804
- return true;
45805
- } catch {
45806
- return false;
45807
- }
46037
+ return findOnPath9("opencode") !== null;
45808
46038
  }
45809
46039
  /**
45810
46040
  * Spawn a subagent via OpenCode CLI.
@@ -45837,24 +46067,17 @@ var init_spawn3 = __esm({
45837
46067
  } catch {
45838
46068
  agentName = OPENCODE_FALLBACK_AGENT;
45839
46069
  }
45840
- const child = nodeSpawn4(
46070
+ const child = spawnCli(
45841
46071
  "opencode",
45842
- [
45843
- "run",
45844
- "--format",
45845
- "json",
45846
- "--agent",
45847
- agentName,
45848
- "--title",
45849
- `CLEO ${context.taskId}`,
45850
- context.prompt
45851
- ],
46072
+ ["run", "--format", "json", "--agent", agentName, "--title", `CLEO ${context.taskId}`],
45852
46073
  {
45853
46074
  cwd: workingDirectory,
45854
46075
  detached: true,
45855
- stdio: "ignore"
46076
+ stdio: ["pipe", "ignore", "ignore"]
45856
46077
  }
45857
46078
  );
46079
+ child.stdin?.on("error", () => void 0);
46080
+ child.stdin?.end(context.prompt, "utf-8");
45858
46081
  child.unref();
45859
46082
  if (child.pid) {
45860
46083
  this.processMap.set(instanceId, {
@@ -45866,6 +46089,9 @@ var init_spawn3 = __esm({
45866
46089
  child.on("exit", () => {
45867
46090
  this.processMap.delete(instanceId);
45868
46091
  });
46092
+ child.on("error", () => {
46093
+ this.processMap.delete(instanceId);
46094
+ });
45869
46095
  return {
45870
46096
  instanceId,
45871
46097
  taskId: context.taskId,
@@ -45932,18 +46158,16 @@ var init_spawn3 = __esm({
45932
46158
  });
45933
46159
 
45934
46160
  // packages/adapters/src/providers/opencode/adapter.ts
45935
- import { exec as exec10 } from "node:child_process";
45936
46161
  import { existsSync as existsSync18 } from "node:fs";
45937
- import { join as join25 } from "node:path";
45938
- import { promisify as promisify11 } from "node:util";
45939
- var execAsync10, OpenCodeAdapter;
46162
+ import { join as join26 } from "node:path";
46163
+ import { findOnPath as findOnPath10 } from "@cleocode/paths";
46164
+ var OpenCodeAdapter;
45940
46165
  var init_adapter3 = __esm({
45941
46166
  "packages/adapters/src/providers/opencode/adapter.ts"() {
45942
46167
  "use strict";
45943
46168
  init_hooks3();
45944
46169
  init_install3();
45945
46170
  init_spawn3();
45946
- execAsync10 = promisify11(exec10);
45947
46171
  OpenCodeAdapter = class {
45948
46172
  /** Unique provider identifier. */
45949
46173
  id = "opencode";
@@ -46038,15 +46262,12 @@ var init_adapter3 = __esm({
46038
46262
  };
46039
46263
  }
46040
46264
  let cliAvailable = false;
46041
- try {
46042
- const { stdout } = await execAsync10("which opencode");
46043
- cliAvailable = stdout.trim().length > 0;
46044
- details.cliPath = stdout.trim();
46045
- } catch {
46046
- details.cliAvailable = false;
46047
- }
46265
+ const resolvedCli = findOnPath10("opencode");
46266
+ cliAvailable = resolvedCli !== null;
46267
+ if (resolvedCli) details.cliPath = resolvedCli;
46268
+ else details.cliAvailable = false;
46048
46269
  if (this.projectDir) {
46049
- const openCodeConfigDir = join25(this.projectDir, ".opencode");
46270
+ const openCodeConfigDir = join26(this.projectDir, ".opencode");
46050
46271
  const configExists = existsSync18(openCodeConfigDir);
46051
46272
  details.configDirExists = configExists;
46052
46273
  }
@@ -46256,7 +46477,7 @@ var init_hooks4 = __esm({
46256
46477
  });
46257
46478
 
46258
46479
  // packages/adapters/src/providers/pi/install.ts
46259
- import { join as join26 } from "node:path";
46480
+ import { join as join27 } from "node:path";
46260
46481
  import { ensureProviderInstructionFile as ensureProviderInstructionFile7 } from "@cleocode/caamp";
46261
46482
  function getCleoReferences() {
46262
46483
  return [`@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`, "@.cleo/memory-bridge.md"];
@@ -46283,7 +46504,7 @@ var init_install4 = __esm({
46283
46504
  });
46284
46505
  const projectUpdated = projectResult.action !== "intact";
46285
46506
  if (projectUpdated) {
46286
- details.instructionFile = join26(projectDir, projectResult.instructFile);
46507
+ details.instructionFile = join27(projectDir, projectResult.instructFile);
46287
46508
  }
46288
46509
  let globalUpdated = false;
46289
46510
  try {
@@ -46354,40 +46575,30 @@ var init_install4 = __esm({
46354
46575
  });
46355
46576
 
46356
46577
  // packages/adapters/src/providers/pi/spawn.ts
46357
- import { exec as exec11, spawn as nodeSpawn5 } from "node:child_process";
46358
- import { unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
46359
- import { promisify as promisify12 } from "node:util";
46578
+ import { findOnPath as findOnPath11 } from "@cleocode/paths";
46360
46579
  function getPiCliPath() {
46361
46580
  return process.env["PI_CLI_PATH"] ?? "pi";
46362
46581
  }
46363
- var execAsync11, PiSpawnProvider;
46582
+ var PiSpawnProvider;
46364
46583
  var init_spawn4 = __esm({
46365
46584
  "packages/adapters/src/providers/pi/spawn.ts"() {
46366
46585
  "use strict";
46367
46586
  init_src();
46368
- execAsync11 = promisify12(exec11);
46587
+ init_cli_spawn();
46588
+ init_prompt_file();
46369
46589
  PiSpawnProvider = class {
46370
46590
  /** Map of instance IDs to tracked process info. */
46371
46591
  processMap = /* @__PURE__ */ new Map();
46372
46592
  /**
46373
46593
  * Check if the Pi CLI is available.
46374
46594
  *
46375
- * Checks `PI_CLI_PATH` env var first, then tries `which pi`.
46595
+ * Checks `PI_CLI_PATH` env var first, then searches PATH for `pi`.
46376
46596
  *
46377
46597
  * @returns true if the Pi CLI is accessible
46378
46598
  */
46379
46599
  async canSpawn() {
46380
46600
  const cliPath = getPiCliPath();
46381
- try {
46382
- if (cliPath !== "pi") {
46383
- const { stdout } = await execAsync11(`test -x "${cliPath}" && echo ok`);
46384
- return stdout.trim() === "ok";
46385
- }
46386
- await execAsync11("which pi");
46387
- return true;
46388
- } catch {
46389
- return false;
46390
- }
46601
+ return findOnPath11(cliPath) !== null;
46391
46602
  }
46392
46603
  /**
46393
46604
  * Spawn a subagent via Pi CLI.
@@ -46403,8 +46614,7 @@ var init_spawn4 = __esm({
46403
46614
  const startTime = (/* @__PURE__ */ new Date()).toISOString();
46404
46615
  let tmpFile;
46405
46616
  try {
46406
- tmpFile = `/tmp/pi-spawn-${instanceId}.txt`;
46407
- await writeFile3(tmpFile, context.prompt, "utf-8");
46617
+ tmpFile = await writeSpawnPromptFile("pi-spawn", context.prompt);
46408
46618
  const cliPath = getPiCliPath();
46409
46619
  const args = [tmpFile];
46410
46620
  const spawnOpts = {
@@ -46414,7 +46624,7 @@ var init_spawn4 = __esm({
46414
46624
  if (context.workingDirectory) {
46415
46625
  spawnOpts.cwd = context.workingDirectory;
46416
46626
  }
46417
- const child = nodeSpawn5(cliPath, args, spawnOpts);
46627
+ const child = spawnCli(cliPath, args, spawnOpts);
46418
46628
  child.unref();
46419
46629
  if (child.pid) {
46420
46630
  this.processMap.set(instanceId, {
@@ -46426,10 +46636,7 @@ var init_spawn4 = __esm({
46426
46636
  const capturedTmpFile = tmpFile;
46427
46637
  child.on("exit", async () => {
46428
46638
  this.processMap.delete(instanceId);
46429
- try {
46430
- await unlink2(capturedTmpFile);
46431
- } catch {
46432
- }
46639
+ await removeSpawnPromptFile(capturedTmpFile);
46433
46640
  });
46434
46641
  return {
46435
46642
  instanceId,
@@ -46441,10 +46648,7 @@ var init_spawn4 = __esm({
46441
46648
  } catch (error48) {
46442
46649
  console.error(`[PiSpawnProvider] Failed to spawn: ${getErrorMessage(error48)}`);
46443
46650
  if (tmpFile) {
46444
- try {
46445
- await unlink2(tmpFile);
46446
- } catch {
46447
- }
46651
+ await removeSpawnPromptFile(tmpFile);
46448
46652
  }
46449
46653
  return {
46450
46654
  instanceId,
@@ -46505,32 +46709,30 @@ var init_spawn4 = __esm({
46505
46709
  });
46506
46710
 
46507
46711
  // packages/adapters/src/providers/pi/adapter.ts
46508
- import { exec as exec12 } from "node:child_process";
46509
46712
  import { existsSync as existsSync19 } from "node:fs";
46510
- import { homedir as homedir13 } from "node:os";
46511
- import { join as join27 } from "node:path";
46512
- import { promisify as promisify13 } from "node:util";
46713
+ import { homedir as homedir12 } from "node:os";
46714
+ import { join as join28 } from "node:path";
46715
+ import { findOnPath as findOnPath12 } from "@cleocode/paths";
46513
46716
  function getPiAgentDir() {
46514
46717
  const env = process.env["PI_CODING_AGENT_DIR"];
46515
46718
  if (env !== void 0 && env.length > 0) {
46516
- if (env === "~") return homedir13();
46517
- if (env.startsWith("~/")) return join27(homedir13(), env.slice(2));
46719
+ if (env === "~") return homedir12();
46720
+ if (env.startsWith("~/")) return join28(homedir12(), env.slice(2));
46518
46721
  return env;
46519
46722
  }
46520
46723
  const piHome = process.env["PI_HOME"];
46521
46724
  if (piHome !== void 0 && piHome.length > 0) {
46522
- return join27(piHome, "agent");
46725
+ return join28(piHome, "agent");
46523
46726
  }
46524
- return join27(homedir13(), ".pi", "agent");
46727
+ return join28(homedir12(), ".pi", "agent");
46525
46728
  }
46526
- var execAsync12, PiAdapter;
46729
+ var PiAdapter;
46527
46730
  var init_adapter4 = __esm({
46528
46731
  "packages/adapters/src/providers/pi/adapter.ts"() {
46529
46732
  "use strict";
46530
46733
  init_hooks4();
46531
46734
  init_install4();
46532
46735
  init_spawn4();
46533
- execAsync12 = promisify13(exec12);
46534
46736
  PiAdapter = class {
46535
46737
  /** Unique provider identifier. */
46536
46738
  id = "pi";
@@ -46609,7 +46811,7 @@ var init_adapter4 = __esm({
46609
46811
  *
46610
46812
  * Checks:
46611
46813
  * 1. Adapter has been initialized
46612
- * 2. Pi CLI is available (via PI_CLI_PATH or `which pi`)
46814
+ * 2. Pi CLI is available (via PI_CLI_PATH or a PATH search for `pi`)
46613
46815
  * 3. Pi global state root (~/.pi/agent/ or PI_CODING_AGENT_DIR) exists
46614
46816
  *
46615
46817
  * @returns Health status with details about each check
@@ -46625,25 +46827,16 @@ var init_adapter4 = __esm({
46625
46827
  }
46626
46828
  let cliAvailable = false;
46627
46829
  const cliPath = process.env["PI_CLI_PATH"] ?? "pi";
46628
- try {
46629
- if (cliPath !== "pi") {
46630
- const { stdout } = await execAsync12(`test -x "${cliPath}" && echo ok`);
46631
- cliAvailable = stdout.trim() === "ok";
46632
- details.cliPath = cliPath;
46633
- } else {
46634
- const { stdout } = await execAsync12("which pi");
46635
- cliAvailable = stdout.trim().length > 0;
46636
- details.cliPath = stdout.trim();
46637
- }
46638
- } catch {
46639
- details.cliAvailable = false;
46640
- }
46830
+ const resolvedCli = findOnPath12(cliPath);
46831
+ cliAvailable = resolvedCli !== null;
46832
+ if (resolvedCli) details.cliPath = cliPath === "pi" ? resolvedCli : cliPath;
46833
+ else details.cliAvailable = false;
46641
46834
  const agentDir = getPiAgentDir();
46642
46835
  const agentDirExists = existsSync19(agentDir);
46643
46836
  details.agentDirExists = agentDirExists;
46644
46837
  details.agentDir = agentDir;
46645
46838
  if (this.projectDir) {
46646
- const projectPiDir = join27(this.projectDir, ".pi");
46839
+ const projectPiDir = join28(this.projectDir, ".pi");
46647
46840
  details.projectPiDirExists = existsSync19(projectPiDir);
46648
46841
  }
46649
46842
  details.piCodingAgentDirSet = process.env["PI_CODING_AGENT_DIR"] !== void 0;
@@ -46818,14 +47011,14 @@ var ClaudeSDKAdapter = class {
46818
47011
 
46819
47012
  // packages/adapters/src/providers/claude-sdk/mcp-registry.ts
46820
47013
  import { existsSync as existsSync9 } from "node:fs";
46821
- import { join as join11 } from "node:path";
47014
+ import { join as join12 } from "node:path";
46822
47015
  var CLEO_MCP_CANDIDATES = [
46823
47016
  { name: "brain", binary: "cleo-mcp-brain" },
46824
47017
  { name: "nexus", binary: "cleo-mcp-nexus" },
46825
47018
  { name: "tasks", binary: "cleo-mcp-tasks" }
46826
47019
  ];
46827
47020
  function findInNodeModules(binary, workingDir) {
46828
- const binPath = join11(workingDir, "node_modules", ".bin", binary);
47021
+ const binPath = join12(workingDir, "node_modules", ".bin", binary);
46829
47022
  if (existsSync9(binPath)) {
46830
47023
  return binPath;
46831
47024
  }
@@ -46855,19 +47048,18 @@ function createAdapter2() {
46855
47048
  }
46856
47049
 
46857
47050
  // packages/adapters/src/providers/codex/adapter.ts
46858
- import { exec as exec3 } from "node:child_process";
46859
47051
  import { existsSync as existsSync10 } from "node:fs";
46860
- import { homedir as homedir9 } from "node:os";
46861
- import { join as join15 } from "node:path";
46862
- import { promisify as promisify4 } from "node:util";
47052
+ import { homedir as homedir8 } from "node:os";
47053
+ import { join as join16 } from "node:path";
47054
+ import { findOnPath as findOnPath3 } from "@cleocode/paths";
46863
47055
 
46864
47056
  // packages/adapters/src/providers/codex/hooks.ts
46865
- import { homedir as homedir8 } from "node:os";
46866
- import { join as join13 } from "node:path";
47057
+ import { homedir as homedir7 } from "node:os";
47058
+ import { join as join14 } from "node:path";
46867
47059
 
46868
47060
  // packages/adapters/src/providers/shared/transcript-reader.ts
46869
47061
  import { readdir as readdir2, readFile as readFile3 } from "node:fs/promises";
46870
- import { join as join12 } from "node:path";
47062
+ import { join as join13 } from "node:path";
46871
47063
  function parseTranscriptLines(raw) {
46872
47064
  const turns = [];
46873
47065
  const lines = raw.split("\n").filter((l) => l.trim());
@@ -46892,7 +47084,7 @@ async function readLatestTranscript(providerDir) {
46892
47084
  if (!entry.isFile()) continue;
46893
47085
  const name15 = entry.name;
46894
47086
  if (name15.endsWith(".json") || name15.endsWith(".jsonl")) {
46895
- allFiles.push(join12(providerDir, name15));
47087
+ allFiles.push(join13(providerDir, name15));
46896
47088
  }
46897
47089
  }
46898
47090
  } catch {
@@ -46982,13 +47174,13 @@ var CodexHookProvider = class {
46982
47174
  * @task T162 @epic T134
46983
47175
  */
46984
47176
  async getTranscript(_sessionId, _projectDir) {
46985
- return readLatestTranscript(join13(homedir8(), ".codex"));
47177
+ return readLatestTranscript(join14(homedir7(), ".codex"));
46986
47178
  }
46987
47179
  };
46988
47180
 
46989
47181
  // packages/adapters/src/providers/codex/install.ts
46990
47182
  init_paths2();
46991
- import { join as join14 } from "node:path";
47183
+ import { join as join15 } from "node:path";
46992
47184
  import { ensureProviderInstructionFile as ensureProviderInstructionFile2 } from "@cleocode/caamp";
46993
47185
  var CodexInstallProvider = class {
46994
47186
  /**
@@ -47008,7 +47200,7 @@ var CodexInstallProvider = class {
47008
47200
  });
47009
47201
  const instructionFileUpdated = result.action !== "intact";
47010
47202
  if (instructionFileUpdated) {
47011
- details.instructionFile = join14(projectDir, result.instructFile);
47203
+ details.instructionFile = join15(projectDir, result.instructFile);
47012
47204
  }
47013
47205
  return {
47014
47206
  success: true,
@@ -47062,7 +47254,6 @@ var CodexInstallProvider = class {
47062
47254
  };
47063
47255
 
47064
47256
  // packages/adapters/src/providers/codex/adapter.ts
47065
- var execAsync3 = promisify4(exec3);
47066
47257
  var CodexAdapter = class {
47067
47258
  /** Unique provider identifier. */
47068
47259
  id = "codex";
@@ -47139,14 +47330,11 @@ var CodexAdapter = class {
47139
47330
  };
47140
47331
  }
47141
47332
  let cliAvailable = false;
47142
- try {
47143
- const { stdout } = await execAsync3("which codex");
47144
- cliAvailable = stdout.trim().length > 0;
47145
- details.cliPath = stdout.trim();
47146
- } catch {
47147
- details.cliAvailable = false;
47148
- }
47149
- const codexConfigDir = join15(homedir9(), ".codex");
47333
+ const resolvedCli = findOnPath3("codex");
47334
+ cliAvailable = resolvedCli !== null;
47335
+ if (resolvedCli) details.cliPath = resolvedCli;
47336
+ else details.cliAvailable = false;
47337
+ const codexConfigDir = join16(homedir8(), ".codex");
47150
47338
  const configExists = existsSync10(codexConfigDir);
47151
47339
  details.configDirExists = configExists;
47152
47340
  const healthy = cliAvailable;
@@ -47174,10 +47362,10 @@ var CodexAdapter = class {
47174
47362
  };
47175
47363
 
47176
47364
  // packages/adapters/src/providers/codex/spawn.ts
47177
- import { exec as exec4, spawn as nodeSpawn2 } from "node:child_process";
47178
47365
  init_src();
47179
- import { promisify as promisify5 } from "node:util";
47180
- var execAsync4 = promisify5(exec4);
47366
+ init_cli_spawn();
47367
+ init_prompt_file();
47368
+ import { findOnPath as findOnPath4 } from "@cleocode/paths";
47181
47369
 
47182
47370
  // packages/adapters/src/providers/codex/index.ts
47183
47371
  function createAdapter3() {
@@ -47188,15 +47376,14 @@ function createAdapter3() {
47188
47376
  init_cursor();
47189
47377
 
47190
47378
  // packages/adapters/src/providers/gemini-cli/adapter.ts
47191
- import { exec as exec5 } from "node:child_process";
47192
47379
  import { existsSync as existsSync14 } from "node:fs";
47193
- import { homedir as homedir11 } from "node:os";
47194
- import { join as join20 } from "node:path";
47195
- import { promisify as promisify6 } from "node:util";
47380
+ import { homedir as homedir10 } from "node:os";
47381
+ import { join as join21 } from "node:path";
47382
+ import { findOnPath as findOnPath5 } from "@cleocode/paths";
47196
47383
 
47197
47384
  // packages/adapters/src/providers/gemini-cli/hooks.ts
47198
- import { homedir as homedir10 } from "node:os";
47199
- import { join as join18 } from "node:path";
47385
+ import { homedir as homedir9 } from "node:os";
47386
+ import { join as join19 } from "node:path";
47200
47387
  var GEMINI_CLI_EVENT_MAP = {
47201
47388
  SessionStart: "SessionStart",
47202
47389
  SessionEnd: "SessionEnd",
@@ -47274,14 +47461,14 @@ var GeminiCliHookProvider = class {
47274
47461
  * @task T161 @epic T134
47275
47462
  */
47276
47463
  async getTranscript(_sessionId, _projectDir) {
47277
- return readLatestTranscript(join18(homedir10(), ".gemini"));
47464
+ return readLatestTranscript(join19(homedir9(), ".gemini"));
47278
47465
  }
47279
47466
  };
47280
47467
 
47281
47468
  // packages/adapters/src/providers/gemini-cli/install.ts
47282
47469
  init_paths2();
47283
47470
  import { existsSync as existsSync13, readFileSync as readFileSync8 } from "node:fs";
47284
- import { join as join19 } from "node:path";
47471
+ import { join as join20 } from "node:path";
47285
47472
  import { ensureProviderInstructionFile as ensureProviderInstructionFile4 } from "@cleocode/caamp";
47286
47473
  var GeminiCliInstallProvider = class {
47287
47474
  /**
@@ -47326,7 +47513,7 @@ var GeminiCliInstallProvider = class {
47326
47513
  */
47327
47514
  async isInstalled() {
47328
47515
  const instructionRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
47329
- const geminiMdPath = join19(process.cwd(), "GEMINI.md");
47516
+ const geminiMdPath = join20(process.cwd(), "GEMINI.md");
47330
47517
  if (existsSync13(geminiMdPath)) {
47331
47518
  try {
47332
47519
  const content = readFileSync8(geminiMdPath, "utf-8");
@@ -47355,7 +47542,6 @@ var GeminiCliInstallProvider = class {
47355
47542
  };
47356
47543
 
47357
47544
  // packages/adapters/src/providers/gemini-cli/adapter.ts
47358
- var execAsync5 = promisify6(exec5);
47359
47545
  var GeminiCliAdapter = class {
47360
47546
  /** Unique provider identifier. */
47361
47547
  id = "gemini-cli";
@@ -47443,14 +47629,11 @@ var GeminiCliAdapter = class {
47443
47629
  };
47444
47630
  }
47445
47631
  let cliAvailable = false;
47446
- try {
47447
- const { stdout } = await execAsync5("which gemini");
47448
- cliAvailable = stdout.trim().length > 0;
47449
- details.cliPath = stdout.trim();
47450
- } catch {
47451
- details.cliAvailable = false;
47452
- }
47453
- const geminiConfigDir = join20(homedir11(), ".gemini");
47632
+ const resolvedCli = findOnPath5("gemini");
47633
+ cliAvailable = resolvedCli !== null;
47634
+ if (resolvedCli) details.cliPath = resolvedCli;
47635
+ else details.cliAvailable = false;
47636
+ const geminiConfigDir = join21(homedir10(), ".gemini");
47454
47637
  const configExists = existsSync14(geminiConfigDir);
47455
47638
  details.configDirExists = configExists;
47456
47639
  const healthy = cliAvailable;
@@ -47479,9 +47662,8 @@ var GeminiCliAdapter = class {
47479
47662
 
47480
47663
  // packages/adapters/src/providers/gemini-cli/spawn.ts
47481
47664
  init_src();
47482
- import { exec as exec6, spawn as nodeSpawn3 } from "node:child_process";
47483
- import { promisify as promisify7 } from "node:util";
47484
- var execAsync6 = promisify7(exec6);
47665
+ init_cli_spawn();
47666
+ import { findOnPath as findOnPath6 } from "@cleocode/paths";
47485
47667
 
47486
47668
  // packages/adapters/src/providers/gemini-cli/index.ts
47487
47669
  function createAdapter5() {
@@ -47489,11 +47671,10 @@ function createAdapter5() {
47489
47671
  }
47490
47672
 
47491
47673
  // packages/adapters/src/providers/kimi/adapter.ts
47492
- import { exec as exec7 } from "node:child_process";
47493
47674
  import { existsSync as existsSync16 } from "node:fs";
47494
- import { homedir as homedir12 } from "node:os";
47495
- import { join as join22 } from "node:path";
47496
- import { promisify as promisify8 } from "node:util";
47675
+ import { homedir as homedir11 } from "node:os";
47676
+ import { join as join23 } from "node:path";
47677
+ import { findOnPath as findOnPath7 } from "@cleocode/paths";
47497
47678
 
47498
47679
  // packages/adapters/src/providers/kimi/hooks.ts
47499
47680
  var KimiHookProvider = class {
@@ -47553,7 +47734,7 @@ var KimiHookProvider = class {
47553
47734
  // packages/adapters/src/providers/kimi/install.ts
47554
47735
  init_paths2();
47555
47736
  import { existsSync as existsSync15, readFileSync as readFileSync9 } from "node:fs";
47556
- import { join as join21 } from "node:path";
47737
+ import { join as join22 } from "node:path";
47557
47738
  import { ensureProviderInstructionFile as ensureProviderInstructionFile5 } from "@cleocode/caamp";
47558
47739
  var KimiInstallProvider = class {
47559
47740
  /**
@@ -47598,7 +47779,7 @@ var KimiInstallProvider = class {
47598
47779
  */
47599
47780
  async isInstalled() {
47600
47781
  const instructionRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
47601
- const agentsMdPath = join21(process.cwd(), "AGENTS.md");
47782
+ const agentsMdPath = join22(process.cwd(), "AGENTS.md");
47602
47783
  if (existsSync15(agentsMdPath)) {
47603
47784
  try {
47604
47785
  const content = readFileSync9(agentsMdPath, "utf-8");
@@ -47627,7 +47808,6 @@ var KimiInstallProvider = class {
47627
47808
  };
47628
47809
 
47629
47810
  // packages/adapters/src/providers/kimi/adapter.ts
47630
- var execAsync7 = promisify8(exec7);
47631
47811
  var KimiAdapter = class {
47632
47812
  /** Unique provider identifier. */
47633
47813
  id = "kimi";
@@ -47702,14 +47882,11 @@ var KimiAdapter = class {
47702
47882
  };
47703
47883
  }
47704
47884
  let cliAvailable = false;
47705
- try {
47706
- const { stdout } = await execAsync7("which kimi");
47707
- cliAvailable = stdout.trim().length > 0;
47708
- details.cliPath = stdout.trim();
47709
- } catch {
47710
- details.cliAvailable = false;
47711
- }
47712
- const kimiConfigDir = join22(homedir12(), ".kimi");
47885
+ const resolvedCli = findOnPath7("kimi");
47886
+ cliAvailable = resolvedCli !== null;
47887
+ if (resolvedCli) details.cliPath = resolvedCli;
47888
+ else details.cliAvailable = false;
47889
+ const kimiConfigDir = join23(homedir11(), ".kimi");
47713
47890
  const configExists = existsSync16(kimiConfigDir);
47714
47891
  details.configDirExists = configExists;
47715
47892
  const healthy = cliAvailable;
@@ -47738,9 +47915,7 @@ var KimiAdapter = class {
47738
47915
 
47739
47916
  // packages/adapters/src/providers/kimi/spawn.ts
47740
47917
  init_src();
47741
- import { exec as exec8 } from "node:child_process";
47742
- import { promisify as promisify9 } from "node:util";
47743
- var execAsync8 = promisify9(exec8);
47918
+ import { findOnPath as findOnPath8 } from "@cleocode/paths";
47744
47919
 
47745
47920
  // packages/adapters/src/providers/kimi/index.ts
47746
47921
  function createAdapter6() {
@@ -47753,15 +47928,15 @@ init_hook_template_installer();
47753
47928
 
47754
47929
  // packages/adapters/src/registry.ts
47755
47930
  import { readFileSync as readFileSync11 } from "node:fs";
47756
- import { dirname as dirname4, join as join28, resolve as resolve2 } from "node:path";
47931
+ import { dirname as dirname5, join as join29, resolve as resolve2 } from "node:path";
47757
47932
  import { fileURLToPath as fileURLToPath3 } from "node:url";
47758
47933
  var PROVIDER_IDS = ["claude-code", "opencode", "cursor", "pi"];
47759
47934
  function getProviderManifests() {
47760
47935
  const manifests = [];
47761
- const baseDir = resolve2(dirname4(fileURLToPath3(import.meta.url)), "providers");
47936
+ const baseDir = resolve2(dirname5(fileURLToPath3(import.meta.url)), "providers");
47762
47937
  for (const providerId of PROVIDER_IDS) {
47763
47938
  try {
47764
- const manifestPath = join28(baseDir, providerId, "manifest.json");
47939
+ const manifestPath = join29(baseDir, providerId, "manifest.json");
47765
47940
  const raw = readFileSync11(manifestPath, "utf-8");
47766
47941
  manifests.push(JSON.parse(raw));
47767
47942
  } catch {