@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.
- package/LICENSE +202 -0
- package/README.md +128 -0
- package/data/dataset-source-registry.v1.json +300 -0
- package/dist/arkgraph/boot.js +6 -0
- package/dist/arkgraph/index.html +1 -0
- package/dist/arkgraph/viewer.css +1 -0
- package/dist/arkgraph/viewer.en.css +1 -0
- package/dist/arkgraph/viewer.en.js +49 -0
- package/dist/arkgraph/viewer.en.js.LEGAL.txt +56 -0
- package/dist/arkgraph/viewer.js +49 -0
- package/dist/arkgraph/viewer.js.LEGAL.txt +56 -0
- package/docker/claude-code/Dockerfile +97 -0
- package/docker/claude-code/codex-pro-relay.mjs +466 -0
- package/docker/claude-code/runtime-contract-check.mjs +79 -0
- package/docs/arkgraph-reading.md +79 -0
- package/docs/configuration.md +100 -0
- package/docs/integration.md +92 -0
- package/docs/maturity-plan.md +27 -0
- package/docs/npm-release.md +44 -0
- package/docs/paper-reading.md +40 -0
- package/docs/research-plan-granularity.md +27 -0
- package/docs/terminal.md +49 -0
- package/examples/toy-evaluation/compile-task.json +27 -0
- package/examples/toy-evaluation/paper.md +5 -0
- package/examples/toy-evaluation/repository/README.md +9 -0
- package/examples/toy-evaluation/repository/checkpoint.json +4 -0
- package/examples/toy-evaluation/repository/evaluate.py +17 -0
- package/examples/toy-evaluation/task.json +81 -0
- package/package.json +59 -0
- package/prompts/compile-research.md +58 -0
- package/prompts/execute-contract.md +72 -0
- package/prompts/execute-workspace-simple.md +51 -0
- package/prompts/execute-workspace.md +34 -0
- package/prompts/prepare-reproduction.md +82 -0
- package/prompts/repair-research.md +45 -0
- package/protocol/CAP.md +129 -0
- package/protocol/LICENSE +12 -0
- package/protocol/MAPPINGS.md +72 -0
- package/protocol/README.md +38 -0
- package/protocol/conformance-v2.0-alpha.1.json +36 -0
- package/protocol/examples/arkgraph/checkpoint-evaluation.json +309 -0
- package/protocol/examples/arkgraph/fixtures.mjs +49 -0
- package/protocol/examples/arkgraph/paper-free.json +291 -0
- package/protocol/examples/arkgraph/partial-failure.json +344 -0
- package/protocol/examples/arkgraph/training-evaluation.json +443 -0
- package/protocol/profiles/agent-trace.md +16 -0
- package/protocol/profiles/computational-run.md +16 -0
- package/protocol/profiles/core.md +15 -0
- package/protocol/profiles/public-bundle.md +18 -0
- package/protocol/profiles/reproduction.md +29 -0
- package/protocol/profiles/research-compilation.md +44 -0
- package/protocol/profiles/research-plan.md +39 -0
- package/protocol/profiles/restricted-evidence.md +15 -0
- package/runtime/bootstrap-autodl-runtime.sh +314 -0
- package/runtime/create-runtime-venv.sh +41 -0
- package/runtime/install-local-cpu-runtime.sh +23 -0
- package/runtime/install-scientific-runtime.sh +153 -0
- package/runtime/mineru/parse.py +62 -0
- package/runtime/mineru/requirements.txt +4 -0
- package/runtime/requirements-baseline.txt +38 -0
- package/schemas/cap/v2/activity.schema.json +47 -0
- package/schemas/cap/v2/agent.schema.json +32 -0
- package/schemas/cap/v2/assertion.schema.json +110 -0
- package/schemas/cap/v2/descriptor.schema.json +243 -0
- package/schemas/cap/v2/entity.schema.json +64 -0
- package/schemas/cap/v2/manifest.schema.json +67 -0
- package/schemas/cap/v2/relation.schema.json +82 -0
- package/schemas/compute-catalog.schema.json +63 -0
- package/schemas/compute-decision.schema.json +27 -0
- package/schemas/execution-contract.schema.json +1024 -0
- package/schemas/research-card.schema.json +30 -0
- package/schemas/research-inventory-draft.schema.json +366 -0
- package/schemas/research.schema.json +1044 -0
- package/schemas/result.schema.json +173 -0
- package/schemas/verification-policy.schema.json +47 -0
- package/schemas/verified-conclusion.schema.json +58 -0
- package/schemas/workspace-summary.schema.json +24 -0
- package/scripts/build-arkgraph-view.mjs +12 -0
- package/scripts/check-execution-feasibility.mjs +24 -0
- package/scripts/check-syntax.mjs +15 -0
- package/scripts/deterministic-asset-preparation.py +438 -0
- package/scripts/package-cap.mjs +23 -0
- package/scripts/package-local-agent.mjs +23 -0
- package/scripts/preview-arkgraph.mjs +25 -0
- package/scripts/replay-research-compiler-candidate.mjs +134 -0
- package/scripts/review-compiler-sources.mjs +44 -0
- package/scripts/run-asset-preparation.sh +17 -0
- package/scripts/run-research-plan.mjs +98 -0
- package/scripts/validate-asset-preparation.py +290 -0
- package/scripts/verify-local-runtime.mjs +57 -0
- package/scripts/verify-npm-package.mjs +57 -0
- package/src/adapters/paper2agent.mjs +107 -0
- package/src/assets/cache.mjs +159 -0
- package/src/assets/compute.mjs +98 -0
- package/src/assets/executor.mjs +145 -0
- package/src/assets/lifecycle.mjs +213 -0
- package/src/assets/manifest.mjs +242 -0
- package/src/assets/opportunistic-preparation.mjs +81 -0
- package/src/assets/plan.mjs +411 -0
- package/src/assets/prompts.mjs +29 -0
- package/src/assets/public-asset-probe.mjs +525 -0
- package/src/assets/qualification.mjs +119 -0
- package/src/assets/readiness.mjs +130 -0
- package/src/assets/reproduction-admission.mjs +355 -0
- package/src/assets/requirements.mjs +152 -0
- package/src/assets/source-grounding.mjs +341 -0
- package/src/assets/source-policy.mjs +118 -0
- package/src/autodl/client.mjs +260 -0
- package/src/autodl/ssh.mjs +380 -0
- package/src/autodl/tools.mjs +129 -0
- package/src/cap/redaction.mjs +38 -0
- package/src/cap/v2/archive.mjs +152 -0
- package/src/cap/v2/attestation.mjs +204 -0
- package/src/cap/v2/canonical-json.mjs +114 -0
- package/src/cap/v2/compilation-artifact.mjs +240 -0
- package/src/cap/v2/core.mjs +282 -0
- package/src/cap/v2/measurement-assessment-records.mjs +23 -0
- package/src/cap/v2/pipeline-artifact.mjs +922 -0
- package/src/cap/v2/read.mjs +41 -0
- package/src/cap/v2/reassessment-artifact.mjs +383 -0
- package/src/cap/v2/research-artifact.mjs +231 -0
- package/src/cap/v2/research-map-records.mjs +46 -0
- package/src/cap/v2/research-object-records.mjs +163 -0
- package/src/cap/v2/research-records.mjs +187 -0
- package/src/cap/v2/verify.mjs +642 -0
- package/src/cli.mjs +1146 -0
- package/src/compute/autodl-pro-compiler.mjs +347 -0
- package/src/compute/autodl-pro-executor.mjs +459 -0
- package/src/compute/autodl-pro-job.mjs +843 -0
- package/src/compute/autodl-pro-network.mjs +295 -0
- package/src/compute/autodl-pro-remote.mjs +810 -0
- package/src/compute/autodl-pro-staging.mjs +117 -0
- package/src/compute/campaign.mjs +110 -0
- package/src/compute/catalog.mjs +123 -0
- package/src/compute/checkpoint-protocol.mjs +154 -0
- package/src/compute/codex-account-lock.mjs +111 -0
- package/src/compute/codex-account-session.mjs +107 -0
- package/src/compute/compiler-profile.mjs +38 -0
- package/src/compute/compiler-router.mjs +23 -0
- package/src/compute/coordinator-recovery.mjs +210 -0
- package/src/compute/executor-router.mjs +29 -0
- package/src/compute/gcp-batch-compiler.mjs +685 -0
- package/src/compute/gcp-batch-executor.mjs +1215 -0
- package/src/compute/gcp-batch-failure.mjs +92 -0
- package/src/compute/gcp-batch-job.mjs +527 -0
- package/src/compute/gcp-batch-lifecycle.mjs +81 -0
- package/src/compute/gcp-checkpoint-worker.mjs +1633 -0
- package/src/compute/local-codex-compiler.mjs +52 -0
- package/src/compute/measurement-hardware.mjs +128 -0
- package/src/compute/remote-attempt.mjs +226 -0
- package/src/compute/requirements.mjs +124 -0
- package/src/compute/research-phases.mjs +48 -0
- package/src/compute/scheduler.mjs +452 -0
- package/src/compute/shared-workloads.mjs +26 -0
- package/src/compute/stage-archive.mjs +79 -0
- package/src/contracts/campaign-contract.mjs +52 -0
- package/src/contracts/execution-contract.mjs +819 -0
- package/src/contracts/execution-mode.mjs +19 -0
- package/src/contracts/execution-timeouts.mjs +45 -0
- package/src/contracts/execution-workload.mjs +68 -0
- package/src/contracts/preflight-schema.mjs +25 -0
- package/src/contracts/public-contract.mjs +63 -0
- package/src/contracts/subject-tags.mjs +31 -0
- package/src/dashboard/data.mjs +898 -0
- package/src/dashboard/server.mjs +79 -0
- package/src/dashboard/static/dashboard.css +366 -0
- package/src/dashboard/static/dashboard.js +560 -0
- package/src/dashboard/static/index.html +85 -0
- package/src/deployment/community-policy.mjs +9 -0
- package/src/deployment/environment.mjs +112 -0
- package/src/deployment/guided.mjs +98 -0
- package/src/deployment/handoff.mjs +102 -0
- package/src/deployment/local-contract.mjs +31 -0
- package/src/deployment/local.mjs +100 -0
- package/src/deployment/prepare.mjs +46 -0
- package/src/deployment/recipe.mjs +108 -0
- package/src/deployment/supplement.mjs +51 -0
- package/src/deployment/terminal.mjs +43 -0
- package/src/diagnosis/renderer.mjs +75 -0
- package/src/diagnosis/target-failure.mjs +46 -0
- package/src/evidence/parser-registry.mjs +54 -0
- package/src/evidence/parsers/fasttext-classification.mjs +82 -0
- package/src/evidence/parsers/json-scalar.mjs +96 -0
- package/src/evidence/parsers/simcse-senteval.mjs +104 -0
- package/src/evidence/parsers/starspace-classification.mjs +78 -0
- package/src/evidence/registry.mjs +147 -0
- package/src/execution/runner-audit.mjs +473 -0
- package/src/gcp/auth.mjs +106 -0
- package/src/gcp/batch-client.mjs +120 -0
- package/src/gcp/resource-discovery.mjs +177 -0
- package/src/gcp/rest.mjs +82 -0
- package/src/gcp/secret-manager.mjs +34 -0
- package/src/gcp/signed-url.mjs +133 -0
- package/src/gcp/storage.mjs +220 -0
- package/src/graph/command.mjs +41 -0
- package/src/graph/execution.mjs +97 -0
- package/src/graph/model.mjs +37 -0
- package/src/graph/presentation.mjs +110 -0
- package/src/graph/query.mjs +159 -0
- package/src/graph/research-relations.mjs +69 -0
- package/src/graph/source-page.mjs +12 -0
- package/src/graph/source-preview.mjs +34 -0
- package/src/graph/validate.mjs +76 -0
- package/src/job.mjs +496 -0
- package/src/network/autodl-routing-proxy.mjs +462 -0
- package/src/network/egress-proxy.mjs +158 -0
- package/src/observability/event-contract.mjs +230 -0
- package/src/observability/pipeline-monitor.mjs +166 -0
- package/src/pipeline/orchestrator.mjs +1281 -0
- package/src/pipeline/recovery-error.mjs +11 -0
- package/src/pipeline/replay.mjs +304 -0
- package/src/pipeline/shared-execution.mjs +115 -0
- package/src/pipeline/stage-checkpoint.mjs +86 -0
- package/src/pipeline/stage-recovery.mjs +101 -0
- package/src/pipeline/targets.mjs +110 -0
- package/src/process.mjs +143 -0
- package/src/protocol.mjs +312 -0
- package/src/provider/codex-account.mjs +44 -0
- package/src/provider/codex-completion.mjs +49 -0
- package/src/provider/completion.mjs +292 -0
- package/src/provider/model-client.mjs +44 -0
- package/src/provider/model-route.mjs +29 -0
- package/src/provider/openrouter-readiness.mjs +189 -0
- package/src/provider/reader-bridge.mjs +35 -0
- package/src/provider/relay.mjs +263 -0
- package/src/provider/runtime-auth.mjs +40 -0
- package/src/public/cap.d.mts +90 -0
- package/src/public/cap.mjs +12 -0
- package/src/public/contracts.d.mts +2 -0
- package/src/public/host.mjs +171 -0
- package/src/public/operations.d.mts +11 -0
- package/src/public/presentation.d.mts +4 -0
- package/src/records/views.mjs +26 -0
- package/src/remote/command.mjs +178 -0
- package/src/remote/ssh.mjs +59 -0
- package/src/repository-origin.mjs +81 -0
- package/src/reproduction/evidence-feedback.mjs +96 -0
- package/src/reproduction/incomplete-initialization.mjs +25 -0
- package/src/reproduction/lifecycle.mjs +253 -0
- package/src/reproduction/plan.mjs +132 -0
- package/src/reproduction/prompts.mjs +70 -0
- package/src/reproduction/runner.mjs +188 -0
- package/src/reproduction/summary.mjs +130 -0
- package/src/reproduction/workspace-mode.mjs +7 -0
- package/src/research/automatic-admission.mjs +156 -0
- package/src/research/compiler-coverage.mjs +85 -0
- package/src/research/compiler-failure.mjs +24 -0
- package/src/research/compiler-normalization-guards.mjs +112 -0
- package/src/research/compiler-repair.mjs +3 -0
- package/src/research/compiler.mjs +853 -0
- package/src/research/continuation-selection.mjs +26 -0
- package/src/research/execution-graph-context.mjs +43 -0
- package/src/research/experiment-importance.mjs +15 -0
- package/src/research/inventory-handoff.mjs +104 -0
- package/src/research/inventory-revisions.mjs +32 -0
- package/src/research/mineru-local.mjs +73 -0
- package/src/research/paper-command.mjs +19 -0
- package/src/research/paper-markdown.mjs +180 -0
- package/src/research/paper-source-map.mjs +69 -0
- package/src/research/planning-policy.mjs +88 -0
- package/src/research/reference-materials.mjs +11 -0
- package/src/research/reproduction-scope.mjs +30 -0
- package/src/research/research-map.mjs +94 -0
- package/src/research/research-objects.mjs +88 -0
- package/src/research/source-discovery.mjs +646 -0
- package/src/research/source-observations.mjs +75 -0
- package/src/research/source-review-cli-mcp.mjs +26 -0
- package/src/research/source-review-input.mjs +209 -0
- package/src/research/source-review-local-codex.mjs +36 -0
- package/src/research/source-review-model.mjs +70 -0
- package/src/research/source-review.mjs +173 -0
- package/src/research/structure.mjs +3163 -0
- package/src/research-card/renderer.mjs +277 -0
- package/src/research-card/verified-conclusion.mjs +143 -0
- package/src/results/output-registry.mjs +183 -0
- package/src/runtime/claude-code.mjs +52 -0
- package/src/runtime/codex-capacity-retry.mjs +87 -0
- package/src/runtime/codex.mjs +64 -0
- package/src/runtime/config.mjs +157 -0
- package/src/runtime/final-output.mjs +40 -0
- package/src/runtime/index.mjs +21 -0
- package/src/runtime/local-codex.mjs +74 -0
- package/src/runtime/opencode.mjs +95 -0
- package/src/runtime/prompt.mjs +13 -0
- package/src/sandbox/docker.mjs +363 -0
- package/src/settings/command.mjs +297 -0
- package/src/settings/store.mjs +119 -0
- package/src/telemetry/pricing.mjs +68 -0
- package/src/telemetry/usage.mjs +265 -0
- package/src/terminal/events.mjs +97 -0
- package/src/terminal/input.mjs +40 -0
- package/src/terminal/plain.mjs +40 -0
- package/src/terminal/remote-stream.mjs +22 -0
- package/src/terminal/screen.mjs +214 -0
- package/src/terminal/transcript.mjs +69 -0
- package/src/util.mjs +107 -0
- package/src/verification/ai-assessor.mjs +534 -0
- package/src/verification/claim-evaluator.mjs +242 -0
- package/src/verification/evidence-context.mjs +165 -0
- package/src/verification/evidence-reader.mjs +95 -0
- package/src/verification/integrity.mjs +570 -0
- package/src/verification/tolerance.mjs +32 -0
- package/src/workloads/cpu-research-preparation.mjs +56 -0
- package/src/workloads/definition.mjs +74 -0
- package/src/workloads/phase-aware-reproduction.mjs +46 -0
- package/src/workloads/reproduction.mjs +85 -0
- package/src/workspace/command.mjs +242 -0
- package/src/workspace/control.mjs +49 -0
- package/src/workspace/entry.mjs +28 -0
- package/src/workspace/input.mjs +93 -0
- package/src/workspace/interactive.mjs +94 -0
- package/src/workspace/jobs.mjs +418 -0
- package/src/workspace/session.mjs +97 -0
- package/src/workspace/worker.mjs +137 -0
- package/ui/arkgraph/ambient-motion.mjs +10 -0
- package/ui/arkgraph/app.jsx +153 -0
- package/ui/arkgraph/boot.js +6 -0
- package/ui/arkgraph/camera-motion.mjs +20 -0
- package/ui/arkgraph/context-reveal.mjs +39 -0
- package/ui/arkgraph/details.css +3 -0
- package/ui/arkgraph/entry.jsx +28 -0
- package/ui/arkgraph/experiment-curves.mjs +17 -0
- package/ui/arkgraph/experiment-selection.mjs +15 -0
- package/ui/arkgraph/experiment-style.css +26 -0
- package/ui/arkgraph/experiment-ui.jsx +32 -0
- package/ui/arkgraph/frame.html +1 -0
- package/ui/arkgraph/graph-gestures.mjs +62 -0
- package/ui/arkgraph/label-layout.mjs +57 -0
- package/ui/arkgraph/locales/en.json +229 -0
- package/ui/arkgraph/locales/source-types.json +15 -0
- package/ui/arkgraph/localization-build.mjs +27 -0
- package/ui/arkgraph/material-build.mjs +23 -0
- package/ui/arkgraph/material-colors.mjs +39 -0
- package/ui/arkgraph/material-style.css +15 -0
- package/ui/arkgraph/open-graph.jsx +326 -0
- package/ui/arkgraph/outline.jsx +49 -0
- package/ui/arkgraph/package-lock.json +888 -0
- package/ui/arkgraph/package.json +17 -0
- package/ui/arkgraph/reading-layout.mjs +130 -0
- package/ui/arkgraph/reading-presentation.mjs +73 -0
- package/ui/arkgraph/record-detail.css +51 -0
- package/ui/arkgraph/record-details.jsx +29 -0
- package/ui/arkgraph/research-types.mjs +31 -0
- package/ui/arkgraph/selection-mark.jsx +6 -0
- package/ui/arkgraph/soft-spine.mjs +26 -0
- package/ui/arkgraph/steering-style.css +187 -0
- package/ui/arkgraph/style.css +272 -0
package/src/cli.mjs
ADDED
|
@@ -0,0 +1,1146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { deployLocally, publishLocalCap } from "./deployment/local.mjs";
|
|
4
|
+
import { setupLocalRuntime } from "./deployment/environment.mjs";
|
|
5
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
6
|
+
import { cp, mkdtemp, mkdir, rm } from "node:fs/promises";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
import { assemblePaper2AgentCompilationCap } from "./adapters/paper2agent.mjs";
|
|
12
|
+
import {
|
|
13
|
+
packCap,
|
|
14
|
+
verifyCapArchive,
|
|
15
|
+
} from "./cap/v2/archive.mjs";
|
|
16
|
+
import { assembleResearchCompilationCap } from "./cap/v2/compilation-artifact.mjs";
|
|
17
|
+
import { verifyCapDirectory } from "./cap/v2/verify.mjs";
|
|
18
|
+
import { AutoDlProClient } from "./autodl/client.mjs";
|
|
19
|
+
import { AutoDlSshClient, parseAutoDlSshConnection } from "./autodl/ssh.mjs";
|
|
20
|
+
import {
|
|
21
|
+
ASSET_QUALIFICATION_BOUNDARY,
|
|
22
|
+
loadAssetQualificationContext,
|
|
23
|
+
planAssetQualification,
|
|
24
|
+
probeAssetQualification,
|
|
25
|
+
verifyAssetQualification,
|
|
26
|
+
} from "./assets/qualification.mjs";
|
|
27
|
+
import { loadComputeCatalog, loadComputePolicy } from "./compute/catalog.mjs";
|
|
28
|
+
import { loadComputeDecision, scheduleCompute } from "./compute/scheduler.mjs";
|
|
29
|
+
import { executeScheduledReproduction } from "./compute/executor-router.mjs";
|
|
30
|
+
import { createExecutionContract, loadExecutionContract } from "./contracts/execution-contract.mjs";
|
|
31
|
+
import { startDashboardServer } from "./dashboard/server.mjs";
|
|
32
|
+
import { listEvidenceParsers, parseContractEvidence } from "./evidence/registry.mjs";
|
|
33
|
+
import {
|
|
34
|
+
loadAndNormalizeTask,
|
|
35
|
+
validateResultFile,
|
|
36
|
+
} from "./protocol.mjs";
|
|
37
|
+
import { executeFullPipeline } from "./pipeline/orchestrator.mjs";
|
|
38
|
+
import { runResearchCompiler } from "./research/compiler.mjs";
|
|
39
|
+
import { loadResearchStructure, normalizeResearchFile } from "./research/structure.mjs";
|
|
40
|
+
import { primaryMetric } from "./records/views.mjs";
|
|
41
|
+
import { dockerDoctor } from "./sandbox/docker.mjs";
|
|
42
|
+
import { CiteArkError, createRunId, shellQuote, writeJson } from "./util.mjs";
|
|
43
|
+
|
|
44
|
+
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
45
|
+
const VERSION = JSON.parse(readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8")).version;
|
|
46
|
+
|
|
47
|
+
if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) await bootstrap().catch((error) => {
|
|
48
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
|
+
console.error(`\nCiteArk Agent: ${message}`);
|
|
50
|
+
process.exitCode = error?.exitCode ?? 1;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
async function bootstrap() {
|
|
54
|
+
loadLocalEnvironment();
|
|
55
|
+
await main();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function loadLocalEnvironment() {
|
|
59
|
+
if (typeof process.loadEnvFile !== "function") return;
|
|
60
|
+
const candidates = [
|
|
61
|
+
path.resolve(".env.local"),
|
|
62
|
+
path.join(PACKAGE_ROOT, ".env.local"),
|
|
63
|
+
];
|
|
64
|
+
for (const candidate of new Set(candidates)) {
|
|
65
|
+
if (!existsSync(candidate)) continue;
|
|
66
|
+
process.loadEnvFile(candidate);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
72
|
+
const [command = process.stdin.isTTY && process.stdout.isTTY ? "start" : "help", ...rest] = argv;
|
|
73
|
+
if (command === "--help" || command === "-h" || command === "help") {
|
|
74
|
+
printHelp();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (command === "--version" || command === "-v" || command === "version") {
|
|
78
|
+
console.log(VERSION);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (command === 'view') {
|
|
82
|
+
if (!rest[0]) throw Error('Usage: citeark view <workspace-directory>');
|
|
83
|
+
const filename = path.join(path.resolve(rest[0]), 'session.events.jsonl');
|
|
84
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY || process.env.TERM === 'dumb') {
|
|
85
|
+
const { Transcript } = await import('./terminal/transcript.mjs');
|
|
86
|
+
const transcript = new Transcript();
|
|
87
|
+
for (const line of readFileSync(filename, 'utf8').split('\n').filter(Boolean)) transcript.add(JSON.parse(line));
|
|
88
|
+
console.log(transcript.lines(100, true).join('\n'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const { TerminalScreen } = await import('./terminal/screen.mjs');
|
|
92
|
+
const screen = new TerminalScreen({ version: VERSION }); screen.start();
|
|
93
|
+
try { await screen.view(filename); } finally { await screen.close(); }
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (command === 'paper') return (await import('./research/paper-command.mjs')).paperCommand(rest, parseOptions);
|
|
97
|
+
if (command === 'session') return (await import('./workspace/jobs.mjs')).sessionCommand(rest, parseOptions);
|
|
98
|
+
if (command === 'graph') return (await import('./graph/command.mjs')).graphCommand(rest, parseOptions);
|
|
99
|
+
if (command === 'start' || (command === 'deploy' && !rest.includes('--replay'))) {
|
|
100
|
+
const { startResearch } = await import('./workspace/command.mjs');
|
|
101
|
+
return startResearch(rest, { parseOptions, agentEntryOptions, gcpEntryOptions, autoDlEntryOptions, agentRuntimeOptions, executorOptions });
|
|
102
|
+
}
|
|
103
|
+
if (command === 'deploy') return deployCommand(rest.filter(value => value !== '--replay'));
|
|
104
|
+
if (command === "handoff") {
|
|
105
|
+
const options = parseOptions(rest, { "--cap": { type: "string", required: true },
|
|
106
|
+
"--research-cap": { type: "string" }, "--output": { type: "string", required: true },
|
|
107
|
+
"--model": { type: "string", required: true }, "--effort": { type: "string", default: "high" },
|
|
108
|
+
"--signing-key": { type: "string" } });
|
|
109
|
+
const { prepareHistoricalHandoff } = await import('./deployment/prepare.mjs');
|
|
110
|
+
console.log(JSON.stringify(await prepareHistoricalHandoff({ capPath: options['--cap'], researchCapPath: options['--research-cap'],
|
|
111
|
+
directory: path.resolve(options['--output']), model: options['--model'], effort: options['--effort'], signingKeyPath: options['--signing-key'] }), null, 2));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (command === "setup") {
|
|
115
|
+
const options = parseOptions(rest, { "--gpu": { type: "boolean", default: false } });
|
|
116
|
+
console.log(JSON.stringify(await setupLocalRuntime({ gpu: options["--gpu"] }), null, 2));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (command === "publish") return await publishCommand(rest);
|
|
120
|
+
if (command === "run") return await runCommand(rest);
|
|
121
|
+
if (command === "compile") return await compileCommand(rest);
|
|
122
|
+
if (command === "validate") return await validateCommand(rest);
|
|
123
|
+
if (command === "research") return await researchCommand(rest);
|
|
124
|
+
if (command === "contract") return await contractCommand(rest);
|
|
125
|
+
if (command === 'model' || command === 'compute' && rest[0] !== 'plan') {
|
|
126
|
+
return (await import('./settings/command.mjs')).settingsCommand(command, rest, parseOptions);
|
|
127
|
+
}
|
|
128
|
+
if (command === "compute") return await computeCommand(rest);
|
|
129
|
+
if (command === "assets") return await assetsCommand(rest);
|
|
130
|
+
if (command === "evidence") return await evidenceCommand(rest);
|
|
131
|
+
if (command === "pipeline") return await pipelineCommand(rest);
|
|
132
|
+
if (command === "cap") return await capCommand(rest);
|
|
133
|
+
if (command === "parsers") return parsersCommand();
|
|
134
|
+
if (command === "doctor") return await doctorCommand(rest);
|
|
135
|
+
if (command === "dashboard") return await dashboardCommand(rest);
|
|
136
|
+
if (command === "autodl") return await autoDlCommand(rest);
|
|
137
|
+
if (command === "init") return await initCommand(rest);
|
|
138
|
+
throw new CiteArkError(`Unknown command: ${command}\nRun citeark --help for usage.`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function deployCommand(argv) {
|
|
142
|
+
const reference = argv[0] && !argv[0].startsWith('-') ? argv.shift() : null;
|
|
143
|
+
const optionalAgent = Object.fromEntries(Object.entries(agentEntryOptions()).map(([key, value]) => [key, { ...value, required: false }]));
|
|
144
|
+
const options = parseOptions(argv, { ...optionalAgent,
|
|
145
|
+
"--repository-id": { type: "string" }, "--run": { type: "string" }, "--cap": { type: "string" },
|
|
146
|
+
"--platform": { type: "string", default: "https://citeark.co" },
|
|
147
|
+
"--work-dir": { type: "string" }, "--image": { type: "string" },
|
|
148
|
+
"--device": { type: "string", default: "auto" }, "--non-interactive": { type: "boolean", default: false },
|
|
149
|
+
"--signing-key": { type: "string" }, "--dry-run": { type: "boolean", default: false },
|
|
150
|
+
});
|
|
151
|
+
if ([reference, options['--repository-id'], options['--cap']].filter(Boolean).length !== 1) {
|
|
152
|
+
throw Error('Provide exactly one paper ID, --repository-id, or --cap.');
|
|
153
|
+
}
|
|
154
|
+
if (Number(process.versions.node.split('.')[0]) < 22) throw Error('Install Node.js 22 or later: https://nodejs.org/');
|
|
155
|
+
const dryRun = options['--dry-run'];
|
|
156
|
+
const interactive = !dryRun && !options['--non-interactive'] && Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
157
|
+
const { createTerminalPrompter, cancelled } = await import('./deployment/terminal.mjs');
|
|
158
|
+
const { fetchDeployment, chooseDeployment, readLocalPreferences, writeLocalPreferences,
|
|
159
|
+
configureLocalModel, ensureGuidedEnvironment, describeDeployment } = await import('./deployment/guided.mjs');
|
|
160
|
+
const prompt = interactive ? createTerminalPrompter() : null;
|
|
161
|
+
let repositoryId = options['--repository-id'] ?? reference;
|
|
162
|
+
let route;
|
|
163
|
+
if (repositoryId) {
|
|
164
|
+
const data = await fetchDeployment(repositoryId, { baseUrl: options['--platform'] });
|
|
165
|
+
repositoryId = data.repositoryId ?? repositoryId;
|
|
166
|
+
console.log(`\nCiteArk · ${data.title ?? repositoryId}`);
|
|
167
|
+
route = await chooseDeployment(data, { runId: options['--run'], prompt });
|
|
168
|
+
}
|
|
169
|
+
if (options['--api-key'] && options['--api-key-env']) throw Error('Provide either --api-key or --api-key-env.');
|
|
170
|
+
if (options['--api-key-env'] && !process.env[options['--api-key-env']] && !dryRun) throw Error(`Environment variable ${options['--api-key-env']} is not set`);
|
|
171
|
+
const explicitRuntime = {
|
|
172
|
+
runtime: options['--agent'], apiBaseUrl: options['--api-base-url'], model: options['--model'],
|
|
173
|
+
apiKey: options['--api-key'] ?? process.env[options['--api-key-env']],
|
|
174
|
+
apiKeySource: options['--api-key-env'] ? `env:${options['--api-key-env']}` : undefined,
|
|
175
|
+
subagentModel: options['--subagent-model'],
|
|
176
|
+
};
|
|
177
|
+
let agentRuntime;
|
|
178
|
+
if (!interactive) {
|
|
179
|
+
if (!dryRun && (!explicitRuntime.apiBaseUrl || !explicitRuntime.model)) {
|
|
180
|
+
throw Error('Use an interactive terminal to configure the model, or pass --api-base-url, --model, and --api-key-env. Use --dry-run to inspect inputs.');
|
|
181
|
+
}
|
|
182
|
+
agentRuntime = agentRuntimeOptions({ ...options, '--agent': options['--agent'] ?? 'opencode',
|
|
183
|
+
'--api-base-url': options['--api-base-url'] ?? 'https://api.invalid', '--model': options['--model'] ?? 'dry-run' }, dryRun);
|
|
184
|
+
}
|
|
185
|
+
const workDirectory = options['--work-dir'] ?? path.join(process.cwd(), `citeark-${(reference ?? 'run').replace(/[^a-zA-Z0-9-]/g, '').slice(0, 40)}-${Date.now()}`);
|
|
186
|
+
const result = await deployLocally({ repositoryId, runId: route?.runId ?? options['--run'], capPath: options['--cap'],
|
|
187
|
+
baseUrl: options['--platform'], workDirectory, image: options['--image'], device: options['--device'],
|
|
188
|
+
signingKeyPath: options['--signing-key'], dryRun, agentRuntime,
|
|
189
|
+
prepareExecution: prompt ? async context => {
|
|
190
|
+
describeDeployment({ ...context, route });
|
|
191
|
+
const localPreflight = await ensureGuidedEnvironment({ ...context, prompt });
|
|
192
|
+
const configured = await configureLocalModel({ options: explicitRuntime, saved: await readLocalPreferences(), prompt });
|
|
193
|
+
console.log(`\nModel: ${configured.model}\nDirectory: ${context.directory}`);
|
|
194
|
+
console.log('This will download research materials and run experiments using your model provider.');
|
|
195
|
+
if (!await prompt.confirm('Start local reproduction?')) throw cancelled();
|
|
196
|
+
await writeLocalPreferences(configured);
|
|
197
|
+
return { agentRuntime: configured, localPreflight };
|
|
198
|
+
} : undefined,
|
|
199
|
+
});
|
|
200
|
+
console.log(result.dryRun ? `Prepared (dry run): ${result.runDirectory}` : `Signed local run: ${result.archive}\nAssessment: ${result.conclusion}`);
|
|
201
|
+
if (prompt && repositoryId && await prompt.confirm('Upload this result to CiteArk?')) {
|
|
202
|
+
const token = process.env.CITEARK_API_KEY ?? await prompt.ask('CiteArk API key (write access required; hidden)', { secret: true });
|
|
203
|
+
console.log(JSON.stringify(await publishLocalCap({ capPath: result.archive, repositoryId, baseUrl: options['--platform'], token }), null, 2));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function publishCommand(argv) {
|
|
208
|
+
const options = parseOptions(argv, { "--cap": { type: "string", required: true },
|
|
209
|
+
"--repository-id": { type: "string" },
|
|
210
|
+
"--plan": { type: "string" }, "--visibility": { type: "string" },
|
|
211
|
+
"--platform": { type: "string", default: "https://citeark.co" },
|
|
212
|
+
"--token-env": { type: "string", default: "CITEARK_API_KEY" }, });
|
|
213
|
+
if (options['--plan']) await publishLocalCap({ capPath: options['--plan'], repositoryId: options['--repository-id'],
|
|
214
|
+
baseUrl: options['--platform'], token: process.env[options['--token-env']], visibility: options['--visibility'] });
|
|
215
|
+
console.log(JSON.stringify(await publishLocalCap({ capPath: options["--cap"], repositoryId: options["--repository-id"],
|
|
216
|
+
baseUrl: options["--platform"], token: process.env[options["--token-env"]], visibility: options["--visibility"] }), null, 2));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function compileCommand(argv) {
|
|
220
|
+
const options = parseOptions(argv, {
|
|
221
|
+
...agentEntryOptions(),
|
|
222
|
+
"--task": { type: "string", required: true },
|
|
223
|
+
"--runs-dir": { type: "string", default: ".citeark/compilations" },
|
|
224
|
+
"--run-id": { type: "string" },
|
|
225
|
+
"--image": { type: "string" },
|
|
226
|
+
"--cap-output": { type: "string" },
|
|
227
|
+
"--signing-key": { type: "string" },
|
|
228
|
+
"--dry-run": { type: "boolean", default: false },
|
|
229
|
+
});
|
|
230
|
+
const compilation = await runResearchCompiler({
|
|
231
|
+
taskPath: options["--task"],
|
|
232
|
+
runsDirectory: options["--runs-dir"],
|
|
233
|
+
runId: options["--run-id"],
|
|
234
|
+
imageOverride: options["--image"],
|
|
235
|
+
agentRuntime: agentRuntimeOptions(options, options["--dry-run"]),
|
|
236
|
+
dryRun: options["--dry-run"],
|
|
237
|
+
});
|
|
238
|
+
if (compilation.dryRun) {
|
|
239
|
+
console.log("CiteArk Research Compiler Run bundle prepared (dry run):");
|
|
240
|
+
console.log(`Run directory: ${compilation.bundle.directories.run}`);
|
|
241
|
+
console.log(`Command: ${compilation.invocation.printable}`);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
console.log("Research compilation: completed");
|
|
245
|
+
console.log(`Research: ${path.join(compilation.bundle.directories.output, "research.normalized.json")}`);
|
|
246
|
+
if (compilation.research.compilationStage === "inventory") {
|
|
247
|
+
const capDirectory = path.join(compilation.bundle.directories.run, "research-compilation-cap");
|
|
248
|
+
const built = await assembleResearchCompilationCap({
|
|
249
|
+
directory: capDirectory,
|
|
250
|
+
inventory: compilation.research,
|
|
251
|
+
compiler: {
|
|
252
|
+
id: "citeark/compiler",
|
|
253
|
+
name: "CiteArk Research Compiler",
|
|
254
|
+
version: compilation.research.provenance?.compiler,
|
|
255
|
+
},
|
|
256
|
+
runId: compilation.bundle.runId,
|
|
257
|
+
createdAt: compilation.bundle.state.finishedAt,
|
|
258
|
+
signingKeyPath: options["--signing-key"],
|
|
259
|
+
});
|
|
260
|
+
const outputPath = path.resolve(
|
|
261
|
+
options["--cap-output"]
|
|
262
|
+
?? path.join(compilation.bundle.directories.run, "research-compilation.cap"),
|
|
263
|
+
);
|
|
264
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
265
|
+
const archive = await packCap({ directory: capDirectory, outputPath });
|
|
266
|
+
console.log(`Compilation CAP: ${archive.path}`);
|
|
267
|
+
console.log(`Compilation Artifact Digest: ${built.artifactDigest}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function runCommand(argv) {
|
|
272
|
+
const options = parseOptions(argv, {
|
|
273
|
+
...agentEntryOptions(),
|
|
274
|
+
...gcpEntryOptions(),
|
|
275
|
+
...autoDlEntryOptions(),
|
|
276
|
+
"--task": { type: "string", required: true },
|
|
277
|
+
"--runs-dir": { type: "string", default: ".citeark/runs" },
|
|
278
|
+
"--image": { type: "string" },
|
|
279
|
+
"--run-id": { type: "string" },
|
|
280
|
+
"--compute-decision": { type: "string" },
|
|
281
|
+
"--dry-run": { type: "boolean", default: false },
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const computeDecision = options["--compute-decision"] ? await loadComputeDecision(options["--compute-decision"]) : null;
|
|
285
|
+
const usesRemoteSecret = new Set(["gcp-batch", "autodl-pro"])
|
|
286
|
+
.has(computeDecision?.selectedProfile?.executor);
|
|
287
|
+
const execution = await executeScheduledReproduction({
|
|
288
|
+
taskPath: options["--task"],
|
|
289
|
+
runsDirectory: options["--runs-dir"],
|
|
290
|
+
runId: options["--run-id"],
|
|
291
|
+
imageOverride: options["--image"],
|
|
292
|
+
computeDecision,
|
|
293
|
+
agentRuntime: agentRuntimeOptions(options, options["--dry-run"], { allowGcpSecret: usesRemoteSecret }),
|
|
294
|
+
executorOptions: executorOptions(options),
|
|
295
|
+
dryRun: options["--dry-run"],
|
|
296
|
+
progress: (message) => console.log(`\n${message}`),
|
|
297
|
+
});
|
|
298
|
+
if (execution.dryRun) {
|
|
299
|
+
console.log("\nCiteArk Agent Run bundle prepared (dry run):");
|
|
300
|
+
console.log(`Run ID: ${execution.bundle.runId}`);
|
|
301
|
+
console.log(`Run directory: ${execution.bundle.directories.run}`);
|
|
302
|
+
console.log(`Command: ${execution.invocation.printable}`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
console.log("\nCiteArk Agent Run finished:");
|
|
306
|
+
console.log(`Status: ${execution.runStatus}`);
|
|
307
|
+
console.log("Research artifacts are generated by the full pipeline under the Research Plan CAP.");
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function validateCommand(argv) {
|
|
311
|
+
const options = parseOptions(argv, {
|
|
312
|
+
"--task": { type: "string", required: true },
|
|
313
|
+
"--result": { type: "string", required: true },
|
|
314
|
+
"--output-dir": { type: "string" },
|
|
315
|
+
});
|
|
316
|
+
const { task } = await loadAndNormalizeTask(options["--task"]);
|
|
317
|
+
const resultPath = path.resolve(options["--result"]);
|
|
318
|
+
const outputDirectory = path.resolve(
|
|
319
|
+
options["--output-dir"] ?? path.dirname(resultPath),
|
|
320
|
+
);
|
|
321
|
+
const validation = await validateResultFile(resultPath, task, outputDirectory);
|
|
322
|
+
if (validation.issues.length > 0) {
|
|
323
|
+
throw new CiteArkError(
|
|
324
|
+
`Result validation failed: \n- ${validation.issues.join("\n- ")}`,
|
|
325
|
+
{ exitCode: 2 },
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
console.log("Result protocol: valid");
|
|
329
|
+
if (validation.protocolVerification) {
|
|
330
|
+
console.log(`Verification: ${validation.protocolVerification.status}`);
|
|
331
|
+
console.log(`Absolute difference: ${validation.protocolVerification.absoluteDifference}`);
|
|
332
|
+
} else {
|
|
333
|
+
console.log("Verification: deferred to the independent verification engine");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
async function researchCommand(argv) {
|
|
338
|
+
const [subcommand, ...rest] = argv;
|
|
339
|
+
if (subcommand !== "validate") throw new CiteArkError("Usage: citeark research validate --input <research.json> [--output <normalized.json>]");
|
|
340
|
+
const options = parseOptions(rest, {
|
|
341
|
+
"--input": { type: "string", required: true },
|
|
342
|
+
"--output": { type: "string" },
|
|
343
|
+
});
|
|
344
|
+
const output = options["--output"] ?? options["--input"];
|
|
345
|
+
const research = await normalizeResearchFile(options["--input"], output);
|
|
346
|
+
console.log(`Research structure: valid (${research.claims.length} claims, ${research.experiments.length} experiments)`);
|
|
347
|
+
console.log(`Normalized: ${path.resolve(output)}`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function contractCommand(argv) {
|
|
351
|
+
const [subcommand, ...rest] = argv;
|
|
352
|
+
if (subcommand !== "create") throw new CiteArkError("Usage: citeark contract create --research <research.json> --claim <id> --output <contract.json> --policy <private.json> --tolerance <number>");
|
|
353
|
+
const options = parseOptions(rest, {
|
|
354
|
+
"--research": { type: "string", required: true },
|
|
355
|
+
"--claim": { type: "string", required: true },
|
|
356
|
+
"--experiment": { type: "string" },
|
|
357
|
+
"--output": { type: "string", required: true },
|
|
358
|
+
"--policy": { type: "string", required: true },
|
|
359
|
+
"--tolerance": { type: "string", required: true },
|
|
360
|
+
});
|
|
361
|
+
const { contract, policy } = await createExecutionContract({
|
|
362
|
+
researchPath: options["--research"],
|
|
363
|
+
claimId: options["--claim"],
|
|
364
|
+
experimentId: options["--experiment"],
|
|
365
|
+
outputPath: options["--output"],
|
|
366
|
+
policyPath: options["--policy"],
|
|
367
|
+
tolerance: options["--tolerance"],
|
|
368
|
+
});
|
|
369
|
+
console.log(`Execution contract: ${path.resolve(options["--output"])}`);
|
|
370
|
+
console.log(`Private policy: ${path.resolve(options["--policy"])}`);
|
|
371
|
+
console.log(`Contract digest: ${contract.contractDigest}`);
|
|
372
|
+
console.log(`Policy digest: ${policy.policyDigest}`);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
async function computeCommand(argv) {
|
|
376
|
+
const [subcommand, ...rest] = argv;
|
|
377
|
+
if (subcommand !== "plan") throw new CiteArkError("Usage: citeark compute plan --research <research.json> --experiment <id> [--contract <contract.json>] [--catalog <catalog.json>] [--policy <policy.json>] [--profile <id>] [--output <decision.json>]");
|
|
378
|
+
const options = parseOptions(rest, {
|
|
379
|
+
"--research": { type: "string", required: true },
|
|
380
|
+
"--experiment": { type: "string", required: true },
|
|
381
|
+
"--contract": { type: "string" },
|
|
382
|
+
"--catalog": { type: "string" },
|
|
383
|
+
"--policy": { type: "string" },
|
|
384
|
+
"--profile": { type: "string" },
|
|
385
|
+
"--output": { type: "string" },
|
|
386
|
+
});
|
|
387
|
+
const [research, catalog, policy, contract] = await Promise.all([
|
|
388
|
+
loadResearchStructure(options["--research"]),
|
|
389
|
+
loadComputeCatalog(options["--catalog"]),
|
|
390
|
+
loadComputePolicy(options["--policy"]),
|
|
391
|
+
options["--contract"] ? loadExecutionContract(options["--contract"]) : null,
|
|
392
|
+
]);
|
|
393
|
+
const experiment = research.experiments.find((item) => item.id === options["--experiment"]);
|
|
394
|
+
if (!experiment) throw new CiteArkError(`Experiment not found: ${options["--experiment"]}`);
|
|
395
|
+
const decision = await scheduleCompute({
|
|
396
|
+
experiment,
|
|
397
|
+
contract,
|
|
398
|
+
catalog,
|
|
399
|
+
policy,
|
|
400
|
+
profileOverride: options["--profile"],
|
|
401
|
+
outputPath: options["--output"],
|
|
402
|
+
});
|
|
403
|
+
console.log(`Compute class: ${decision.requirement.classification}`);
|
|
404
|
+
console.log(`Selected profile: ${decision.selectedProfile.id}`);
|
|
405
|
+
console.log(`Executor: ${decision.selectedProfile.executor}`);
|
|
406
|
+
console.log(`Estimated cost: ${decision.estimate.costUsd ?? "unknown"} USD`);
|
|
407
|
+
if (options["--output"]) console.log(`Decision: ${path.resolve(options["--output"])}`);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
async function evidenceCommand(argv) {
|
|
411
|
+
const [subcommand, ...rest] = argv;
|
|
412
|
+
if (subcommand !== "parse") throw new CiteArkError("Usage: citeark evidence parse --contract <contract.json> --output-dir <run/output> --metrics <metrics.json>");
|
|
413
|
+
const options = parseOptions(rest, {
|
|
414
|
+
"--contract": { type: "string", required: true },
|
|
415
|
+
"--output-dir": { type: "string", required: true },
|
|
416
|
+
"--metrics": { type: "string", required: true },
|
|
417
|
+
});
|
|
418
|
+
const contract = await loadExecutionContract(options["--contract"]);
|
|
419
|
+
const { resolveResearchPlan } = await import("./reproduction/plan.mjs");
|
|
420
|
+
const effectiveContract = await resolveResearchPlan(contract, options["--output-dir"]);
|
|
421
|
+
const metrics = await parseContractEvidence({ contract: effectiveContract, outputDirectory: options["--output-dir"], metricsPath: options["--metrics"] });
|
|
422
|
+
const measurement = metrics.measurements?.[0] ?? metrics;
|
|
423
|
+
const primary = primaryMetric(metrics);
|
|
424
|
+
console.log(`Evidence parser: ${measurement.parser.id}@${measurement.parser.version}`);
|
|
425
|
+
console.log(`Primary metric: ${primary.metric}=${primary.value} ${primary.unit}`);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
async function pipelineCommand(argv) {
|
|
429
|
+
const [subcommand, ...rest] = argv;
|
|
430
|
+
if (subcommand !== "execute") throw new CiteArkError("Usage: citeark pipeline execute ...");
|
|
431
|
+
return await pipelineExecuteCommand(rest);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
async function pipelineExecuteCommand(argv, { forcedStopAfter } = {}) {
|
|
435
|
+
const options = parseOptions(argv, {
|
|
436
|
+
...agentEntryOptions(),
|
|
437
|
+
...gcpEntryOptions(),
|
|
438
|
+
...autoDlEntryOptions(),
|
|
439
|
+
"--compile-task": { type: "string" },
|
|
440
|
+
"--research": { type: "string" },
|
|
441
|
+
"--compilation": { type: "string" },
|
|
442
|
+
"--paper": { type: "string" },
|
|
443
|
+
"--claim": { type: "string" },
|
|
444
|
+
"--experiment": { type: "string" },
|
|
445
|
+
"--tolerance": { type: "string", required: true },
|
|
446
|
+
"--work-dir": { type: "string", required: true },
|
|
447
|
+
"--resume": { type: "boolean", default: false },
|
|
448
|
+
"--signing-key": { type: "string" },
|
|
449
|
+
"--compute-catalog": { type: "string" },
|
|
450
|
+
"--compute-policy": { type: "string" },
|
|
451
|
+
"--compute-profile": { type: "string" },
|
|
452
|
+
"--dataset-registry": { type: "string" },
|
|
453
|
+
"--repository": { type: "string" },
|
|
454
|
+
"--stop-after": { type: "string" },
|
|
455
|
+
"--dry-run": { type: "boolean", default: false },
|
|
456
|
+
});
|
|
457
|
+
if (forcedStopAfter && options["--stop-after"] && options["--stop-after"] !== forcedStopAfter) {
|
|
458
|
+
throw new CiteArkError(`assets prepare stops at ${forcedStopAfter}`);
|
|
459
|
+
}
|
|
460
|
+
const stopAfter = forcedStopAfter ?? options["--stop-after"];
|
|
461
|
+
const pipeline = await executeFullPipeline({
|
|
462
|
+
compileTaskPath: options["--compile-task"],
|
|
463
|
+
researchPath: options["--research"],
|
|
464
|
+
compilationArtifactPath: options["--compilation"],
|
|
465
|
+
paperPath: options["--paper"],
|
|
466
|
+
claimId: options["--claim"],
|
|
467
|
+
experimentId: options["--experiment"],
|
|
468
|
+
tolerance: options["--tolerance"],
|
|
469
|
+
workDirectory: options["--work-dir"],
|
|
470
|
+
resume: options["--resume"],
|
|
471
|
+
signingKeyPath: options["--signing-key"],
|
|
472
|
+
computeCatalogPath: options["--compute-catalog"],
|
|
473
|
+
computePolicyPath: options["--compute-policy"],
|
|
474
|
+
computeProfile: options["--compute-profile"],
|
|
475
|
+
datasetRegistryPath: options["--dataset-registry"],
|
|
476
|
+
repositoryPath: options["--repository"],
|
|
477
|
+
stopAfter,
|
|
478
|
+
agentRuntime: agentRuntimeOptions(options, options["--dry-run"], { allowGcpSecret: true }),
|
|
479
|
+
executorOptions: executorOptions(options),
|
|
480
|
+
dryRun: options["--dry-run"],
|
|
481
|
+
progress: (message) => console.log(message),
|
|
482
|
+
});
|
|
483
|
+
if (pipeline.dryRun) {
|
|
484
|
+
console.log(stopAfter === ASSET_QUALIFICATION_BOUNDARY
|
|
485
|
+
? `Asset preparation bundle ready (dry run): ${pipeline.directories.root}`
|
|
486
|
+
: `Pipeline prepared: ${pipeline.directories.root}`);
|
|
487
|
+
if (pipeline.compilationArtifact) {
|
|
488
|
+
console.log(`Input Compilation Artifact: ${pipeline.compilationArtifact.artifactDigest}`);
|
|
489
|
+
}
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (stopAfter === ASSET_QUALIFICATION_BOUNDARY) {
|
|
493
|
+
console.log("Asset checks passed");
|
|
494
|
+
console.log("Research execution not started");
|
|
495
|
+
console.log(`Plan digest: ${pipeline.qualification.planDigest}`);
|
|
496
|
+
console.log(`Manifest digest: ${pipeline.qualification.manifestDigest}`);
|
|
497
|
+
console.log(`Cache hit: ${pipeline.qualification.cacheHit}`);
|
|
498
|
+
console.log(`Checkpoint: ${pipeline.qualification.checkpointPrefix}`);
|
|
499
|
+
console.log(`Evidence: ${path.join(pipeline.directories.protocol, "asset-qualification.json")}`);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
console.log(`Pipeline: ${pipeline.state.status}`);
|
|
503
|
+
console.log(`Verification: ${pipeline.replay.assessment.verificationStatus}`);
|
|
504
|
+
console.log(`CAP: ${pipeline.directories.cap}`);
|
|
505
|
+
console.log(`CAP file: ${pipeline.archive.path}`);
|
|
506
|
+
console.log(`Archive SHA-256: ${pipeline.archive.sha256}`);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async function assetsCommand(argv) {
|
|
510
|
+
const [subcommand, ...rest] = argv;
|
|
511
|
+
if (subcommand === "prepare") {
|
|
512
|
+
return await pipelineExecuteCommand(rest, {
|
|
513
|
+
forcedStopAfter: ASSET_QUALIFICATION_BOUNDARY,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
if (subcommand === "verify") {
|
|
517
|
+
const options = parseOptions(rest, {
|
|
518
|
+
"--plan": { type: "string", required: true },
|
|
519
|
+
"--manifest": { type: "string", required: true },
|
|
520
|
+
});
|
|
521
|
+
const verification = await verifyAssetQualification({
|
|
522
|
+
planPath: options["--plan"],
|
|
523
|
+
manifestPath: options["--manifest"],
|
|
524
|
+
});
|
|
525
|
+
if (!verification.valid) {
|
|
526
|
+
throw new CiteArkError(`Invalid asset manifest: \n- ${verification.issues.join("\n- ")}`, {
|
|
527
|
+
exitCode: 2,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
console.log("Asset manifest valid");
|
|
531
|
+
console.log(`Plan digest: ${verification.plan.planDigest}`);
|
|
532
|
+
console.log(`Manifest digest: ${verification.manifest.manifestDigest}`);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (!new Set(["plan", "probe"]).has(subcommand)) {
|
|
536
|
+
throw new CiteArkError("Usage: citeark assets plan|probe|prepare|verify ...");
|
|
537
|
+
}
|
|
538
|
+
const options = parseOptions(rest, {
|
|
539
|
+
"--research": { type: "string", required: true },
|
|
540
|
+
"--claim": { type: "string" },
|
|
541
|
+
"--experiment": { type: "string" },
|
|
542
|
+
"--dataset-registry": { type: "string" },
|
|
543
|
+
"--output": { type: "string" },
|
|
544
|
+
});
|
|
545
|
+
const context = await loadAssetQualificationContext({
|
|
546
|
+
researchPath: options["--research"],
|
|
547
|
+
claimId: options["--claim"],
|
|
548
|
+
experimentId: options["--experiment"],
|
|
549
|
+
datasetRegistryPath: options["--dataset-registry"],
|
|
550
|
+
});
|
|
551
|
+
if (subcommand === "plan") {
|
|
552
|
+
const { plan, failures } = planAssetQualification(context);
|
|
553
|
+
if (options["--output"]) await writeJson(options["--output"], plan);
|
|
554
|
+
console.log(`Assets: ${plan.summary.assetCount}`);
|
|
555
|
+
console.log(`Prepared assets: ${plan.summary.prepareCount}`);
|
|
556
|
+
console.log(`Streamed assets: ${plan.summary.streamCount}`);
|
|
557
|
+
console.log(`Metadata only: ${plan.summary.metadataOnlyCount}`);
|
|
558
|
+
console.log(`Over budget: ${plan.summary.blockedCount}`);
|
|
559
|
+
console.log(`Estimated download: ${plan.summary.expectedDownloadBytes} bytes`);
|
|
560
|
+
if (options["--output"]) console.log(`Plan: ${path.resolve(options["--output"])}`);
|
|
561
|
+
for (const failure of failures) console.log(`Blocked: ${failure.reasonCode} ${failure.message}`);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const admission = await probeAssetQualification({
|
|
565
|
+
...context,
|
|
566
|
+
outputPath: options["--output"],
|
|
567
|
+
});
|
|
568
|
+
console.log(`Ready targets: ${admission.summary.admittedTargetCount}/${admission.summary.targetCount}`);
|
|
569
|
+
console.log(`Blocked targets: ${admission.summary.blockedTargetCount}`);
|
|
570
|
+
console.log(`Retryable targets: ${admission.summary.retryableTargetCount}`);
|
|
571
|
+
console.log(`URL request attempts: ${admission.summary.requestAttemptCount}`);
|
|
572
|
+
if (options["--output"]) console.log(`Probe: ${path.resolve(options["--output"])}`);
|
|
573
|
+
if (admission.summary.admittedTargetCount !== admission.summary.targetCount) process.exitCode = 2;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
async function capCommand(argv) {
|
|
577
|
+
const [subcommand, ...rest] = argv;
|
|
578
|
+
if (subcommand === "import-paper2agent") {
|
|
579
|
+
const options = parseOptions(rest, {
|
|
580
|
+
"--delivery": { type: "string", required: true },
|
|
581
|
+
"--inventory": { type: "string", required: true },
|
|
582
|
+
"--paper2agent-version": { type: "string" },
|
|
583
|
+
"--run-id": { type: "string" },
|
|
584
|
+
"--signing-key": { type: "string" },
|
|
585
|
+
"--output": { type: "string", required: true },
|
|
586
|
+
});
|
|
587
|
+
const inventory = await loadResearchStructure(options["--inventory"]);
|
|
588
|
+
const temporary = await mkdtemp(path.join(os.tmpdir(), "citeark-import-paper2agent-"));
|
|
589
|
+
try {
|
|
590
|
+
const artifactDirectory = path.join(temporary, "artifact");
|
|
591
|
+
const built = await assemblePaper2AgentCompilationCap({
|
|
592
|
+
directory: artifactDirectory,
|
|
593
|
+
inventory,
|
|
594
|
+
deliveryPath: options["--delivery"],
|
|
595
|
+
paper2AgentVersion: options["--paper2agent-version"],
|
|
596
|
+
runId: options["--run-id"] ?? createRunId(),
|
|
597
|
+
signingKeyPath: options["--signing-key"],
|
|
598
|
+
});
|
|
599
|
+
const outputPath = path.resolve(options["--output"]);
|
|
600
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
601
|
+
const archive = await packCap({ directory: artifactDirectory, outputPath });
|
|
602
|
+
console.log(`Paper2Agent delivery: ${built.delivery.kind}`);
|
|
603
|
+
console.log(`Compilation CAP: ${archive.path}`);
|
|
604
|
+
console.log(`Artifact Digest: ${built.artifactDigest}`);
|
|
605
|
+
return;
|
|
606
|
+
} finally {
|
|
607
|
+
await rm(temporary, { recursive: true, force: true });
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (subcommand === "create-compilation") {
|
|
611
|
+
const options = parseOptions(rest, {
|
|
612
|
+
"--inventory": { type: "string", required: true },
|
|
613
|
+
"--compiler-id": { type: "string", required: true },
|
|
614
|
+
"--compiler-name": { type: "string", required: true },
|
|
615
|
+
"--compiler-version": { type: "string" },
|
|
616
|
+
"--run-id": { type: "string" },
|
|
617
|
+
"--signing-key": { type: "string" },
|
|
618
|
+
"--output": { type: "string", required: true },
|
|
619
|
+
});
|
|
620
|
+
const inventory = await loadResearchStructure(options["--inventory"]);
|
|
621
|
+
const temporary = await mkdtemp(path.join(os.tmpdir(), "citeark-create-compilation-"));
|
|
622
|
+
try {
|
|
623
|
+
const built = await assembleResearchCompilationCap({
|
|
624
|
+
directory: path.join(temporary, "artifact"),
|
|
625
|
+
inventory,
|
|
626
|
+
compiler: {
|
|
627
|
+
id: options["--compiler-id"],
|
|
628
|
+
name: options["--compiler-name"],
|
|
629
|
+
version: options["--compiler-version"],
|
|
630
|
+
},
|
|
631
|
+
runId: options["--run-id"] ?? createRunId(),
|
|
632
|
+
signingKeyPath: options["--signing-key"],
|
|
633
|
+
});
|
|
634
|
+
const outputPath = path.resolve(options["--output"]);
|
|
635
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
636
|
+
const archive = await packCap({
|
|
637
|
+
directory: path.join(temporary, "artifact"),
|
|
638
|
+
outputPath,
|
|
639
|
+
});
|
|
640
|
+
console.log(`Compilation CAP: ${archive.path}`);
|
|
641
|
+
console.log(`Artifact Digest: ${built.artifactDigest}`);
|
|
642
|
+
return;
|
|
643
|
+
} finally {
|
|
644
|
+
await rm(temporary, { recursive: true, force: true });
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (subcommand === "pack") {
|
|
648
|
+
const options = parseOptions(rest, {
|
|
649
|
+
"--dir": { type: "string", required: true },
|
|
650
|
+
"--output": { type: "string", required: true },
|
|
651
|
+
});
|
|
652
|
+
const source = path.resolve(options["--dir"]);
|
|
653
|
+
const destination = path.resolve(options["--output"]);
|
|
654
|
+
const archive = await packCap({ directory: source, outputPath: destination });
|
|
655
|
+
console.log(`CAP file: ${archive.path}`);
|
|
656
|
+
console.log(`Archive SHA-256: ${archive.sha256}`);
|
|
657
|
+
console.log(`Artifact Digest: ${archive.artifactDigest}`);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
if (subcommand !== "verify") {
|
|
661
|
+
throw new CiteArkError("Usage: citeark cap import-paper2agent|create-compilation|pack|verify ...");
|
|
662
|
+
}
|
|
663
|
+
const options = parseOptions(rest, {
|
|
664
|
+
"--dir": { type: "string" },
|
|
665
|
+
"--file": { type: "string" },
|
|
666
|
+
});
|
|
667
|
+
if (Boolean(options["--dir"]) === Boolean(options["--file"])) {
|
|
668
|
+
throw new CiteArkError("cap verify requires exactly one of --dir or --file");
|
|
669
|
+
}
|
|
670
|
+
const report = options["--file"]
|
|
671
|
+
? await verifyCapArchive(path.resolve(options["--file"]))
|
|
672
|
+
: await verifyCapDirectory(path.resolve(options["--dir"]));
|
|
673
|
+
if (!report.valid) throw new CiteArkError(`CAP validation failed: \n- ${report.issues.join("\n- ")}`, { exitCode: 2 });
|
|
674
|
+
console.log("CAP: valid");
|
|
675
|
+
console.log(`Protocol: ${report.protocolVersion}`);
|
|
676
|
+
console.log(`Artifact Digest: ${report.artifactDigest}`);
|
|
677
|
+
console.log(`Profiles: ${report.manifest.profiles.join(", ")}`);
|
|
678
|
+
console.log(`Valid signatures: ${report.attestations.filter((item) => item.signatureValid && item.subjectValid).length}`);
|
|
679
|
+
if (report.archive) console.log(`Archive SHA-256: ${report.archive.sha256}`);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function parsersCommand() {
|
|
683
|
+
for (const parser of listEvidenceParsers()) console.log(`${parser.id}@${parser.version}`);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
async function autoDlCommand(argv) {
|
|
687
|
+
const [subcommand, ...rest] = argv;
|
|
688
|
+
if (!new Set([
|
|
689
|
+
"list",
|
|
690
|
+
"images",
|
|
691
|
+
"status",
|
|
692
|
+
"start",
|
|
693
|
+
"stop",
|
|
694
|
+
"release",
|
|
695
|
+
"bootstrap",
|
|
696
|
+
"save-image",
|
|
697
|
+
]).has(subcommand)) {
|
|
698
|
+
throw new CiteArkError(
|
|
699
|
+
"Usage: citeark autodl list|images|status|start|stop|release|bootstrap|save-image [--instance <uuid>] [--token-env AUTODL_API_TOKEN]",
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
const needsInstance = !new Set(["list", "images"]).has(subcommand);
|
|
703
|
+
const options = parseOptions(rest, {
|
|
704
|
+
"--instance": { type: "string", required: needsInstance },
|
|
705
|
+
"--token-env": { type: "string", default: "AUTODL_API_TOKEN" },
|
|
706
|
+
"--token-stdin": { type: "boolean", default: false },
|
|
707
|
+
"--confirm": { type: "string" },
|
|
708
|
+
"--image-name": { type: "string" },
|
|
709
|
+
"--save-as": { type: "string" },
|
|
710
|
+
});
|
|
711
|
+
const token = options["--token-stdin"]
|
|
712
|
+
? await readSecretFromStdin()
|
|
713
|
+
: process.env[options["--token-env"]];
|
|
714
|
+
if (!token) {
|
|
715
|
+
throw new CiteArkError(
|
|
716
|
+
options["--token-stdin"]
|
|
717
|
+
? "No AutoDL token received on stdin"
|
|
718
|
+
: `Environment variable ${options["--token-env"]} is not set`,
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
const client = new AutoDlProClient({ token });
|
|
722
|
+
const instanceUuid = options["--instance"];
|
|
723
|
+
if (subcommand === "list") {
|
|
724
|
+
const result = await client.listInstances();
|
|
725
|
+
const instances = Array.isArray(result?.list) ? result.list : [];
|
|
726
|
+
console.log(JSON.stringify(instances.map((instance) => ({
|
|
727
|
+
uuid: instance.uuid,
|
|
728
|
+
name: instance.name,
|
|
729
|
+
status: instance.status,
|
|
730
|
+
region: instance.region_name ?? instance.region_sign,
|
|
731
|
+
gpuSpecUuid: instance.gpu_spec_uuid,
|
|
732
|
+
gpuCount: instance.req_gpu_amount,
|
|
733
|
+
})), null, 2));
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
if (subcommand === "images") {
|
|
737
|
+
const result = await client.listPrivateImages();
|
|
738
|
+
const images = Array.isArray(result?.list) ? result.list : [];
|
|
739
|
+
console.log(JSON.stringify(images.map((image) => ({
|
|
740
|
+
imageUuid: image.image_uuid,
|
|
741
|
+
name: image.name,
|
|
742
|
+
status: image.status,
|
|
743
|
+
imageSize: image.image_size,
|
|
744
|
+
createdAt: image.create_at,
|
|
745
|
+
})), null, 2));
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
if (subcommand === "status") {
|
|
749
|
+
console.log(await client.getStatus(instanceUuid));
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (subcommand === "start") {
|
|
753
|
+
await client.powerOn(instanceUuid, { startCommand: "sleep infinity" });
|
|
754
|
+
console.log(`AutoDL instance start requested: ${instanceUuid}`);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (subcommand === "stop") {
|
|
758
|
+
await client.powerOff(instanceUuid);
|
|
759
|
+
console.log(`AutoDL instance stop requested: ${instanceUuid}`);
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (subcommand === "bootstrap") {
|
|
763
|
+
const connection = parseAutoDlSshConnection(
|
|
764
|
+
await client.getInstance(instanceUuid),
|
|
765
|
+
);
|
|
766
|
+
const ssh = new AutoDlSshClient(connection);
|
|
767
|
+
try {
|
|
768
|
+
await ssh.connect();
|
|
769
|
+
await Promise.all([
|
|
770
|
+
ssh.putFile(
|
|
771
|
+
path.join(PACKAGE_ROOT, "runtime", "bootstrap-autodl-runtime.sh"),
|
|
772
|
+
"/root/citeark-bootstrap-runtime.sh",
|
|
773
|
+
),
|
|
774
|
+
ssh.putFile(
|
|
775
|
+
path.join(PACKAGE_ROOT, "docker", "claude-code", "codex-pro-relay.mjs"),
|
|
776
|
+
"/root/codex-pro-relay.mjs",
|
|
777
|
+
),
|
|
778
|
+
ssh.putFile(
|
|
779
|
+
path.join(PACKAGE_ROOT, "runtime", "requirements-baseline.txt"),
|
|
780
|
+
"/root/citeark-requirements-baseline.txt",
|
|
781
|
+
),
|
|
782
|
+
ssh.putFile(
|
|
783
|
+
path.join(PACKAGE_ROOT, "runtime", "create-runtime-venv.sh"),
|
|
784
|
+
"/root/citeark-create-runtime-venv.sh",
|
|
785
|
+
),
|
|
786
|
+
]);
|
|
787
|
+
const result = await ssh.exec(
|
|
788
|
+
"chmod 0700 /root/citeark-bootstrap-runtime.sh && /root/citeark-bootstrap-runtime.sh",
|
|
789
|
+
{
|
|
790
|
+
onStdout: (text) => process.stdout.write(text),
|
|
791
|
+
onStderr: (text) => process.stderr.write(text),
|
|
792
|
+
},
|
|
793
|
+
);
|
|
794
|
+
if (result.code !== 0) {
|
|
795
|
+
throw new CiteArkError(`AutoDL runtime initialization failed (exit code ${result.code})`);
|
|
796
|
+
}
|
|
797
|
+
} finally {
|
|
798
|
+
ssh.close();
|
|
799
|
+
}
|
|
800
|
+
if (options["--save-as"]) {
|
|
801
|
+
await ensureAutoDlInstanceStopped(client, instanceUuid);
|
|
802
|
+
const saved = await client.saveInstanceImage(instanceUuid, options["--save-as"]);
|
|
803
|
+
console.log(`AutoDL private image save submitted: ${saved?.image_uuid ?? "waiting for AutoDL image ID"}`);
|
|
804
|
+
} else {
|
|
805
|
+
console.log("AutoDL runtime ready. Save a private image or run again with --save-as.");
|
|
806
|
+
}
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
if (subcommand === "save-image") {
|
|
810
|
+
if (!options["--image-name"]) {
|
|
811
|
+
throw new CiteArkError("save-image requires --image-name");
|
|
812
|
+
}
|
|
813
|
+
await ensureAutoDlInstanceStopped(client, instanceUuid);
|
|
814
|
+
const saved = await client.saveInstanceImage(instanceUuid, options["--image-name"]);
|
|
815
|
+
console.log(`AutoDL private image save submitted: ${saved?.image_uuid ?? "waiting for AutoDL image ID"}`);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
if (options["--confirm"] !== instanceUuid) {
|
|
819
|
+
throw new CiteArkError("Releasing an instance deletes its system disk. Pass the full instance UUID with --confirm.");
|
|
820
|
+
}
|
|
821
|
+
const status = String(await client.getStatus(instanceUuid)).toLowerCase();
|
|
822
|
+
if (!new Set(["stopped", "shutdown", "shutoff"]).has(status)) {
|
|
823
|
+
await client.powerOff(instanceUuid);
|
|
824
|
+
await client.waitForStatus(instanceUuid, ["stopped", "shutdown", "shutoff"]);
|
|
825
|
+
}
|
|
826
|
+
await client.release(instanceUuid);
|
|
827
|
+
console.log(`AutoDL instance released: ${instanceUuid}`);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
async function ensureAutoDlInstanceStopped(client, instanceUuid) {
|
|
831
|
+
const status = String(await client.getStatus(instanceUuid)).trim().toLowerCase();
|
|
832
|
+
if (new Set(["stopped", "shutdown", "shutoff"]).has(status)) return;
|
|
833
|
+
await client.powerOff(instanceUuid);
|
|
834
|
+
await client.waitForStatus(instanceUuid, ["stopped", "shutdown", "shutoff"]);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
async function readSecretFromStdin() {
|
|
838
|
+
const chunks = [];
|
|
839
|
+
let bytes = 0;
|
|
840
|
+
for await (const chunk of process.stdin) {
|
|
841
|
+
bytes += chunk.length;
|
|
842
|
+
if (bytes > 16 * 1024) throw new CiteArkError("The credential on stdin exceeds the size limit");
|
|
843
|
+
chunks.push(chunk);
|
|
844
|
+
}
|
|
845
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
async function doctorCommand(argv) {
|
|
849
|
+
const options = parseOptions(argv, {
|
|
850
|
+
"--image": {
|
|
851
|
+
type: "string",
|
|
852
|
+
default: "citeark-agent/runtime:cpu",
|
|
853
|
+
},
|
|
854
|
+
"--agent": { type: "string", default: "opencode" },
|
|
855
|
+
});
|
|
856
|
+
if (!new Set(["claude-code", "codex", "opencode"]).has(options["--agent"])) {
|
|
857
|
+
throw new CiteArkError("--agent must be claude-code, codex, or opencode");
|
|
858
|
+
}
|
|
859
|
+
const report = await dockerDoctor(options["--image"], options["--agent"]);
|
|
860
|
+
console.log(`Docker client: ${report.client ?? "unavailable"}`);
|
|
861
|
+
console.log(`Docker server: ${report.server ?? "unavailable"}`);
|
|
862
|
+
console.log(`Runtime image: ${report.image ?? "unavailable"}`);
|
|
863
|
+
console.log(`Agent runtime: ${options["--agent"]}`);
|
|
864
|
+
console.log(`Agent CLI: ${report.runtime ?? "unavailable"}`);
|
|
865
|
+
if (report.issues.length > 0) {
|
|
866
|
+
throw new CiteArkError(`Runtime not ready: \n- ${report.issues.join("\n- ")}`);
|
|
867
|
+
}
|
|
868
|
+
console.log("CiteArk Agent runtime: ready");
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
async function dashboardCommand(argv) {
|
|
872
|
+
const options = parseOptions(argv, {
|
|
873
|
+
"--pipelines-dir": { type: "string", default: ".citeark/pipelines" },
|
|
874
|
+
"--host": { type: "string", default: "127.0.0.1" },
|
|
875
|
+
"--port": { type: "string", default: "4310" },
|
|
876
|
+
});
|
|
877
|
+
const port = Number(options["--port"]);
|
|
878
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
879
|
+
throw new CiteArkError("--port must be an integer from 0 to 65535");
|
|
880
|
+
}
|
|
881
|
+
const dashboard = await startDashboardServer({
|
|
882
|
+
pipelinesDirectory: options["--pipelines-dir"],
|
|
883
|
+
host: options["--host"],
|
|
884
|
+
port,
|
|
885
|
+
});
|
|
886
|
+
console.log("CiteArk Agent dashboard started");
|
|
887
|
+
console.log(`URL: ${dashboard.url}`);
|
|
888
|
+
console.log(`Pipeline directory: ${dashboard.pipelinesDirectory}`);
|
|
889
|
+
console.log("Press Ctrl+C to stop");
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
async function initCommand(argv) {
|
|
893
|
+
const options = parseOptions(argv, {
|
|
894
|
+
"--dir": { type: "string", default: "citeark-agent-task" },
|
|
895
|
+
});
|
|
896
|
+
const destination = path.resolve(options["--dir"]);
|
|
897
|
+
await mkdir(destination, { recursive: true });
|
|
898
|
+
await cp(
|
|
899
|
+
path.join(PACKAGE_ROOT, "examples", "toy-evaluation", "task.json"),
|
|
900
|
+
path.join(destination, "task.json"),
|
|
901
|
+
);
|
|
902
|
+
await cp(
|
|
903
|
+
path.join(PACKAGE_ROOT, "examples", "toy-evaluation", "paper.md"),
|
|
904
|
+
path.join(destination, "paper.md"),
|
|
905
|
+
);
|
|
906
|
+
await cp(
|
|
907
|
+
path.join(PACKAGE_ROOT, "examples", "toy-evaluation", "repository"),
|
|
908
|
+
path.join(destination, "repository"),
|
|
909
|
+
{ recursive: true },
|
|
910
|
+
);
|
|
911
|
+
console.log(`Example task created: ${destination}`);
|
|
912
|
+
console.log(
|
|
913
|
+
`Next: citeark run --task ${shellQuote(path.join(destination, "task.json"))} --agent opencode --api-base-url https://api.deepseek.com --model '<model-id>' --dry-run`,
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function parseOptions(argv, definitions) {
|
|
918
|
+
const output = {};
|
|
919
|
+
for (const [name, definition] of Object.entries(definitions)) {
|
|
920
|
+
if (definition.default !== undefined) output[name] = definition.default;
|
|
921
|
+
}
|
|
922
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
923
|
+
const name = argv[index];
|
|
924
|
+
const definition = definitions[name];
|
|
925
|
+
if (!definition) throw new CiteArkError(`Unknown option: ${name}`);
|
|
926
|
+
if (definition.type === "boolean") {
|
|
927
|
+
output[name] = true;
|
|
928
|
+
continue;
|
|
929
|
+
}
|
|
930
|
+
const value = argv[index + 1];
|
|
931
|
+
if (value === undefined || value.startsWith("--")) {
|
|
932
|
+
throw new CiteArkError(`Missing value for ${name}`);
|
|
933
|
+
}
|
|
934
|
+
output[name] = value;
|
|
935
|
+
index += 1;
|
|
936
|
+
}
|
|
937
|
+
for (const [name, definition] of Object.entries(definitions)) {
|
|
938
|
+
if (definition.required && output[name] === undefined) {
|
|
939
|
+
throw new CiteArkError(`Missing required option: ${name}`);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
return output;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
function agentEntryOptions() {
|
|
946
|
+
return {
|
|
947
|
+
"--agent": { type: "string", required: true },
|
|
948
|
+
"--api-base-url": { type: "string", required: true },
|
|
949
|
+
"--api-key": { type: "string" },
|
|
950
|
+
"--api-key-env": { type: "string" },
|
|
951
|
+
"--model": { type: "string", required: true },
|
|
952
|
+
"--subagent-model": { type: "string" },
|
|
953
|
+
"--effort": { type: "string" }, "--model-budget": { type: "string" },
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
function agentRuntimeOptions(options, dryRun, { allowGcpSecret = false } = {}) {
|
|
958
|
+
const runtime = options["--agent"];
|
|
959
|
+
if (!new Set(["claude-code", "codex", "opencode"]).has(runtime)) {
|
|
960
|
+
throw new CiteArkError("--agent must be claude-code, codex, or opencode");
|
|
961
|
+
}
|
|
962
|
+
if (options["--api-key"] && options["--api-key-env"]) {
|
|
963
|
+
throw new CiteArkError("Provide either --api-key or --api-key-env");
|
|
964
|
+
}
|
|
965
|
+
const environmentName = options["--api-key-env"];
|
|
966
|
+
const apiKey = options["--api-key"] ?? (environmentName ? process.env[environmentName] : null);
|
|
967
|
+
const hasGcpSecret = Boolean(options["--gcp-provider-secret"] ?? process.env.CITEARK_GCP_PROVIDER_SECRET);
|
|
968
|
+
if (!dryRun && !apiKey && !(allowGcpSecret && hasGcpSecret)) {
|
|
969
|
+
throw new CiteArkError(
|
|
970
|
+
environmentName
|
|
971
|
+
? `Environment variable ${environmentName} is not set`
|
|
972
|
+
: "Provide --api-key, --api-key-env, or --gcp-provider-secret for GCP Batch.",
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
return {
|
|
976
|
+
runtime,
|
|
977
|
+
apiBaseUrl: options["--api-base-url"],
|
|
978
|
+
apiKey,
|
|
979
|
+
apiKeySource: apiKey
|
|
980
|
+
? (environmentName ? `env:${environmentName}` : "parameter")
|
|
981
|
+
: "gcp-secret-manager",
|
|
982
|
+
model: options["--model"],
|
|
983
|
+
subagentModel: options["--subagent-model"],
|
|
984
|
+
effort: options["--effort"], maxBudgetUsd: options["--model-budget"] ? Number(options["--model-budget"]) : undefined,
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function gcpEntryOptions() {
|
|
989
|
+
return {
|
|
990
|
+
"--gcp-project": { type: "string" },
|
|
991
|
+
"--gcp-region": { type: "string" },
|
|
992
|
+
"--gcp-staging-bucket": { type: "string" },
|
|
993
|
+
"--gcp-asset-cache-bucket": { type: "string" },
|
|
994
|
+
"--gcp-asset-restore-checkpoint-prefix": { type: "string" },
|
|
995
|
+
"--gcp-asset-restore-checkpoint-bucket": { type: "string" },
|
|
996
|
+
"--gcp-service-account": { type: "string" },
|
|
997
|
+
"--gcp-provider-secret": { type: "string" },
|
|
998
|
+
"--gcp-machine-type": { type: "string" },
|
|
999
|
+
"--gcp-provisioning-model": { type: "string" },
|
|
1000
|
+
"--gcp-boot-disk-gb": { type: "string" },
|
|
1001
|
+
"--gcp-wait-timeout-minutes": { type: "string" },
|
|
1002
|
+
"--gcp-critical-checkpoint-seconds": { type: "string" },
|
|
1003
|
+
"--gcp-full-checkpoint-seconds": { type: "string" },
|
|
1004
|
+
"--gcp-checkpoint-retention": { type: "string" },
|
|
1005
|
+
"--gcp-result-stability-seconds": { type: "string" },
|
|
1006
|
+
"--gcp-disable-checkpoints": { type: "boolean", default: false },
|
|
1007
|
+
"--gcp-keep-job": { type: "boolean", default: false },
|
|
1008
|
+
"--gcp-keep-staging": { type: "boolean", default: false },
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
function autoDlEntryOptions() {
|
|
1013
|
+
return {
|
|
1014
|
+
"--autodl-token-env": { type: "string", default: "AUTODL_API_TOKEN" },
|
|
1015
|
+
"--allow-remote-model-key": { type: "boolean", default: false },
|
|
1016
|
+
"--autodl-image-uuid": { type: "string" },
|
|
1017
|
+
"--autodl-gpu-spec-uuid": { type: "string" },
|
|
1018
|
+
"--autodl-data-centers": { type: "string" },
|
|
1019
|
+
"--autodl-max-hourly-cny": { type: "string" },
|
|
1020
|
+
"--autodl-expand-system-disk-gb": { type: "string" },
|
|
1021
|
+
"--autodl-keep-instance": { type: "boolean", default: false },
|
|
1022
|
+
"--autodl-keep-failed-instance": { type: "boolean", default: false },
|
|
1023
|
+
"--autodl-release-on-failure": { type: "boolean", default: false },
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function executorOptions(options) {
|
|
1028
|
+
const autoDlTokenEnvironment = options["--autodl-token-env"];
|
|
1029
|
+
return {
|
|
1030
|
+
gcpBatch: {
|
|
1031
|
+
projectId: options["--gcp-project"],
|
|
1032
|
+
region: options["--gcp-region"],
|
|
1033
|
+
stagingBucket: options["--gcp-staging-bucket"],
|
|
1034
|
+
assetCacheBucket: options["--gcp-asset-cache-bucket"],
|
|
1035
|
+
assetPreparationRestoreCheckpointPrefix:
|
|
1036
|
+
options["--gcp-asset-restore-checkpoint-prefix"],
|
|
1037
|
+
assetPreparationRestoreCheckpointBucket:
|
|
1038
|
+
options["--gcp-asset-restore-checkpoint-bucket"],
|
|
1039
|
+
serviceAccount: options["--gcp-service-account"],
|
|
1040
|
+
providerSecret: options["--gcp-provider-secret"],
|
|
1041
|
+
machineType: options["--gcp-machine-type"],
|
|
1042
|
+
provisioningModel: options["--gcp-provisioning-model"],
|
|
1043
|
+
bootDiskGb: options["--gcp-boot-disk-gb"],
|
|
1044
|
+
waitTimeoutMinutes: options["--gcp-wait-timeout-minutes"],
|
|
1045
|
+
checkpointEnabled: options["--gcp-disable-checkpoints"] ? false : undefined,
|
|
1046
|
+
criticalCheckpointIntervalSeconds: options["--gcp-critical-checkpoint-seconds"],
|
|
1047
|
+
fullCheckpointIntervalSeconds: options["--gcp-full-checkpoint-seconds"],
|
|
1048
|
+
checkpointRetention: options["--gcp-checkpoint-retention"],
|
|
1049
|
+
keepJob: options["--gcp-keep-job"],
|
|
1050
|
+
keepStaging: options["--gcp-keep-staging"],
|
|
1051
|
+
},
|
|
1052
|
+
autoDl: {
|
|
1053
|
+
allowRemoteModelKey: options["--allow-remote-model-key"],
|
|
1054
|
+
apiToken: autoDlTokenEnvironment
|
|
1055
|
+
? process.env[autoDlTokenEnvironment]
|
|
1056
|
+
: undefined,
|
|
1057
|
+
imageUuid: options["--autodl-image-uuid"],
|
|
1058
|
+
gpuSpecUuid: options["--autodl-gpu-spec-uuid"],
|
|
1059
|
+
dataCenterList: options["--autodl-data-centers"]
|
|
1060
|
+
?.split(",")
|
|
1061
|
+
.map((item) => item.trim())
|
|
1062
|
+
.filter(Boolean),
|
|
1063
|
+
maxHourlyCny: options["--autodl-max-hourly-cny"],
|
|
1064
|
+
expandSystemDiskGb: options["--autodl-expand-system-disk-gb"],
|
|
1065
|
+
providerSecret: options["--gcp-provider-secret"],
|
|
1066
|
+
keepInstance: options["--autodl-keep-instance"],
|
|
1067
|
+
keepFailedInstance: options["--autodl-keep-failed-instance"]
|
|
1068
|
+
? true
|
|
1069
|
+
: options["--autodl-release-on-failure"]
|
|
1070
|
+
? false
|
|
1071
|
+
: undefined,
|
|
1072
|
+
},
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
function printHelp() {
|
|
1077
|
+
console.log(`CiteArk Agent ${VERSION}
|
|
1078
|
+
|
|
1079
|
+
Independent research, experiment execution, and signed evidence.
|
|
1080
|
+
|
|
1081
|
+
Start and continue
|
|
1082
|
+
citeark Open the interactive research workspace
|
|
1083
|
+
citeark start <paper-id> Start from a CiteArk paper
|
|
1084
|
+
citeark start --paper <path> Start from a paper file or URL
|
|
1085
|
+
citeark start --cap <file> Use a CAP artifact as research input
|
|
1086
|
+
citeark start --resume --work-dir <directory>
|
|
1087
|
+
citeark view <directory> Browse a saved conversation without running it
|
|
1088
|
+
|
|
1089
|
+
Profiles and sessions
|
|
1090
|
+
citeark model add|list|use|remove|check <name>
|
|
1091
|
+
citeark compute add|list|use|remove|check <name>
|
|
1092
|
+
citeark session list
|
|
1093
|
+
citeark session attach|status|pause|resume|cancel <directory>
|
|
1094
|
+
citeark session note <directory> --message <text>
|
|
1095
|
+
citeark session fetch <remote-directory> --compute <name> --output <path>
|
|
1096
|
+
|
|
1097
|
+
Research options
|
|
1098
|
+
--goal <text> Set your research question
|
|
1099
|
+
--repository <path-or-url> Include source code
|
|
1100
|
+
--guide <file> Include research instructions
|
|
1101
|
+
--compute <name> Select a saved local, SSH or catalog profile
|
|
1102
|
+
--background Start a detached research worker
|
|
1103
|
+
--compute-catalog <file> Use your local or remote compute configuration
|
|
1104
|
+
--plan-only Save a plan without running experiments
|
|
1105
|
+
--experiments <id,id> Select experiments
|
|
1106
|
+
--plain Use line-oriented terminal output
|
|
1107
|
+
--non-interactive Run with explicit options, without prompts
|
|
1108
|
+
--dry-run Prepare inputs without models or compute
|
|
1109
|
+
|
|
1110
|
+
Model options
|
|
1111
|
+
--model-profile <name> Select a saved model configuration
|
|
1112
|
+
--assessment-profile <name> Use a separate model for scientific assessment
|
|
1113
|
+
--change-model Record an explicit model change on resume
|
|
1114
|
+
--effort <level> low, medium, high, xhigh or max
|
|
1115
|
+
--model-budget <usd> Runtime model budget (not a total cost cap)
|
|
1116
|
+
--agent <runtime> opencode, codex, or claude-code
|
|
1117
|
+
--api-base-url <url> Model endpoint
|
|
1118
|
+
--model <name> Model name
|
|
1119
|
+
--api-key-env <name> Environment variable containing the API key
|
|
1120
|
+
|
|
1121
|
+
Artifacts and tools
|
|
1122
|
+
citeark publish --cap <file> [--plan <file>]
|
|
1123
|
+
citeark cap verify --file <file>
|
|
1124
|
+
citeark graph --cap <file> --operation subgraph
|
|
1125
|
+
citeark paper setup --python python3.12
|
|
1126
|
+
citeark paper parse --input paper.pdf --output ./paper-reading
|
|
1127
|
+
citeark setup [--gpu]
|
|
1128
|
+
citeark doctor
|
|
1129
|
+
citeark deploy --replay <paper-id>
|
|
1130
|
+
|
|
1131
|
+
Advanced commands
|
|
1132
|
+
compile · run · pipeline · research · contract · compute · assets
|
|
1133
|
+
evidence · handoff · parsers · dashboard · autodl · init
|
|
1134
|
+
|
|
1135
|
+
Terminal controls
|
|
1136
|
+
PgUp/PgDn or mouse wheel Browse the full conversation
|
|
1137
|
+
End Follow new output
|
|
1138
|
+
Ctrl+O Expand or collapse long tool output
|
|
1139
|
+
/pause /resume /cancel Control the attached research worker
|
|
1140
|
+
Enter Queue an instruction for the next invocation
|
|
1141
|
+
Ctrl+C Detach from the research worker
|
|
1142
|
+
|
|
1143
|
+
Documentation: https://citeark.co/docs/local-reproduction`);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
export { parseOptions, agentEntryOptions, gcpEntryOptions, autoDlEntryOptions, agentRuntimeOptions, executorOptions };
|