@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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import {
|
|
4
|
+
mkdir,
|
|
5
|
+
mkdtemp,
|
|
6
|
+
readFile,
|
|
7
|
+
writeFile,
|
|
8
|
+
stat,
|
|
9
|
+
rm,
|
|
10
|
+
} from "node:fs/promises";
|
|
11
|
+
import { randomUUID } from "node:crypto";
|
|
12
|
+
import { readSettings } from "../settings/store.mjs";
|
|
13
|
+
import { shellQuote } from "../util.mjs";
|
|
14
|
+
import { captureProcess } from "../process.mjs";
|
|
15
|
+
import { sshCommand, sshShell } from "./ssh.mjs";
|
|
16
|
+
import { attachJob } from "../workspace/jobs.mjs";
|
|
17
|
+
|
|
18
|
+
export function takeOption(args, flag) {
|
|
19
|
+
const index = args.indexOf(flag);
|
|
20
|
+
if (index < 0) return undefined;
|
|
21
|
+
if (!args[index + 1] || args[index + 1].startsWith("--"))
|
|
22
|
+
throw Error(`${flag} requires a value.`);
|
|
23
|
+
return args.splice(index, 2)[1];
|
|
24
|
+
}
|
|
25
|
+
export async function remoteProfile(name) {
|
|
26
|
+
const settings = await readSettings();
|
|
27
|
+
const profile = settings.compute[name];
|
|
28
|
+
if (!profile || profile.type !== "ssh")
|
|
29
|
+
throw Error(`Unknown SSH compute profile: ${name}`);
|
|
30
|
+
return profile;
|
|
31
|
+
}
|
|
32
|
+
export async function startRemoteResearch(argv, profile, name) {
|
|
33
|
+
if (argv.includes("--api-key"))
|
|
34
|
+
throw Error(
|
|
35
|
+
"Remote research uses credentials configured on the server. Select a remote model profile or API key environment variable.",
|
|
36
|
+
);
|
|
37
|
+
const detach = argv.includes("--background");
|
|
38
|
+
const args = [...argv];
|
|
39
|
+
takeOption(args, "--compute");
|
|
40
|
+
const specified = takeOption(args, "--work-dir");
|
|
41
|
+
const root =
|
|
42
|
+
specified ?? path.posix.join(profile.directory, `research-${randomUUID()}`);
|
|
43
|
+
if (!path.posix.isAbsolute(root))
|
|
44
|
+
throw Error("Use an absolute remote workspace path.");
|
|
45
|
+
if (args.includes("--dry-run")) {
|
|
46
|
+
console.log(
|
|
47
|
+
JSON.stringify(
|
|
48
|
+
{
|
|
49
|
+
host: profile.host,
|
|
50
|
+
directory: root,
|
|
51
|
+
modelCredentials: "configured-on-remote-host",
|
|
52
|
+
action: "prepare-only",
|
|
53
|
+
},
|
|
54
|
+
null,
|
|
55
|
+
2,
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!args.includes("--resume")) {
|
|
61
|
+
await sshShell(
|
|
62
|
+
profile,
|
|
63
|
+
`mkdir -p ${shellQuote(profile.directory)} && mkdir ${shellQuote(root)} && mkdir ${shellQuote(path.posix.join(root, "input-files"))}`,
|
|
64
|
+
);
|
|
65
|
+
for (const flag of ["--paper", "--cap", "--repository", "--guide"]) {
|
|
66
|
+
const i = args.indexOf(flag);
|
|
67
|
+
const local = args[i + 1];
|
|
68
|
+
if (i < 0 || /^https?:\/\//.test(local)) continue;
|
|
69
|
+
const location = path.resolve(local);
|
|
70
|
+
const info = await stat(location);
|
|
71
|
+
const destination = path.posix.join(
|
|
72
|
+
root,
|
|
73
|
+
"input-files",
|
|
74
|
+
`${flag.slice(2)}${info.isDirectory() ? "" : path.extname(location)}`,
|
|
75
|
+
);
|
|
76
|
+
if (info.isDirectory()) {
|
|
77
|
+
const temp = await mkdtemp(path.join(os.tmpdir(), "citeark-transfer-"));
|
|
78
|
+
try {
|
|
79
|
+
const archive = path.join(temp, "code.tgz");
|
|
80
|
+
const result = await captureProcess(
|
|
81
|
+
"tar",
|
|
82
|
+
[
|
|
83
|
+
"--exclude=.git",
|
|
84
|
+
"--exclude=.env*",
|
|
85
|
+
"--exclude=node_modules",
|
|
86
|
+
"--exclude=.citeark",
|
|
87
|
+
"-czf",
|
|
88
|
+
archive,
|
|
89
|
+
"-C",
|
|
90
|
+
location,
|
|
91
|
+
".",
|
|
92
|
+
],
|
|
93
|
+
{ env: { ...process.env, COPYFILE_DISABLE: "1" } },
|
|
94
|
+
);
|
|
95
|
+
if (result.code) throw Error(result.stderr);
|
|
96
|
+
await sshShell(
|
|
97
|
+
profile,
|
|
98
|
+
`mkdir ${shellQuote(destination)} && tar -xzf - -C ${shellQuote(destination)}`,
|
|
99
|
+
{ input: await readFile(archive) },
|
|
100
|
+
);
|
|
101
|
+
} finally {
|
|
102
|
+
await rm(temp, { recursive: true, force: true });
|
|
103
|
+
}
|
|
104
|
+
} else
|
|
105
|
+
await sshShell(profile, `cat > ${shellQuote(destination)}`, {
|
|
106
|
+
input: await readFile(location),
|
|
107
|
+
});
|
|
108
|
+
args[i + 1] = destination;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Catalog paths and model profile names refer to the server's configuration.
|
|
112
|
+
args.push("--work-dir", root);
|
|
113
|
+
if (!args.includes("--background")) args.push("--background");
|
|
114
|
+
const started = JSON.parse(await sshCommand(profile, ["start", ...args]));
|
|
115
|
+
console.log(`Research started on ${profile.host}: ${started.directory}`);
|
|
116
|
+
console.log(
|
|
117
|
+
`Reconnect: citeark session attach ${JSON.stringify(root)} --compute ${name}`,
|
|
118
|
+
);
|
|
119
|
+
if (detach) return started;
|
|
120
|
+
const state = await attachJob(root, {
|
|
121
|
+
inspect: (directory, cursor) => inspectRemote(profile, directory, cursor),
|
|
122
|
+
control: (directory, text) =>
|
|
123
|
+
sshCommand(profile, ["session", "note", directory, "--message", text]),
|
|
124
|
+
});
|
|
125
|
+
if (state?.status === "awaiting_selection")
|
|
126
|
+
console.log(
|
|
127
|
+
`Run selected experiments: citeark start --resume --work-dir ${JSON.stringify(root)} --compute ${name} --experiments <ids>`,
|
|
128
|
+
);
|
|
129
|
+
return state;
|
|
130
|
+
}
|
|
131
|
+
export const inspectRemote = async (profile, root, cursor = 0) =>
|
|
132
|
+
JSON.parse(
|
|
133
|
+
await sshCommand(profile, [
|
|
134
|
+
"session",
|
|
135
|
+
"inspect",
|
|
136
|
+
root,
|
|
137
|
+
"--cursor",
|
|
138
|
+
String(cursor),
|
|
139
|
+
]),
|
|
140
|
+
);
|
|
141
|
+
export async function remoteSession(argv, name) {
|
|
142
|
+
const profile = await remoteProfile(name);
|
|
143
|
+
const [action, root, ...args] = argv;
|
|
144
|
+
if (action === "attach")
|
|
145
|
+
return attachJob(root, {
|
|
146
|
+
inspect: (directory, cursor) => inspectRemote(profile, directory, cursor),
|
|
147
|
+
control: (directory, text) =>
|
|
148
|
+
sshCommand(profile, ["session", "note", directory, "--message", text]),
|
|
149
|
+
});
|
|
150
|
+
if (action === "fetch") {
|
|
151
|
+
const output = path.resolve(
|
|
152
|
+
takeOption(args, "--output") ?? path.basename(root),
|
|
153
|
+
);
|
|
154
|
+
const state = await inspectRemote(profile, root);
|
|
155
|
+
if (!state.artifacts.length)
|
|
156
|
+
throw Error("This session has no CAP artifacts yet.");
|
|
157
|
+
await mkdir(output, { recursive: true });
|
|
158
|
+
const { readCapArchive } = await import("../cap/v2/read.mjs");
|
|
159
|
+
const temp = await mkdtemp(path.join(os.tmpdir(), "citeark-cap-check-"));
|
|
160
|
+
try {
|
|
161
|
+
for (const [index, file] of [...new Set(state.artifacts)].entries()) {
|
|
162
|
+
const bytes = await sshShell(profile, `cat -- ${shellQuote(file)}`, {
|
|
163
|
+
binary: true,
|
|
164
|
+
});
|
|
165
|
+
const local = path.join(temp, `${index}.cap`);
|
|
166
|
+
await writeFile(local, bytes);
|
|
167
|
+
await readCapArchive(local, path.join(temp, `verify-${index}`));
|
|
168
|
+
const target = path.join(output, `${index + 1}-${path.basename(file)}`);
|
|
169
|
+
await writeFile(target, bytes, { flag: "wx" });
|
|
170
|
+
console.log(target);
|
|
171
|
+
}
|
|
172
|
+
} finally {
|
|
173
|
+
await rm(temp, { recursive: true, force: true });
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
console.log((await sshCommand(profile, ["session", ...argv])).trim());
|
|
178
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { shellQuote } from "../util.mjs";
|
|
3
|
+
|
|
4
|
+
export function sshArguments(profile, command) {
|
|
5
|
+
return [
|
|
6
|
+
...(profile.configFile ? ["-F", profile.configFile] : []),
|
|
7
|
+
"-o",
|
|
8
|
+
"BatchMode=yes",
|
|
9
|
+
"-o",
|
|
10
|
+
"StrictHostKeyChecking=yes",
|
|
11
|
+
"-o",
|
|
12
|
+
"ConnectTimeout=15",
|
|
13
|
+
...(profile.port ? ["-p", String(profile.port)] : []),
|
|
14
|
+
...(profile.identityFile ? ["-i", profile.identityFile] : []),
|
|
15
|
+
profile.host,
|
|
16
|
+
command,
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
export async function sshShell(
|
|
20
|
+
profile,
|
|
21
|
+
command,
|
|
22
|
+
{ input, binary = false } = {},
|
|
23
|
+
) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const child = spawn("ssh", sshArguments(profile, command), {
|
|
26
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
27
|
+
});
|
|
28
|
+
const output = [];
|
|
29
|
+
let error = "";
|
|
30
|
+
child.stdout.on("data", (chunk) => output.push(chunk));
|
|
31
|
+
child.stderr.on("data", (chunk) => {
|
|
32
|
+
error += chunk;
|
|
33
|
+
});
|
|
34
|
+
child.on("error", reject);
|
|
35
|
+
child.stdin.on("error", (err) => {
|
|
36
|
+
if (err.code !== "EPIPE") reject(err);
|
|
37
|
+
});
|
|
38
|
+
child.on("close", (code) =>
|
|
39
|
+
code === 0
|
|
40
|
+
? resolve(
|
|
41
|
+
binary
|
|
42
|
+
? Buffer.concat(output)
|
|
43
|
+
: Buffer.concat(output).toString("utf8"),
|
|
44
|
+
)
|
|
45
|
+
: reject(
|
|
46
|
+
Error(
|
|
47
|
+
`SSH command failed (${code}): ${error.trim() || "Check the remote command and SSH connection."}`,
|
|
48
|
+
),
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
child.stdin.end(input);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export const sshCommand = (profile, args, options) =>
|
|
55
|
+
sshShell(
|
|
56
|
+
profile,
|
|
57
|
+
`cd ${shellQuote(profile.directory)} && exec ${shellQuote(profile.command ?? "citeark")} ${args.map(shellQuote).join(" ")}`,
|
|
58
|
+
options,
|
|
59
|
+
);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { devNull } from "node:os";
|
|
3
|
+
|
|
4
|
+
import { captureProcess } from "./process.mjs";
|
|
5
|
+
import { CiteArkError } from "./util.mjs";
|
|
6
|
+
|
|
7
|
+
export const IMPLEMENTATION_ORIGINS = new Set([
|
|
8
|
+
"official",
|
|
9
|
+
"citeark_reconstruction",
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
export const RECONSTRUCTION_SCAFFOLD_COMMIT = "8af5c5a966cf8d5e55560659ef5a33e6ceadaa33";
|
|
13
|
+
|
|
14
|
+
export const RECONSTRUCTION_REPOSITORY = Object.freeze({
|
|
15
|
+
implementationOrigin: "citeark_reconstruction",
|
|
16
|
+
url: "citeark://reconstruction/v1",
|
|
17
|
+
commit: RECONSTRUCTION_SCAFFOLD_COMMIT,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export function isCiteArkReconstructionRepository(repository) {
|
|
21
|
+
return repository?.implementationOrigin === "citeark_reconstruction"
|
|
22
|
+
|| repository?.url === RECONSTRUCTION_REPOSITORY.url;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Create the deterministic empty base used by paper-driven reconstructions. */
|
|
26
|
+
export async function prepareReconstructionRepository(destination) {
|
|
27
|
+
const fixedEnvironment = {
|
|
28
|
+
...process.env,
|
|
29
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
30
|
+
GIT_CONFIG_GLOBAL: devNull,
|
|
31
|
+
GIT_AUTHOR_NAME: "CiteArk",
|
|
32
|
+
GIT_AUTHOR_EMAIL: "research@citeark.com",
|
|
33
|
+
GIT_AUTHOR_DATE: "2000-01-01T00:00:00Z",
|
|
34
|
+
GIT_COMMITTER_NAME: "CiteArk",
|
|
35
|
+
GIT_COMMITTER_EMAIL: "research@citeark.com",
|
|
36
|
+
GIT_COMMITTER_DATE: "2000-01-01T00:00:00Z",
|
|
37
|
+
};
|
|
38
|
+
await mkdir(destination, { recursive: true });
|
|
39
|
+
await writeFile(
|
|
40
|
+
`${destination}/CITEARK_RECONSTRUCTION.md`,
|
|
41
|
+
`# CiteArk independent reconstruction\n\nThis workspace intentionally starts without author-provided source code. The execution Agent must implement only the fixed, paper-grounded protocol in the blind execution contract.\n`,
|
|
42
|
+
"utf8",
|
|
43
|
+
);
|
|
44
|
+
const init = await captureProcess(
|
|
45
|
+
"git",
|
|
46
|
+
["init", "--object-format=sha1", "--initial-branch=main"],
|
|
47
|
+
{ cwd: destination, env: fixedEnvironment },
|
|
48
|
+
);
|
|
49
|
+
if (init.code !== 0) throw new CiteArkError(`无法初始化独立重建工作区:${init.stderr.trim()}`);
|
|
50
|
+
const add = await captureProcess(
|
|
51
|
+
"git",
|
|
52
|
+
["-c", "core.autocrlf=false", "add", "CITEARK_RECONSTRUCTION.md"],
|
|
53
|
+
{ cwd: destination, env: fixedEnvironment },
|
|
54
|
+
);
|
|
55
|
+
if (add.code !== 0) throw new CiteArkError(`无法固定独立重建工作区:${add.stderr.trim()}`);
|
|
56
|
+
const commit = await captureProcess(
|
|
57
|
+
"git",
|
|
58
|
+
[
|
|
59
|
+
"commit",
|
|
60
|
+
"--no-gpg-sign",
|
|
61
|
+
"--cleanup=verbatim",
|
|
62
|
+
"-m",
|
|
63
|
+
"Initialize CiteArk independent reconstruction workspace",
|
|
64
|
+
],
|
|
65
|
+
{ cwd: destination, env: fixedEnvironment },
|
|
66
|
+
);
|
|
67
|
+
if (commit.code !== 0) throw new CiteArkError(`无法提交独立重建工作区:${commit.stderr.trim()}`);
|
|
68
|
+
const revision = await captureProcess(
|
|
69
|
+
"git",
|
|
70
|
+
["rev-parse", "HEAD"],
|
|
71
|
+
{ cwd: destination, env: fixedEnvironment },
|
|
72
|
+
);
|
|
73
|
+
if (revision.code !== 0) throw new CiteArkError("无法读取独立重建工作区版本");
|
|
74
|
+
const observedCommit = revision.stdout.trim();
|
|
75
|
+
if (observedCommit !== RECONSTRUCTION_SCAFFOLD_COMMIT) {
|
|
76
|
+
throw new CiteArkError(
|
|
77
|
+
`独立重建基座 commit 不稳定:expected=${RECONSTRUCTION_SCAFFOLD_COMMIT}, observed=${observedCommit}`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return observedCommit;
|
|
81
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
3
|
+
import { getEvidenceParser } from "../evidence/parser-registry.mjs";
|
|
4
|
+
import { safeRelativePath } from "../util.mjs";
|
|
5
|
+
|
|
6
|
+
/** Extraction feedback for the live Agent. No target values, scientific verdicts
|
|
7
|
+
* or automatic metric selection: a valid scalar can still answer the wrong question.
|
|
8
|
+
*/
|
|
9
|
+
export async function inspectResearchPlanEvidence(contract, outputDirectory) {
|
|
10
|
+
const measurements = [];
|
|
11
|
+
const files = new Map();
|
|
12
|
+
const root = await realpath(outputDirectory);
|
|
13
|
+
for (const measurement of contract.measurements ?? []) {
|
|
14
|
+
const descriptor = measurement.parser;
|
|
15
|
+
const item = {
|
|
16
|
+
measurementId: measurement.measurementId,
|
|
17
|
+
metric: measurement.metric,
|
|
18
|
+
unit: measurement.unit,
|
|
19
|
+
evidencePath: descriptor?.evidencePath ?? null,
|
|
20
|
+
parser: descriptor?.id ?? null,
|
|
21
|
+
interpretation: measurementInterpretation(measurement),
|
|
22
|
+
...(descriptor?.id === "json.scalar" ? { field: descriptor.config?.pointer ?? "",
|
|
23
|
+
scale: descriptor.config?.scale ?? 1, offset: descriptor.config?.offset ?? 0 } : {}),
|
|
24
|
+
};
|
|
25
|
+
try {
|
|
26
|
+
if (!safeRelativePath(descriptor?.evidencePath)) throw new Error("Evidence path must stay inside output");
|
|
27
|
+
if (!files.has(descriptor.evidencePath)) {
|
|
28
|
+
const filename = path.join(root, descriptor.evidencePath);
|
|
29
|
+
const stat = await lstat(filename);
|
|
30
|
+
if (!stat.isFile() || !(await realpath(filename)).startsWith(`${root}${path.sep}`)) {
|
|
31
|
+
throw new Error("Evidence must be a regular file inside output");
|
|
32
|
+
}
|
|
33
|
+
// The preview is advisory and bounded; large evidence remains available
|
|
34
|
+
// to the final parser, not a reason to rerun or mark the experiment failed.
|
|
35
|
+
if (stat.size > 32 * 1024 * 1024) throw new Error("Evidence exceeds the 32 MiB interactive preview limit; inspect it directly before final parsing");
|
|
36
|
+
files.set(descriptor.evidencePath, await readFile(filename, "utf8"));
|
|
37
|
+
}
|
|
38
|
+
const parser = getEvidenceParser(descriptor);
|
|
39
|
+
if (!parser) throw new Error(`Unknown parser ${descriptor?.id}@${descriptor?.version}`);
|
|
40
|
+
const text = files.get(descriptor.evidencePath);
|
|
41
|
+
const parsed = parser.parse(text, descriptor.config ?? {});
|
|
42
|
+
item.status = "available";
|
|
43
|
+
item.value = parsed.primary.value;
|
|
44
|
+
if (descriptor.id === "json.scalar") {
|
|
45
|
+
// Expose neighboring field NAMES only. Their presence is not an error
|
|
46
|
+
// and never selects a field based on its numeric proximity to a target.
|
|
47
|
+
item.neighboringFields = neighboringFields(text, descriptor.config?.pointer ?? "");
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
item.status = "unresolved";
|
|
51
|
+
item.reason = error.code === "ENOENT" ? "Evidence has not been written at this path" : error.message;
|
|
52
|
+
}
|
|
53
|
+
measurements.push(item);
|
|
54
|
+
}
|
|
55
|
+
const assigned = contract.executionPlan?.originalMeasurements ?? contract.measurements ?? [];
|
|
56
|
+
const assignedIds = assigned.map((item) => item.measurementId);
|
|
57
|
+
const currentIds = new Set(measurements.map((item) => item.measurementId));
|
|
58
|
+
const interpretationReview = measurements
|
|
59
|
+
.filter((item) => item.status === "available" && item.interpretation.status !== "resolved")
|
|
60
|
+
.map((item) => ({
|
|
61
|
+
measurementId: item.measurementId,
|
|
62
|
+
field: item.field ?? null,
|
|
63
|
+
neighboringFields: item.neighboringFields ?? [],
|
|
64
|
+
action: "Resolve the quantity and aggregation from the source/evaluator using the retained output before considering another experiment.",
|
|
65
|
+
}));
|
|
66
|
+
return {
|
|
67
|
+
role: "extraction_preview_not_scientific_verification",
|
|
68
|
+
interpretationReview,
|
|
69
|
+
assignedMeasurementIds: assignedIds,
|
|
70
|
+
additionalPlannedMeasurementIds: measurements.filter((item) => !assignedIds.includes(item.measurementId)).map((item) => item.measurementId),
|
|
71
|
+
remainingClaimMeasurementIds: (contract.workspacePlan?.measurements ?? []).filter((item) => !currentIds.has(item.measurementId)).map((item) => item.measurementId),
|
|
72
|
+
measurements,
|
|
73
|
+
nextAction: "Check field meaning and aggregation against the sources. Correct source-resolvable defects using existing raw output; never select a value because it looks closer to the paper. Missing or genuinely unavailable evidence may remain partial within the same budget.",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function neighboringFields(text, pointer) {
|
|
78
|
+
try {
|
|
79
|
+
if (!pointer.startsWith("/")) return [];
|
|
80
|
+
const keys = pointer.slice(1).split("/").map((key) => key.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
81
|
+
let parent = JSON.parse(text);
|
|
82
|
+
for (const key of keys.slice(0, -1)) parent = parent[key];
|
|
83
|
+
return parent && typeof parent === "object" && !Array.isArray(parent) ? Object.keys(parent).slice(0, 30) : [];
|
|
84
|
+
} catch { return []; }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A source-grounded declaration to be audited, never a scientific verdict. */
|
|
88
|
+
export function measurementInterpretation(measurement) {
|
|
89
|
+
const review = measurement?.interpretation;
|
|
90
|
+
const sources = Array.isArray(review?.sources)
|
|
91
|
+
? review.sources.filter((item) => typeof item === "string" && item.trim()) : [];
|
|
92
|
+
const reason = typeof review?.reason === "string" ? review.reason.trim() : "";
|
|
93
|
+
const resolved = review?.status === "resolved" && sources.length > 0 && reason.length > 0;
|
|
94
|
+
return { status: resolved ? "resolved" : "unresolved", sources, reason: reason
|
|
95
|
+
|| "The selected quantity, evaluator field and aggregation have no recorded source-grounded interpretation." };
|
|
96
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { readdir, rename } from 'node:fs/promises';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { pathExists, readJson } from '../util.mjs';
|
|
5
|
+
|
|
6
|
+
export async function preserveIncompleteInitialization({runsDirectory, runId, task}) {
|
|
7
|
+
const root=path.resolve(runsDirectory,runId);
|
|
8
|
+
if (!await pathExists(root)) return null;
|
|
9
|
+
// Never replace a prepared run, remote execution, or recoverable session.
|
|
10
|
+
if (await pathExists(path.join(root,'run.json')) || await pathExists(path.join(root,'recovery-bundle.json'))) return null;
|
|
11
|
+
const submitted=await readJson(path.join(root,'input','submitted-task.json')).catch(()=>null);
|
|
12
|
+
if (!task.contractDigest || submitted?.contractDigest!==task.contractDigest) return null;
|
|
13
|
+
for (const folder of ['execution','output','workspace','runtime-home']) {
|
|
14
|
+
async function hasFiles(directory) {
|
|
15
|
+
for(const entry of await readdir(directory,{withFileTypes:true}).catch(()=>[])) {
|
|
16
|
+
if (!entry.isDirectory() || await hasFiles(path.join(directory,entry.name))) return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if(await hasFiles(path.join(root,folder))) return null;
|
|
21
|
+
}
|
|
22
|
+
const preserved=`${root}.incomplete-${randomUUID()}`;
|
|
23
|
+
await rename(root,preserved);
|
|
24
|
+
return preserved;
|
|
25
|
+
}
|