@citeark/agent 0.3.20

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 (347) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +128 -0
  3. package/data/dataset-source-registry.v1.json +300 -0
  4. package/dist/arkgraph/boot.js +6 -0
  5. package/dist/arkgraph/index.html +1 -0
  6. package/dist/arkgraph/viewer.css +1 -0
  7. package/dist/arkgraph/viewer.en.css +1 -0
  8. package/dist/arkgraph/viewer.en.js +49 -0
  9. package/dist/arkgraph/viewer.en.js.LEGAL.txt +56 -0
  10. package/dist/arkgraph/viewer.js +49 -0
  11. package/dist/arkgraph/viewer.js.LEGAL.txt +56 -0
  12. package/docker/claude-code/Dockerfile +97 -0
  13. package/docker/claude-code/codex-pro-relay.mjs +466 -0
  14. package/docker/claude-code/runtime-contract-check.mjs +79 -0
  15. package/docs/arkgraph-reading.md +79 -0
  16. package/docs/configuration.md +100 -0
  17. package/docs/integration.md +92 -0
  18. package/docs/maturity-plan.md +27 -0
  19. package/docs/npm-release.md +44 -0
  20. package/docs/paper-reading.md +40 -0
  21. package/docs/research-plan-granularity.md +27 -0
  22. package/docs/terminal.md +49 -0
  23. package/examples/toy-evaluation/compile-task.json +27 -0
  24. package/examples/toy-evaluation/paper.md +5 -0
  25. package/examples/toy-evaluation/repository/README.md +9 -0
  26. package/examples/toy-evaluation/repository/checkpoint.json +4 -0
  27. package/examples/toy-evaluation/repository/evaluate.py +17 -0
  28. package/examples/toy-evaluation/task.json +81 -0
  29. package/package.json +59 -0
  30. package/prompts/compile-research.md +58 -0
  31. package/prompts/execute-contract.md +72 -0
  32. package/prompts/execute-workspace-simple.md +51 -0
  33. package/prompts/execute-workspace.md +34 -0
  34. package/prompts/prepare-reproduction.md +82 -0
  35. package/prompts/repair-research.md +45 -0
  36. package/protocol/CAP.md +129 -0
  37. package/protocol/LICENSE +12 -0
  38. package/protocol/MAPPINGS.md +72 -0
  39. package/protocol/README.md +38 -0
  40. package/protocol/conformance-v2.0-alpha.1.json +36 -0
  41. package/protocol/examples/arkgraph/checkpoint-evaluation.json +309 -0
  42. package/protocol/examples/arkgraph/fixtures.mjs +49 -0
  43. package/protocol/examples/arkgraph/paper-free.json +291 -0
  44. package/protocol/examples/arkgraph/partial-failure.json +344 -0
  45. package/protocol/examples/arkgraph/training-evaluation.json +443 -0
  46. package/protocol/profiles/agent-trace.md +16 -0
  47. package/protocol/profiles/computational-run.md +16 -0
  48. package/protocol/profiles/core.md +15 -0
  49. package/protocol/profiles/public-bundle.md +18 -0
  50. package/protocol/profiles/reproduction.md +29 -0
  51. package/protocol/profiles/research-compilation.md +44 -0
  52. package/protocol/profiles/research-plan.md +39 -0
  53. package/protocol/profiles/restricted-evidence.md +15 -0
  54. package/runtime/bootstrap-autodl-runtime.sh +314 -0
  55. package/runtime/create-runtime-venv.sh +41 -0
  56. package/runtime/install-local-cpu-runtime.sh +23 -0
  57. package/runtime/install-scientific-runtime.sh +153 -0
  58. package/runtime/mineru/parse.py +62 -0
  59. package/runtime/mineru/requirements.txt +4 -0
  60. package/runtime/requirements-baseline.txt +38 -0
  61. package/schemas/cap/v2/activity.schema.json +47 -0
  62. package/schemas/cap/v2/agent.schema.json +32 -0
  63. package/schemas/cap/v2/assertion.schema.json +110 -0
  64. package/schemas/cap/v2/descriptor.schema.json +243 -0
  65. package/schemas/cap/v2/entity.schema.json +64 -0
  66. package/schemas/cap/v2/manifest.schema.json +67 -0
  67. package/schemas/cap/v2/relation.schema.json +82 -0
  68. package/schemas/compute-catalog.schema.json +63 -0
  69. package/schemas/compute-decision.schema.json +27 -0
  70. package/schemas/execution-contract.schema.json +1024 -0
  71. package/schemas/research-card.schema.json +30 -0
  72. package/schemas/research-inventory-draft.schema.json +366 -0
  73. package/schemas/research.schema.json +1044 -0
  74. package/schemas/result.schema.json +173 -0
  75. package/schemas/verification-policy.schema.json +47 -0
  76. package/schemas/verified-conclusion.schema.json +58 -0
  77. package/schemas/workspace-summary.schema.json +24 -0
  78. package/scripts/build-arkgraph-view.mjs +12 -0
  79. package/scripts/check-execution-feasibility.mjs +24 -0
  80. package/scripts/check-syntax.mjs +15 -0
  81. package/scripts/deterministic-asset-preparation.py +438 -0
  82. package/scripts/package-cap.mjs +23 -0
  83. package/scripts/package-local-agent.mjs +23 -0
  84. package/scripts/preview-arkgraph.mjs +25 -0
  85. package/scripts/replay-research-compiler-candidate.mjs +134 -0
  86. package/scripts/review-compiler-sources.mjs +44 -0
  87. package/scripts/run-asset-preparation.sh +17 -0
  88. package/scripts/run-research-plan.mjs +98 -0
  89. package/scripts/validate-asset-preparation.py +290 -0
  90. package/scripts/verify-local-runtime.mjs +57 -0
  91. package/scripts/verify-npm-package.mjs +57 -0
  92. package/src/adapters/paper2agent.mjs +107 -0
  93. package/src/assets/cache.mjs +159 -0
  94. package/src/assets/compute.mjs +98 -0
  95. package/src/assets/executor.mjs +145 -0
  96. package/src/assets/lifecycle.mjs +213 -0
  97. package/src/assets/manifest.mjs +242 -0
  98. package/src/assets/opportunistic-preparation.mjs +81 -0
  99. package/src/assets/plan.mjs +411 -0
  100. package/src/assets/prompts.mjs +29 -0
  101. package/src/assets/public-asset-probe.mjs +525 -0
  102. package/src/assets/qualification.mjs +119 -0
  103. package/src/assets/readiness.mjs +130 -0
  104. package/src/assets/reproduction-admission.mjs +355 -0
  105. package/src/assets/requirements.mjs +152 -0
  106. package/src/assets/source-grounding.mjs +341 -0
  107. package/src/assets/source-policy.mjs +118 -0
  108. package/src/autodl/client.mjs +260 -0
  109. package/src/autodl/ssh.mjs +380 -0
  110. package/src/autodl/tools.mjs +129 -0
  111. package/src/cap/redaction.mjs +38 -0
  112. package/src/cap/v2/archive.mjs +152 -0
  113. package/src/cap/v2/attestation.mjs +204 -0
  114. package/src/cap/v2/canonical-json.mjs +114 -0
  115. package/src/cap/v2/compilation-artifact.mjs +240 -0
  116. package/src/cap/v2/core.mjs +282 -0
  117. package/src/cap/v2/measurement-assessment-records.mjs +23 -0
  118. package/src/cap/v2/pipeline-artifact.mjs +922 -0
  119. package/src/cap/v2/read.mjs +41 -0
  120. package/src/cap/v2/reassessment-artifact.mjs +383 -0
  121. package/src/cap/v2/research-artifact.mjs +231 -0
  122. package/src/cap/v2/research-map-records.mjs +46 -0
  123. package/src/cap/v2/research-object-records.mjs +163 -0
  124. package/src/cap/v2/research-records.mjs +187 -0
  125. package/src/cap/v2/verify.mjs +642 -0
  126. package/src/cli.mjs +1146 -0
  127. package/src/compute/autodl-pro-compiler.mjs +347 -0
  128. package/src/compute/autodl-pro-executor.mjs +459 -0
  129. package/src/compute/autodl-pro-job.mjs +843 -0
  130. package/src/compute/autodl-pro-network.mjs +295 -0
  131. package/src/compute/autodl-pro-remote.mjs +810 -0
  132. package/src/compute/autodl-pro-staging.mjs +117 -0
  133. package/src/compute/campaign.mjs +110 -0
  134. package/src/compute/catalog.mjs +123 -0
  135. package/src/compute/checkpoint-protocol.mjs +154 -0
  136. package/src/compute/codex-account-lock.mjs +111 -0
  137. package/src/compute/codex-account-session.mjs +107 -0
  138. package/src/compute/compiler-profile.mjs +38 -0
  139. package/src/compute/compiler-router.mjs +23 -0
  140. package/src/compute/coordinator-recovery.mjs +210 -0
  141. package/src/compute/executor-router.mjs +29 -0
  142. package/src/compute/gcp-batch-compiler.mjs +685 -0
  143. package/src/compute/gcp-batch-executor.mjs +1215 -0
  144. package/src/compute/gcp-batch-failure.mjs +92 -0
  145. package/src/compute/gcp-batch-job.mjs +527 -0
  146. package/src/compute/gcp-batch-lifecycle.mjs +81 -0
  147. package/src/compute/gcp-checkpoint-worker.mjs +1633 -0
  148. package/src/compute/local-codex-compiler.mjs +52 -0
  149. package/src/compute/measurement-hardware.mjs +128 -0
  150. package/src/compute/remote-attempt.mjs +226 -0
  151. package/src/compute/requirements.mjs +124 -0
  152. package/src/compute/research-phases.mjs +48 -0
  153. package/src/compute/scheduler.mjs +452 -0
  154. package/src/compute/shared-workloads.mjs +26 -0
  155. package/src/compute/stage-archive.mjs +79 -0
  156. package/src/contracts/campaign-contract.mjs +52 -0
  157. package/src/contracts/execution-contract.mjs +819 -0
  158. package/src/contracts/execution-mode.mjs +19 -0
  159. package/src/contracts/execution-timeouts.mjs +45 -0
  160. package/src/contracts/execution-workload.mjs +68 -0
  161. package/src/contracts/preflight-schema.mjs +25 -0
  162. package/src/contracts/public-contract.mjs +63 -0
  163. package/src/contracts/subject-tags.mjs +31 -0
  164. package/src/dashboard/data.mjs +898 -0
  165. package/src/dashboard/server.mjs +79 -0
  166. package/src/dashboard/static/dashboard.css +366 -0
  167. package/src/dashboard/static/dashboard.js +560 -0
  168. package/src/dashboard/static/index.html +85 -0
  169. package/src/deployment/community-policy.mjs +9 -0
  170. package/src/deployment/environment.mjs +112 -0
  171. package/src/deployment/guided.mjs +98 -0
  172. package/src/deployment/handoff.mjs +102 -0
  173. package/src/deployment/local-contract.mjs +31 -0
  174. package/src/deployment/local.mjs +100 -0
  175. package/src/deployment/prepare.mjs +46 -0
  176. package/src/deployment/recipe.mjs +108 -0
  177. package/src/deployment/supplement.mjs +51 -0
  178. package/src/deployment/terminal.mjs +43 -0
  179. package/src/diagnosis/renderer.mjs +75 -0
  180. package/src/diagnosis/target-failure.mjs +46 -0
  181. package/src/evidence/parser-registry.mjs +54 -0
  182. package/src/evidence/parsers/fasttext-classification.mjs +82 -0
  183. package/src/evidence/parsers/json-scalar.mjs +96 -0
  184. package/src/evidence/parsers/simcse-senteval.mjs +104 -0
  185. package/src/evidence/parsers/starspace-classification.mjs +78 -0
  186. package/src/evidence/registry.mjs +147 -0
  187. package/src/execution/runner-audit.mjs +473 -0
  188. package/src/gcp/auth.mjs +106 -0
  189. package/src/gcp/batch-client.mjs +120 -0
  190. package/src/gcp/resource-discovery.mjs +177 -0
  191. package/src/gcp/rest.mjs +82 -0
  192. package/src/gcp/secret-manager.mjs +34 -0
  193. package/src/gcp/signed-url.mjs +133 -0
  194. package/src/gcp/storage.mjs +220 -0
  195. package/src/graph/command.mjs +41 -0
  196. package/src/graph/execution.mjs +97 -0
  197. package/src/graph/model.mjs +37 -0
  198. package/src/graph/presentation.mjs +110 -0
  199. package/src/graph/query.mjs +159 -0
  200. package/src/graph/research-relations.mjs +69 -0
  201. package/src/graph/source-page.mjs +12 -0
  202. package/src/graph/source-preview.mjs +34 -0
  203. package/src/graph/validate.mjs +76 -0
  204. package/src/job.mjs +496 -0
  205. package/src/network/autodl-routing-proxy.mjs +462 -0
  206. package/src/network/egress-proxy.mjs +158 -0
  207. package/src/observability/event-contract.mjs +230 -0
  208. package/src/observability/pipeline-monitor.mjs +166 -0
  209. package/src/pipeline/orchestrator.mjs +1281 -0
  210. package/src/pipeline/recovery-error.mjs +11 -0
  211. package/src/pipeline/replay.mjs +304 -0
  212. package/src/pipeline/shared-execution.mjs +115 -0
  213. package/src/pipeline/stage-checkpoint.mjs +86 -0
  214. package/src/pipeline/stage-recovery.mjs +101 -0
  215. package/src/pipeline/targets.mjs +110 -0
  216. package/src/process.mjs +143 -0
  217. package/src/protocol.mjs +312 -0
  218. package/src/provider/codex-account.mjs +44 -0
  219. package/src/provider/codex-completion.mjs +49 -0
  220. package/src/provider/completion.mjs +292 -0
  221. package/src/provider/model-client.mjs +44 -0
  222. package/src/provider/model-route.mjs +29 -0
  223. package/src/provider/openrouter-readiness.mjs +189 -0
  224. package/src/provider/reader-bridge.mjs +35 -0
  225. package/src/provider/relay.mjs +263 -0
  226. package/src/provider/runtime-auth.mjs +40 -0
  227. package/src/public/cap.d.mts +90 -0
  228. package/src/public/cap.mjs +12 -0
  229. package/src/public/contracts.d.mts +2 -0
  230. package/src/public/host.mjs +171 -0
  231. package/src/public/operations.d.mts +11 -0
  232. package/src/public/presentation.d.mts +4 -0
  233. package/src/records/views.mjs +26 -0
  234. package/src/remote/command.mjs +178 -0
  235. package/src/remote/ssh.mjs +59 -0
  236. package/src/repository-origin.mjs +81 -0
  237. package/src/reproduction/evidence-feedback.mjs +96 -0
  238. package/src/reproduction/incomplete-initialization.mjs +25 -0
  239. package/src/reproduction/lifecycle.mjs +253 -0
  240. package/src/reproduction/plan.mjs +132 -0
  241. package/src/reproduction/prompts.mjs +70 -0
  242. package/src/reproduction/runner.mjs +188 -0
  243. package/src/reproduction/summary.mjs +130 -0
  244. package/src/reproduction/workspace-mode.mjs +7 -0
  245. package/src/research/automatic-admission.mjs +156 -0
  246. package/src/research/compiler-coverage.mjs +85 -0
  247. package/src/research/compiler-failure.mjs +24 -0
  248. package/src/research/compiler-normalization-guards.mjs +112 -0
  249. package/src/research/compiler-repair.mjs +3 -0
  250. package/src/research/compiler.mjs +853 -0
  251. package/src/research/continuation-selection.mjs +26 -0
  252. package/src/research/execution-graph-context.mjs +43 -0
  253. package/src/research/experiment-importance.mjs +15 -0
  254. package/src/research/inventory-handoff.mjs +104 -0
  255. package/src/research/inventory-revisions.mjs +32 -0
  256. package/src/research/mineru-local.mjs +73 -0
  257. package/src/research/paper-command.mjs +19 -0
  258. package/src/research/paper-markdown.mjs +180 -0
  259. package/src/research/paper-source-map.mjs +69 -0
  260. package/src/research/planning-policy.mjs +88 -0
  261. package/src/research/reference-materials.mjs +11 -0
  262. package/src/research/reproduction-scope.mjs +30 -0
  263. package/src/research/research-map.mjs +94 -0
  264. package/src/research/research-objects.mjs +88 -0
  265. package/src/research/source-discovery.mjs +646 -0
  266. package/src/research/source-observations.mjs +75 -0
  267. package/src/research/source-review-cli-mcp.mjs +26 -0
  268. package/src/research/source-review-input.mjs +209 -0
  269. package/src/research/source-review-local-codex.mjs +36 -0
  270. package/src/research/source-review-model.mjs +70 -0
  271. package/src/research/source-review.mjs +173 -0
  272. package/src/research/structure.mjs +3163 -0
  273. package/src/research-card/renderer.mjs +277 -0
  274. package/src/research-card/verified-conclusion.mjs +143 -0
  275. package/src/results/output-registry.mjs +183 -0
  276. package/src/runtime/claude-code.mjs +52 -0
  277. package/src/runtime/codex-capacity-retry.mjs +87 -0
  278. package/src/runtime/codex.mjs +64 -0
  279. package/src/runtime/config.mjs +157 -0
  280. package/src/runtime/final-output.mjs +40 -0
  281. package/src/runtime/index.mjs +21 -0
  282. package/src/runtime/local-codex.mjs +74 -0
  283. package/src/runtime/opencode.mjs +95 -0
  284. package/src/runtime/prompt.mjs +13 -0
  285. package/src/sandbox/docker.mjs +363 -0
  286. package/src/settings/command.mjs +297 -0
  287. package/src/settings/store.mjs +119 -0
  288. package/src/telemetry/pricing.mjs +68 -0
  289. package/src/telemetry/usage.mjs +265 -0
  290. package/src/terminal/events.mjs +97 -0
  291. package/src/terminal/input.mjs +40 -0
  292. package/src/terminal/plain.mjs +40 -0
  293. package/src/terminal/remote-stream.mjs +22 -0
  294. package/src/terminal/screen.mjs +214 -0
  295. package/src/terminal/transcript.mjs +69 -0
  296. package/src/util.mjs +107 -0
  297. package/src/verification/ai-assessor.mjs +534 -0
  298. package/src/verification/claim-evaluator.mjs +242 -0
  299. package/src/verification/evidence-context.mjs +165 -0
  300. package/src/verification/evidence-reader.mjs +95 -0
  301. package/src/verification/integrity.mjs +570 -0
  302. package/src/verification/tolerance.mjs +32 -0
  303. package/src/workloads/cpu-research-preparation.mjs +56 -0
  304. package/src/workloads/definition.mjs +74 -0
  305. package/src/workloads/phase-aware-reproduction.mjs +46 -0
  306. package/src/workloads/reproduction.mjs +85 -0
  307. package/src/workspace/command.mjs +242 -0
  308. package/src/workspace/control.mjs +49 -0
  309. package/src/workspace/entry.mjs +28 -0
  310. package/src/workspace/input.mjs +93 -0
  311. package/src/workspace/interactive.mjs +94 -0
  312. package/src/workspace/jobs.mjs +418 -0
  313. package/src/workspace/session.mjs +97 -0
  314. package/src/workspace/worker.mjs +137 -0
  315. package/ui/arkgraph/ambient-motion.mjs +10 -0
  316. package/ui/arkgraph/app.jsx +153 -0
  317. package/ui/arkgraph/boot.js +6 -0
  318. package/ui/arkgraph/camera-motion.mjs +20 -0
  319. package/ui/arkgraph/context-reveal.mjs +39 -0
  320. package/ui/arkgraph/details.css +3 -0
  321. package/ui/arkgraph/entry.jsx +28 -0
  322. package/ui/arkgraph/experiment-curves.mjs +17 -0
  323. package/ui/arkgraph/experiment-selection.mjs +15 -0
  324. package/ui/arkgraph/experiment-style.css +26 -0
  325. package/ui/arkgraph/experiment-ui.jsx +32 -0
  326. package/ui/arkgraph/frame.html +1 -0
  327. package/ui/arkgraph/graph-gestures.mjs +62 -0
  328. package/ui/arkgraph/label-layout.mjs +57 -0
  329. package/ui/arkgraph/locales/en.json +229 -0
  330. package/ui/arkgraph/locales/source-types.json +15 -0
  331. package/ui/arkgraph/localization-build.mjs +27 -0
  332. package/ui/arkgraph/material-build.mjs +23 -0
  333. package/ui/arkgraph/material-colors.mjs +39 -0
  334. package/ui/arkgraph/material-style.css +15 -0
  335. package/ui/arkgraph/open-graph.jsx +326 -0
  336. package/ui/arkgraph/outline.jsx +49 -0
  337. package/ui/arkgraph/package-lock.json +888 -0
  338. package/ui/arkgraph/package.json +17 -0
  339. package/ui/arkgraph/reading-layout.mjs +130 -0
  340. package/ui/arkgraph/reading-presentation.mjs +73 -0
  341. package/ui/arkgraph/record-detail.css +51 -0
  342. package/ui/arkgraph/record-details.jsx +29 -0
  343. package/ui/arkgraph/research-types.mjs +31 -0
  344. package/ui/arkgraph/selection-mark.jsx +6 -0
  345. package/ui/arkgraph/soft-spine.mjs +26 -0
  346. package/ui/arkgraph/steering-style.css +187 -0
  347. package/ui/arkgraph/style.css +272 -0
@@ -0,0 +1,363 @@
1
+ import { recordResearchCleanup } from '../workspace/control.mjs';
2
+ import { hasSessionEvents, createRuntimeStream } from '../terminal/events.mjs';
3
+ import path from "node:path";
4
+
5
+ import {
6
+ recordRunnerProcessFinished,
7
+ recordRunnerProcessStarted,
8
+ } from "../execution/runner-audit.mjs";
9
+ import { captureProcess, runProcess } from "../process.mjs";
10
+ import { previewProviderSession } from "../provider/relay.mjs";
11
+ import { openCodeModelDefinition } from "../runtime/opencode.mjs";
12
+ import { CiteArkError, printableCommand, writeJson, readJson, pathExists } from "../util.mjs";
13
+
14
+ export function buildDockerRun({
15
+ bundle,
16
+ runtimeCommand,
17
+ runtimeArgs,
18
+ attempt,
19
+ providerSession = previewProviderSession(bundle.runtimeAgent),
20
+ egressSession,
21
+ }) {
22
+ const agent = bundle.runtimeAgent;
23
+ const environment = bundle.executionEnvironment ?? bundle.runtimeTask.environment;
24
+ const containerName = `${bundle.runId}-a${attempt}`
25
+ .toLowerCase()
26
+ .replaceAll(/[^a-z0-9_.-]/g, "-")
27
+ .slice(0, 63);
28
+ const containerUser = `${process.getuid?.() ?? 1000}:${process.getgid?.() ?? 1000}`;
29
+ const args = [
30
+ "run",
31
+ "--rm",
32
+ "--name",
33
+ containerName,
34
+ "--user",
35
+ containerUser,
36
+ "--workdir",
37
+ "/job/workspace/repository",
38
+ "--cpus",
39
+ String(environment.cpus),
40
+ "--memory",
41
+ `${environment.memoryGb}g`,
42
+ "--shm-size",
43
+ `${environment.shmGb}g`,
44
+ "--pids-limit",
45
+ "4096",
46
+ "--add-host",
47
+ "host.docker.internal:host-gateway",
48
+ "--env",
49
+ "HOME=/job/runtime-home",
50
+ "--volume",
51
+ `${bundle.directories.input}:/job/input:ro`,
52
+ "--volume",
53
+ `${bundle.directories.workspace}:/job/workspace:rw`,
54
+ "--volume",
55
+ `${bundle.directories.output}:/job/output:rw`,
56
+ "--volume",
57
+ `${bundle.directories.runtimeHome}:/job/runtime-home:rw`,
58
+ ];
59
+ args.push(...providerDockerEnvironment(agent, providerSession));
60
+ if (egressSession?.containerProxyUrl) {
61
+ args.push(
62
+ "--env",
63
+ `HTTP_PROXY=${egressSession.containerProxyUrl}`,
64
+ "--env",
65
+ `HTTPS_PROXY=${egressSession.containerProxyUrl}`,
66
+ "--env",
67
+ `http_proxy=${egressSession.containerProxyUrl}`,
68
+ "--env",
69
+ `https_proxy=${egressSession.containerProxyUrl}`,
70
+ "--env",
71
+ "NO_PROXY=127.0.0.1,localhost,host.docker.internal",
72
+ "--env",
73
+ "no_proxy=127.0.0.1,localhost,host.docker.internal",
74
+ );
75
+ }
76
+ if (environment.gpu === "all") {
77
+ args.push("--gpus", "all");
78
+ }
79
+ if (bundle.deploymentHandoff) {
80
+ for (const [key, target] of Object.entries({ assets: 'assets', runtimeCache: 'runtime-cache', runtimeVenv: 'runtime-venv' })) {
81
+ args.push('--volume', `${bundle.directories[key]}:/job/${target}:rw`);
82
+ }
83
+ args.push(environment.image, 'bash', '/job/input/local-runtime.sh', runtimeCommand, ...runtimeArgs);
84
+ } else args.push(environment.image, runtimeCommand, ...runtimeArgs);
85
+ return {
86
+ command: "docker",
87
+ args,
88
+ containerName,
89
+ printable: printableCommand("docker", sanitizeDockerArgs(args)),
90
+ credentialRelay: {
91
+ mode: providerSession.mode,
92
+ protocol: providerSession.apiProtocol,
93
+ source: providerSession.credentialSource,
94
+ injectedIntoSandbox: providerSession.credentialInjectedIntoSandbox,
95
+ },
96
+ networkEgress: {
97
+ mode: egressSession?.mode ?? "direct",
98
+ allowedHosts: egressSession?.allowedHosts ?? [],
99
+ },
100
+ };
101
+ }
102
+
103
+
104
+ export async function runDockerInvocation(
105
+ invocation,
106
+ { bundle, attempt, timeoutMs },
107
+ ) {
108
+ const tracePath = path.join(bundle.directories.execution, "trace.jsonl");
109
+ const stderrPath = path.join(bundle.directories.execution, "claude-stderr.log");
110
+ const marker = {
111
+ type: "citeark.attempt_started",
112
+ run_id: bundle.runId,
113
+ attempt,
114
+ recorded_at: new Date().toISOString(),
115
+ };
116
+ const { appendFile } = await import("node:fs/promises");
117
+ await appendFile(tracePath, `${JSON.stringify(marker)}\n`);
118
+
119
+ const runnerEvent = await recordRunnerProcessStarted({
120
+ executionDirectory: bundle.directories.execution,
121
+ runId: bundle.runId,
122
+ attempt,
123
+ executor: "docker",
124
+ command: invocation.command,
125
+ args: sanitizeDockerArgs(invocation.args),
126
+ workingDirectory: "/job/workspace/repository",
127
+ captureBoundary: "host-runner-outside-agent-mounts",
128
+ });
129
+
130
+ const stream = hasSessionEvents() ? createRuntimeStream({ source: `${bundle.runId}:${attempt}`, runtime: bundle.runtimeAgent.runtime }) : null;
131
+ const result = await runProcess(invocation.command, invocation.args, {
132
+ env: sanitizedHostRuntimeEnvironment(),
133
+ timeoutMs,
134
+ stdoutPath: tracePath,
135
+ stderrPath,
136
+ append: true,
137
+ printStdout: false,
138
+ onStdout: stream ? chunk => stream.write(chunk) : undefined,
139
+ onTimeout: async () => {
140
+ const stopped = await captureProcess('docker', ['stop', '--time', '5', invocation.containerName]);
141
+ const absent = stopped.code ? await captureProcess('docker', ['inspect', '--format', '{{.State.Running}}', invocation.containerName]) : null;
142
+ const finished = stopped.code === 0 || absent?.stdout.trim() === 'false' || /No such (object|container)/i.test(absent?.stderr ?? '');
143
+ await recordResearchCleanup({ provider: 'docker', resource: invocation.containerName, status: finished ? 'released' : 'failed', ...(!finished ? { error: stopped.stderr.trim() } : {}) });
144
+ if (!finished) throw Error(`Could not stop container ${invocation.containerName}: ${stopped.stderr.trim()}`);
145
+ },
146
+ }).finally(() => stream?.end());
147
+
148
+ await recordRunnerProcessFinished({
149
+ executionDirectory: bundle.directories.execution,
150
+ startedEvent: runnerEvent,
151
+ exitCode: result.code,
152
+ signal: result.signal,
153
+ timedOut: result.timedOut,
154
+ });
155
+
156
+ await appendFile(
157
+ tracePath,
158
+ `${JSON.stringify({
159
+ type: "citeark.attempt_finished",
160
+ run_id: bundle.runId,
161
+ attempt,
162
+ exit_code: result.code,
163
+ signal: result.signal,
164
+ timed_out: result.timedOut,
165
+ recorded_at: new Date().toISOString(),
166
+ })}\n`,
167
+ );
168
+ return result;
169
+ }
170
+
171
+ export async function writeInvocation(bundle, invocations) {
172
+ const filename = path.join(bundle.directories.execution, 'invocation.json');
173
+ const previous = bundle.restored && await pathExists(filename) ? (await readJson(filename)).invocations : [];
174
+ const currentAttempts = new Set(invocations.map(item => item.attempt));
175
+ await writeJson(path.join(bundle.directories.execution, "invocation.json"), {
176
+ schemaVersion: "0.1",
177
+ sandbox: "docker",
178
+ credentials: {
179
+ agent: bundle.runtimeAgent.runtime,
180
+ protocol: bundle.runtimeAgent.api.protocol,
181
+ source: invocations[0]?.credentialRelay?.source ?? null,
182
+ mode: invocations[0]?.credentialRelay?.mode ?? "host-credential-relay",
183
+ injectedIntoSandbox:
184
+ invocations[0]?.credentialRelay?.injectedIntoSandbox ?? false,
185
+ valueRecorded: false,
186
+ },
187
+ networkEgress: invocations[0]?.networkEgress ?? { mode: "direct", allowedHosts: [] },
188
+ invocations: [...previous.filter(item => !currentAttempts.has(item.attempt)), ...invocations.map((invocation) => ({
189
+ attempt: invocation.attempt,
190
+ command: invocation.command,
191
+ args: sanitizeDockerArgs(invocation.args),
192
+ printable: invocation.printable,
193
+ containerName: invocation.containerName,
194
+ }))],
195
+ });
196
+ }
197
+
198
+ export async function dockerDoctor(image, runtime = "opencode") {
199
+ const client = await captureProcess("docker", ["--version"]).catch(() => null);
200
+ const server = await captureProcess("docker", ["version", "--format", "{{.Server.Version}}"]).catch(
201
+ () => null,
202
+ );
203
+ let imageInspection = null;
204
+ if (server?.code === 0 && image) {
205
+ imageInspection = await captureProcess("docker", [
206
+ "image",
207
+ "inspect",
208
+ "--format",
209
+ "{{.Id}}",
210
+ image,
211
+ ]).catch(() => null);
212
+ }
213
+ const runtimeCommand = runtime === "claude-code" ? "claude" : runtime;
214
+ const runtimeInspection = imageInspection?.code === 0
215
+ ? await captureProcess("docker", [
216
+ "run",
217
+ "--rm",
218
+ image,
219
+ runtimeCommand,
220
+ "--version",
221
+ ]).catch(() => null)
222
+ : null;
223
+ return {
224
+ client: client?.code === 0 ? client.stdout.trim() : null,
225
+ server: server?.code === 0 ? server.stdout.trim() : null,
226
+ image: imageInspection?.code === 0 ? imageInspection.stdout.trim() : null,
227
+ runtime: runtimeInspection?.code === 0
228
+ ? (runtimeInspection.stdout || runtimeInspection.stderr).trim()
229
+ : null,
230
+ issues: [
231
+ ...(client?.code === 0 ? [] : ["Docker CLI is unavailable"]),
232
+ ...(server?.code === 0 ? [] : ["Docker is not running or is inaccessible"]),
233
+ ...(server?.code === 0 && image && imageInspection?.code !== 0
234
+ ? [`Docker image not found: ${image}`]
235
+ : []),
236
+ ...(imageInspection?.code === 0 && runtimeInspection?.code !== 0
237
+ ? [`The image does not contain a working ${runtimeCommand} CLI`]
238
+ : []),
239
+ ],
240
+ };
241
+ }
242
+
243
+ export async function inspectDockerImage(image) {
244
+ const [id, repositoryDigests] = await Promise.all([
245
+ captureProcess("docker", ["image", "inspect", "--format", "{{.Id}}", image]).catch(
246
+ () => null,
247
+ ),
248
+ captureProcess("docker", [
249
+ "image",
250
+ "inspect",
251
+ "--format",
252
+ "{{json .RepoDigests}}",
253
+ image,
254
+ ]).catch(() => null),
255
+ ]);
256
+ if (id?.code !== 0) return null;
257
+ let parsedDigests = [];
258
+ if (repositoryDigests?.code === 0) {
259
+ try {
260
+ parsedDigests = JSON.parse(repositoryDigests.stdout.trim()) ?? [];
261
+ } catch {
262
+ parsedDigests = [];
263
+ }
264
+ }
265
+ return { id: id.stdout.trim(), repositoryDigests: parsedDigests };
266
+ }
267
+
268
+ export function requireRuntimeCredentials(agent) {
269
+ if (!agent.api?.apiKey) {
270
+ throw new CiteArkError("缺少本次运行的 API Key。真实密钥只保留在宿主机密钥隔离代理中。");
271
+ }
272
+ }
273
+
274
+ function providerDockerEnvironment(agent, providerSession) {
275
+ if (agent.runtime === "claude-code") {
276
+ return [
277
+ "--env",
278
+ `ANTHROPIC_API_KEY=${providerSession.containerCredential}`,
279
+ "--env",
280
+ `ANTHROPIC_BASE_URL=${providerSession.containerBaseUrl}`,
281
+ "--env",
282
+ `ANTHROPIC_MODEL=${agent.model}`,
283
+ "--env",
284
+ `ANTHROPIC_DEFAULT_OPUS_MODEL=${agent.model}`,
285
+ "--env",
286
+ `ANTHROPIC_DEFAULT_SONNET_MODEL=${agent.model}`,
287
+ "--env",
288
+ `ANTHROPIC_DEFAULT_HAIKU_MODEL=${agent.subagentModel}`,
289
+ "--env",
290
+ `CLAUDE_CODE_SUBAGENT_MODEL=${agent.subagentModel}`,
291
+ "--env",
292
+ `CLAUDE_CODE_EFFORT_LEVEL=${agent.effort}`,
293
+ "--env",
294
+ `CLAUDE_CODE_AUTO_COMPACT_WINDOW=${agent.autoCompactWindow}`,
295
+ "--env",
296
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1",
297
+ ];
298
+ }
299
+ if (agent.runtime === "codex") {
300
+ return [
301
+ "--env",
302
+ `OPENAI_API_KEY=${providerSession.containerCredential}`,
303
+ "--env",
304
+ "CODEX_HOME=/job/runtime-home/codex",
305
+ ];
306
+ }
307
+ const config = {
308
+ $schema: "https://opencode.ai/config.json",
309
+ model: `citeark/${agent.model}`,
310
+ provider: {
311
+ citeark: {
312
+ npm: "@ai-sdk/openai-compatible",
313
+ name: "CiteArk Relay",
314
+ options: {
315
+ baseURL: `${providerSession.containerBaseUrl}/v1`,
316
+ apiKey: "{env:CITEARK_API_KEY}",
317
+ },
318
+ models: { [agent.model]: openCodeModelDefinition(agent) },
319
+ },
320
+ },
321
+ };
322
+ return [
323
+ "--env",
324
+ `CITEARK_API_KEY=${providerSession.containerCredential}`,
325
+ "--env",
326
+ `OPENCODE_CONFIG_CONTENT=${JSON.stringify(config)}`,
327
+ "--env",
328
+ "OPENCODE_DISABLE_AUTOUPDATE=1",
329
+ ];
330
+ }
331
+
332
+ function sanitizedHostRuntimeEnvironment() {
333
+ const environment = { ...process.env };
334
+ delete environment.ANTHROPIC_API_KEY;
335
+ delete environment.ANTHROPIC_AUTH_TOKEN;
336
+ delete environment.DEEPSEEK_API_KEY;
337
+ delete environment.OPENAI_API_KEY;
338
+ delete environment.CITEARK_API_KEY;
339
+ return environment;
340
+ }
341
+
342
+ function sanitizeDockerArgs(args) {
343
+ return args.map((argument) =>
344
+ argument
345
+ .replace(/^ANTHROPIC_AUTH_TOKEN=.*$/, "ANTHROPIC_AUTH_TOKEN=<redacted>")
346
+ .replace(/^ANTHROPIC_API_KEY=.*$/, "ANTHROPIC_API_KEY=<redacted>")
347
+ .replace(/^OPENAI_API_KEY=.*$/, "OPENAI_API_KEY=<redacted>")
348
+ .replace(/^CITEARK_API_KEY=.*$/, "CITEARK_API_KEY=<redacted>"),
349
+ );
350
+ }
351
+
352
+ // A crashed coordinator can leave Docker running. Never start a second Agent
353
+ // against that same writable workspace when recovering its saved session.
354
+ export async function assertLocalRunStopped(bundle, { run = captureProcess } = {}) {
355
+ if (!bundle.restored) return;
356
+ const filename = path.join(bundle.directories.execution, 'invocation.json');
357
+ if (!await pathExists(filename)) return;
358
+ const previous = (await readJson(filename)).invocations?.at(-1);
359
+ if (!previous?.containerName) return;
360
+ const result = await run('docker', ['inspect', '--format', '{{.State.Running}}', previous.containerName]);
361
+ if (result.code === 0 && result.stdout.trim() === 'true') throw new CiteArkError(`The previous container ${previous.containerName} is still running. Inspect it before stopping it or restarting this workspace.`);
362
+ if (result.code !== 0 && !/No such (object|container)/i.test(result.stderr)) throw new CiteArkError(`Cannot check the previous container: ${result.stderr.trim()}`);
363
+ }
@@ -0,0 +1,297 @@
1
+ import {
2
+ readSettings,
3
+ writeSettings,
4
+ profileName,
5
+ modelProfile,
6
+ computeProfile,
7
+ resolveModelProfile,
8
+ } from "./store.mjs";
9
+ import { createTerminalPrompter } from "../deployment/terminal.mjs";
10
+ import {
11
+ buildModelRequest,
12
+ readModelResponse,
13
+ } from "../provider/completion.mjs";
14
+ import { loadComputeCatalog, loadComputePolicy } from "../compute/catalog.mjs";
15
+
16
+ export async function settingsCommand(
17
+ kind,
18
+ argv,
19
+ parseOptions,
20
+ prompt = process.stdin.isTTY ? createTerminalPrompter() : null,
21
+ ) {
22
+ const [action = "list", name, ...rest] = argv;
23
+ const settings = await readSettings();
24
+ const group = kind === "model" ? "models" : "compute";
25
+ const defaultKey = kind === "model" ? "defaultModel" : "defaultCompute";
26
+ if (action === "list") {
27
+ for (const [key, value] of Object.entries(settings[group]))
28
+ console.log(
29
+ `${key === settings[defaultKey] ? "*" : " "} ${key} ${kind === "model" ? `${value.model} · ${value.apiBaseUrl}` : value.type === "ssh" ? value.host : value.type}`,
30
+ );
31
+ if (!Object.keys(settings[group]).length)
32
+ console.log(`No ${kind} profiles. Run citeark ${kind} add <name>.`);
33
+ return settings[group];
34
+ }
35
+ profileName(name);
36
+ if (["use", "remove", "check"].includes(action) && !settings[group][name])
37
+ throw Error(`Unknown ${kind} profile: ${name}`);
38
+ if (action === "use") settings[defaultKey] = name;
39
+ else if (action === "remove") {
40
+ delete settings[group][name];
41
+ if (settings[defaultKey] === name) delete settings[defaultKey];
42
+ } else if (action === "add") {
43
+ if (settings[group][name])
44
+ throw Error(
45
+ `Profile ${name} already exists. Remove it or use a new name.`,
46
+ );
47
+ if (kind === "model") {
48
+ const options = parseOptions(rest, {
49
+ "--agent": { type: "string" },
50
+ "--api-base-url": { type: "string" },
51
+ "--model": { type: "string" },
52
+ "--api-key-env": { type: "string" },
53
+ "--effort": { type: "string" },
54
+ "--budget": { type: "string" },
55
+ });
56
+ const runtime =
57
+ options["--agent"] ??
58
+ (prompt
59
+ ? await ask(prompt, "Agent runtime: opencode, codex or claude-code", {
60
+ defaultValue: "opencode",
61
+ })
62
+ : "opencode");
63
+ const apiBaseUrl =
64
+ options["--api-base-url"] ?? (await ask(prompt, "Model API base URL"));
65
+ const model = options["--model"] ?? (await ask(prompt, "Model name"));
66
+ const apiKeyEnv =
67
+ options["--api-key-env"] ??
68
+ (await ask(prompt, "API key environment variable", {
69
+ defaultValue: "CITEARK_MODEL_API_KEY",
70
+ }));
71
+ settings.models[name] = modelProfile({
72
+ runtime,
73
+ apiBaseUrl,
74
+ model,
75
+ ...(apiKeyEnv ? { apiKeyEnv } : {}),
76
+ ...(options["--effort"] ? { effort: options["--effort"] } : {}),
77
+ ...(options["--budget"]
78
+ ? { maxBudgetUsd: Number(options["--budget"]) }
79
+ : {}),
80
+ });
81
+ } else {
82
+ const options = parseOptions(rest, {
83
+ "--type": { type: "string" },
84
+ "--host": { type: "string" },
85
+ "--directory": { type: "string" },
86
+ "--port": { type: "string" },
87
+ "--identity": { type: "string" },
88
+ "--ssh-config": { type: "string" },
89
+ "--command": { type: "string" },
90
+ "--catalog": { type: "string" },
91
+ "--policy": { type: "string" },
92
+ "--profile": { type: "string" },
93
+ "--device": { type: "string" },
94
+ "--image": { type: "string" },
95
+ });
96
+ const type =
97
+ options["--type"] ??
98
+ (await ask(prompt, "Compute type: local, ssh or catalog", {
99
+ defaultValue: "local",
100
+ }));
101
+ settings.compute[name] = computeProfile({
102
+ type,
103
+ host:
104
+ options["--host"] ??
105
+ (type === "ssh"
106
+ ? await ask(prompt, "SSH host or config alias")
107
+ : undefined),
108
+ directory:
109
+ options["--directory"] ??
110
+ (type === "ssh"
111
+ ? await ask(prompt, "Remote workspace root (absolute path)")
112
+ : undefined),
113
+ ...(options["--port"] ? { port: Number(options["--port"]) } : {}),
114
+ identityFile: options["--identity"],
115
+ configFile: options["--ssh-config"],
116
+ command: options["--command"],
117
+ catalog:
118
+ options["--catalog"] ??
119
+ (type === "catalog"
120
+ ? await ask(prompt, "Compute catalog file")
121
+ : undefined),
122
+ policy: options["--policy"],
123
+ profile: options["--profile"],
124
+ device: options["--device"],
125
+ image: options["--image"],
126
+ });
127
+ if (type === "catalog") {
128
+ await loadComputeCatalog(settings.compute[name].catalog);
129
+ if (settings.compute[name].policy)
130
+ await loadComputePolicy(settings.compute[name].policy);
131
+ }
132
+ }
133
+ settings[defaultKey] ??= name;
134
+ } else if (action === "check") {
135
+ if (kind === "model") {
136
+ const value = resolveModelProfile(settings, name);
137
+ if (value.apiKeyEnv && !value.apiKey)
138
+ throw Error(`Set ${value.apiKeyEnv} before checking this model.`);
139
+ await checkModel(value);
140
+ console.log(
141
+ `Model ${name}: tool calling and structured response passed.`,
142
+ );
143
+ } else {
144
+ const value = settings.compute[name];
145
+ if (value.type === "ssh") {
146
+ const { sshCommand } = await import("../remote/ssh.mjs");
147
+ console.log(await sshCommand(value, ["doctor"]));
148
+ } else if (value.type === "catalog") {
149
+ await loadComputeCatalog(value.catalog);
150
+ console.log(
151
+ `Catalog ${name}: valid. Runtime credentials and capacity are checked when submitting a task.`,
152
+ );
153
+ } else {
154
+ const { checkLocalExecution } = await import(
155
+ "../deployment/environment.mjs"
156
+ );
157
+ console.log(
158
+ JSON.stringify(
159
+ await checkLocalExecution({
160
+ environment: {
161
+ image:
162
+ value.image ??
163
+ `citeark-agent/runtime:${value.device === "cuda" ? "cuda" : "cpu"}`,
164
+ gpu: value.device === "cuda" ? "all" : "none",
165
+ cpus: 1,
166
+ memoryGb: 1,
167
+ },
168
+ compute: {},
169
+ }),
170
+ null,
171
+ 2,
172
+ ),
173
+ );
174
+ }
175
+ }
176
+ return;
177
+ } else throw Error(`Usage: citeark ${kind} list|add|use|remove|check [name]`);
178
+ await writeSettings(settings);
179
+ console.log(
180
+ `${kind === "model" ? "Model" : "Compute"} profile ${name}: ${action === "remove" ? "removed" : "saved"}.`,
181
+ );
182
+ }
183
+ async function ask(prompt, label, options) {
184
+ if (!prompt)
185
+ throw Error(
186
+ `${label} is required. Supply the matching command option or use an interactive terminal.`,
187
+ );
188
+ return prompt.ask(label, options);
189
+ }
190
+
191
+ export async function checkModel(agent, { fetchImpl = fetch } = {}) {
192
+ const messages = [
193
+ {
194
+ role: "user",
195
+ content:
196
+ 'Call citeark_probe with value "ready", then return {"ready":true}.',
197
+ },
198
+ ];
199
+ const tools = [
200
+ {
201
+ type: "function",
202
+ function: {
203
+ name: "citeark_probe",
204
+ description: "Check tool response support.",
205
+ parameters: {
206
+ type: "object",
207
+ properties: { value: { type: "string" } },
208
+ required: ["value"],
209
+ additionalProperties: false,
210
+ },
211
+ },
212
+ },
213
+ ];
214
+ const format = {
215
+ type: "json_schema",
216
+ json_schema: {
217
+ name: "citeark_probe_result",
218
+ strict: true,
219
+ schema: {
220
+ type: "object",
221
+ properties: { ready: { type: "boolean" } },
222
+ required: ["ready"],
223
+ additionalProperties: false,
224
+ },
225
+ },
226
+ };
227
+ let called = false;
228
+ for (let turn = 0; turn < 3; turn++) {
229
+ const request = buildModelRequest({
230
+ agent,
231
+ apiKey: agent.apiKey,
232
+ messages,
233
+ tools,
234
+ format,
235
+ maxTokens: 4096,
236
+ signal: AbortSignal.timeout(60000),
237
+ });
238
+ const response = await fetchImpl(request.url, request.init);
239
+ if (!response.ok)
240
+ throw Error(
241
+ `Model check failed (HTTP ${response.status}). Check the endpoint, credentials and model capabilities.`,
242
+ );
243
+ const payload = readModelResponse(await response.json(), request.protocol);
244
+ const choice = payload.choices?.[0];
245
+ const message = choice?.message;
246
+ if (
247
+ payload.error ||
248
+ message?.refusal ||
249
+ (choice?.finish_reason &&
250
+ !["stop", "tool_calls"].includes(choice.finish_reason))
251
+ )
252
+ throw Error("Model response was refused or incomplete.");
253
+ if (!message) throw Error("Model returned no response.");
254
+ if (message.tool_calls?.length) {
255
+ messages.push({ ...message, role: "assistant" });
256
+ for (const call of message.tool_calls) {
257
+ if (
258
+ call.function.name !== "citeark_probe" ||
259
+ JSON.parse(call.function.arguments).value !== "ready"
260
+ )
261
+ throw Error("Model check returned an invalid tool call.");
262
+ called = true;
263
+ messages.push({
264
+ role: "tool",
265
+ tool_call_id: call.id,
266
+ content: '{"accepted":true}',
267
+ });
268
+ }
269
+ } else {
270
+ if (!called || JSON.parse(message.content).ready !== true)
271
+ throw Error(
272
+ "Model did not complete the tool and structured response check.",
273
+ );
274
+ return { protocol: request.protocol, model: agent.model };
275
+ }
276
+ }
277
+ throw Error("Model did not finish the connection check.");
278
+ }
279
+
280
+ export async function settingsMenu(kind, prompt) {
281
+ const settings = await readSettings();
282
+ const group = kind === "model" ? "models" : "compute";
283
+ const selected = await prompt.choose(`Select ${kind}`, [
284
+ ...Object.entries(settings[group]).map(([name, value]) => ({
285
+ value: name,
286
+ label: `${name} · ${value.model ?? value.host ?? value.type}`,
287
+ })),
288
+ { value: "+", label: "Add a profile" },
289
+ ]);
290
+ const { parseOptions } = await import("../cli.mjs");
291
+ if (selected === "+") {
292
+ const name = await prompt.ask("Profile name");
293
+ await settingsCommand(kind, ["add", name], parseOptions, prompt);
294
+ return settingsCommand(kind, ["use", name], parseOptions, prompt);
295
+ }
296
+ return settingsCommand(kind, ["use", selected], parseOptions, prompt);
297
+ }