@aiwg/cli 2026.10.3 → 2026.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/agentic/code/providers/model-capabilities.v1.json +96 -4
- package/bin/aiwg.mjs +50 -27
- package/dist/src/agents/grounding/knowledge-base.js +54 -6
- package/dist/src/artifacts/browser-export.js +6 -0
- package/dist/src/artifacts/checksum-manifest.js +1 -0
- package/dist/src/artifacts/citation-parser.js +173 -92
- package/dist/src/artifacts/citation-table-schema.js +59 -0
- package/dist/src/artifacts/cli.js +69 -18
- package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
- package/dist/src/artifacts/corpus-tools/vision-extract.js +2 -0
- package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
- package/dist/src/artifacts/corpus-views/renderers.js +3 -3
- package/dist/src/artifacts/discovery-eval.js +6 -4
- package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
- package/dist/src/artifacts/fortemi-core-sync.js +166 -40
- package/dist/src/artifacts/framework-capabilities.js +171 -0
- package/dist/src/artifacts/framework-index-paths.js +73 -0
- package/dist/src/artifacts/framework-source-digest.js +75 -0
- package/dist/src/artifacts/index-builder.js +286 -131
- package/dist/src/artifacts/index-files.js +132 -18
- package/dist/src/artifacts/index-preparation.js +130 -0
- package/dist/src/artifacts/index-refresh.js +591 -0
- package/dist/src/artifacts/index-worker.mjs +11 -0
- package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
- package/dist/src/artifacts/prebuilt-deployment.js +46 -0
- package/dist/src/artifacts/prebuilt-relations.js +80 -0
- package/dist/src/artifacts/query-engine.js +410 -88
- package/dist/src/artifacts/relations-builder.js +168 -0
- package/dist/src/artifacts/relations.js +148 -0
- package/dist/src/artifacts/stats.js +5 -2
- package/dist/src/artifacts/types.js +30 -10
- package/dist/src/artifacts/watcher.js +1 -1
- package/dist/src/auth/credential-store.js +2 -1
- package/dist/src/catalog/cli.d.mts +5 -0
- package/dist/src/channel/manager.d.mts +20 -0
- package/dist/src/channel/manager.mjs +19 -2
- package/dist/src/cli/command-log.js +2 -3
- package/dist/src/cli/handlers/artifacts.js +3 -0
- package/dist/src/cli/handlers/auth.js +3 -0
- package/dist/src/cli/handlers/decision.js +19 -12
- package/dist/src/cli/handlers/diagnose.js +4 -3
- package/dist/src/cli/handlers/effect.js +4 -2
- package/dist/src/cli/handlers/evidence.js +3 -0
- package/dist/src/cli/handlers/help.js +1 -0
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/init.js +4 -1
- package/dist/src/cli/handlers/lint.js +5 -0
- package/dist/src/cli/handlers/models.js +104 -8
- package/dist/src/cli/handlers/ralph-launcher.js +2 -0
- package/dist/src/cli/handlers/refresh.js +12 -0
- package/dist/src/cli/handlers/resource-versions.js +3 -0
- package/dist/src/cli/handlers/rules.js +195 -0
- package/dist/src/cli/handlers/run.js +4 -0
- package/dist/src/cli/handlers/runtime-info.js +1 -2
- package/dist/src/cli/handlers/script-runner.js +3 -2
- package/dist/src/cli/handlers/session.js +19 -9
- package/dist/src/cli/handlers/sessions.js +137 -43
- package/dist/src/cli/handlers/setup-manifest.js +39 -44
- package/dist/src/cli/handlers/setup.js +41 -0
- package/dist/src/cli/handlers/steward.js +11 -0
- package/dist/src/cli/handlers/subcommands.js +57 -2
- package/dist/src/cli/handlers/uhp.js +3 -0
- package/dist/src/cli/handlers/use.js +294 -55
- package/dist/src/cli/handlers/utilities.js +26 -10
- package/dist/src/cli/handlers/version.js +8 -0
- package/dist/src/cli/router.js +15 -1
- package/dist/src/cli/services/deployment-verification.js +19 -9
- package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
- package/dist/src/cli/skill-usage.js +2 -3
- package/dist/src/config/aiwg-config.js +87 -37
- package/dist/src/config/cli.js +111 -5
- package/dist/src/config/decision-config.js +106 -0
- package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
- package/dist/src/config/gitignore.js +50 -0
- package/dist/src/config/index-graph-overrides.js +36 -0
- package/dist/src/config/project-artifacts-health.d.mts +37 -0
- package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
- package/dist/src/config/user-config-dir.d.mts +9 -0
- package/dist/src/config/user-config.js +2 -1
- package/dist/src/config/user-registry.js +23 -15
- package/dist/src/config/user-state.js +7 -0
- package/dist/src/decision/ask.js +203 -43
- package/dist/src/decision/context-live-qualification.js +2 -2
- package/dist/src/decision/driver.js +13 -8
- package/dist/src/decision/ensemble/aggregate.js +23 -10
- package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
- package/dist/src/decision/entry.js +2 -15
- package/dist/src/decision/graph-live-qualification.js +1 -1
- package/dist/src/decision/graph-run.js +9 -0
- package/dist/src/decision/heldout/collector.js +5 -13
- package/dist/src/decision/heldout/contract.js +30 -7
- package/dist/src/decision/jev-credentials.js +15 -1
- package/dist/src/decision/ledger.js +131 -28
- package/dist/src/decision/offload-activation.js +137 -0
- package/dist/src/decision/offload.js +550 -0
- package/dist/src/decision/qualification/load.js +4 -6
- package/dist/src/decision/savings.js +28 -0
- package/dist/src/effects/types.js +5 -1
- package/dist/src/effects/verifiers/git.js +2 -1
- package/dist/src/effects/verifiers/tracker.js +26 -14
- package/dist/src/extensions/commands/definitions.js +19 -0
- package/dist/src/extensions/project-local-remove.js +36 -1
- package/dist/src/gates/providers/loader.js +61 -17
- package/dist/src/installation/manager-command.d.mts +18 -0
- package/dist/src/installation/manager-command.mjs +14 -2
- package/dist/src/installation/manager.d.mts +49 -0
- package/dist/src/installation/manager.mjs +78 -3
- package/dist/src/issues/cli.js +4 -4
- package/dist/src/issues/local.js +24 -5
- package/dist/src/jobs/runner.js +1 -1
- package/dist/src/lint/cli.js +27 -1
- package/dist/src/lint/loader.js +2 -1
- package/dist/src/lint/reporters.js +25 -1
- package/dist/src/lint/rule-activation.js +43 -0
- package/dist/src/lint/runner.js +137 -62
- package/dist/src/mcp/adapters/codex-runtime.js +7 -1
- package/dist/src/mcp/claude-install.d.mts +4 -0
- package/dist/src/mcp/claude-install.mjs +41 -0
- package/dist/src/mcp/cli.d.mts +1 -0
- package/dist/src/mcp/cli.mjs +36 -11
- package/dist/src/mcp/config-file.d.mts +28 -0
- package/dist/src/mcp/config-layers.d.mts +36 -0
- package/dist/src/mcp/credentials.d.mts +51 -0
- package/dist/src/mcp/grok-build-config.d.mts +6 -0
- package/dist/src/mcp/grok-build-config.mjs +1 -1
- package/dist/src/mcp/helpers.mjs +3 -2
- package/dist/src/mcp/muse-native-config.d.mts +13 -0
- package/dist/src/mcp/muse-native-config.mjs +1 -0
- package/dist/src/mcp/omp-config.d.mts +4 -0
- package/dist/src/mcp/registry.js +3 -93
- package/dist/src/mcp/registry.mjs +3 -87
- package/dist/src/mcp/server-config.d.mts +3 -0
- package/dist/src/mcp/server-config.mjs +89 -0
- package/dist/src/mcp/server.mjs +37 -375
- package/dist/src/mcp/test-simple.mjs +2 -1
- package/dist/src/mcp/toml-editor.d.mts +4 -0
- package/dist/src/mcp/toml-string.d.mts +1 -0
- package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
- package/dist/src/mcp/tool-filters.d.mts +46 -0
- package/dist/src/mcp/tools/decision.mjs +12 -11
- package/dist/src/mcp/tools/discovery.mjs +62 -55
- package/dist/src/mcp/tools/orchestration.mjs +12 -2
- package/dist/src/mcp/tools/worker-invoke.mjs +1340 -23
- package/dist/src/mcp/tools/worker-shell-control.mjs +52 -21
- package/dist/src/mcp/tools/worker-stdin-runtime.mjs +3 -3
- package/dist/src/mission-protocol/codecs.js +8 -0
- package/dist/src/models/config-loader.js +7 -2
- package/dist/src/models/model-capabilities.v1.json +96 -4
- package/dist/src/models/model-discovery.js +76 -11
- package/dist/src/models/provider-policy.js +101 -7
- package/dist/src/models/qualification-digest.d.mts +2 -0
- package/dist/src/models/resolver.js +12 -10
- package/dist/src/models/worker-direct-readiness.js +65 -44
- package/dist/src/models/worker-dispatch-offer.js +3 -3
- package/dist/src/models/worker-health-readiness.js +16 -3
- package/dist/src/models/worker-installation.d.mts +39 -0
- package/dist/src/models/worker-installation.mjs +135 -28
- package/dist/src/process/bounded-child-process.d.mts +84 -0
- package/dist/src/process/bounded-child-process.mjs +43 -0
- package/dist/src/process/cli-command.d.mts +16 -0
- package/dist/src/process/signal-child.d.mts +6 -0
- package/dist/src/process/signal-child.mjs +7 -0
- package/dist/src/providers/deployed-skill-roots.js +20 -0
- package/dist/src/providers/grok-build-acp.js +3 -2
- package/dist/src/providers/grok-build-headless.js +12 -4
- package/dist/src/providers/grok-build-inspect.js +1 -0
- package/dist/src/providers/omp-agent.d.mts +8 -0
- package/dist/src/providers/omp-diagnostics.d.mts +1 -0
- package/dist/src/providers/omp-paths.d.mts +13 -0
- package/dist/src/providers/skill-ownership.d.mts +9 -0
- package/dist/src/providers/skill-ownership.mjs +88 -0
- package/dist/src/rules/activation.d.mts +21 -0
- package/dist/src/rules/activation.mjs +62 -0
- package/dist/src/rules/inline-budget.d.mts +26 -0
- package/dist/src/rules/inline-budget.mjs +66 -0
- package/dist/src/rules/inventory.js +129 -0
- package/dist/src/rules/pin-state.js +73 -0
- package/dist/src/rules/pins.d.mts +14 -0
- package/dist/src/rules/pins.mjs +112 -0
- package/dist/src/rules/rule-frontmatter.schema.json +197 -0
- package/dist/src/serve/mission-conductor.js +38 -12
- package/dist/src/serve/worker-invocation.js +30 -10
- package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
- package/dist/src/sessions/adapter-registry.js +23 -19
- package/dist/src/sessions/adapters/claude.js +39 -54
- package/dist/src/sessions/adapters/codex.js +95 -67
- package/dist/src/sessions/adapters/copilot.js +4 -4
- package/dist/src/sessions/adapters/cursor.js +40 -57
- package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
- package/dist/src/sessions/adapters/factory.js +31 -27
- package/dist/src/sessions/adapters/generic.js +10 -10
- package/dist/src/sessions/adapters/grok-build.js +11 -11
- package/dist/src/sessions/adapters/grokbot.js +24 -13
- package/dist/src/sessions/adapters/hermes.js +27 -29
- package/dist/src/sessions/adapters/muse-workspace-scan.js +31 -11
- package/dist/src/sessions/adapters/muse.js +150 -93
- package/dist/src/sessions/adapters/omp.js +28 -14
- package/dist/src/sessions/adapters/openclaw.js +89 -79
- package/dist/src/sessions/adapters/opencode.js +27 -24
- package/dist/src/sessions/adapters/openhuman.js +18 -60
- package/dist/src/sessions/adapters/pi.js +29 -14
- package/dist/src/sessions/adapters/warp.js +3 -3
- package/dist/src/sessions/adapters/windsurf.js +19 -48
- package/dist/src/sessions/batch-contracts.js +16 -8
- package/dist/src/sessions/batch-import.js +252 -12
- package/dist/src/sessions/contracts.js +50 -3
- package/dist/src/sessions/coverage-preflight.js +27 -2
- package/dist/src/sessions/export-plan.js +4 -3
- package/dist/src/sessions/import-exclusions.js +72 -0
- package/dist/src/sessions/import-lease.js +34 -18
- package/dist/src/sessions/import-limits.js +37 -0
- package/dist/src/sessions/importer.js +60 -38
- package/dist/src/sessions/lifecycle.js +45 -0
- package/dist/src/sessions/policy.js +145 -26
- package/dist/src/sessions/readers.js +106 -53
- package/dist/src/sessions/refresh.js +105 -0
- package/dist/src/sessions/repository.js +151 -54
- package/dist/src/sessions/workspace-discovery.js +292 -60
- package/dist/src/sessions/workspace-matching.js +107 -0
- package/dist/src/skills/importer.js +1 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
- package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
- package/dist/src/smiths/context-pipeline/finalization.js +6 -5
- package/dist/src/smiths/context-pipeline/generator.js +21 -4
- package/dist/src/smiths/context-pipeline/parallelism-section.js +7 -15
- package/dist/src/smiths/mcpsmith/generator.js +1 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +76 -18
- package/dist/src/storage/backends/fs.js +18 -76
- package/dist/src/storage/backends/obsidian.js +1 -0
- package/dist/src/tracker/forge-http.js +2 -1
- package/dist/src/update/checker.d.mts +2 -0
- package/dist/src/update/service.d.mts +22 -0
- package/dist/src/utils/contained-filesystem.d.mts +37 -0
- package/dist/src/utils/contained-filesystem.mjs +683 -0
- package/dist/src/utils/temporary-directory.js +36 -0
- package/dist/src/writing/example-generator.js +1 -1
- package/package.json +15 -2
- package/schemas/models/model-catalog.v1.schema.json +1 -1
- package/schemas/models/provider-model-capabilities.v1.schema.json +6 -0
- package/tools/_resolve-impl.mjs +13 -15
- package/tools/agents/deploy-agents.mjs +49 -21
- package/tools/agents/providers/base.mjs +104 -134
- package/tools/agents/providers/claude.mjs +8 -24
- package/tools/agents/providers/codex.mjs +18 -11
- package/tools/agents/providers/cursor.mjs +19 -18
- package/tools/agents/providers/grok-build.mjs +3 -1
- package/tools/agents/providers/hermes.mjs +57 -47
- package/tools/agents/providers/openclaw.mjs +9 -4
- package/tools/agents/providers/pi.mjs +5 -0
- package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
- package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
- package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
- package/tools/agents/providers/rule-delivery.mjs +1270 -0
- package/tools/agents/providers/warp.mjs +20 -26
- package/tools/cli/decision-offload-report.mjs +40 -0
- package/tools/cli/workspace-status.mjs +862 -0
- package/tools/plugin/package-plugins.mjs +186 -8
- package/tools/plugin/plugin-links.mjs +114 -0
- package/tools/providers/antigravity-transport.mjs +3 -1
- package/tools/providers/deepseek-harness-transport.mjs +6 -4
- package/tools/providers/omp-transport.mjs +4 -2
- package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
- package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
- package/tools/ralph-external/lib/omp-adapter.mjs +1 -1
- package/tools/ralph-external/lib/pi-adapter.mjs +0 -4
- package/tools/ralph-external/lib/provider-adapter.mjs +59 -1
- package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
- package/tools/ralph-external/lib/session-environment.mjs +28 -0
- package/tools/ralph-external/lib/systemd-client.mjs +49 -0
- package/tools/ralph-external/lib/worker-health.mjs +1 -1
- package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
- package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
- package/tools/ralph-external/process-monitor.mjs +1017 -0
- package/tools/ralph-external/session-launcher.mjs +5057 -0
- package/tools/scripts/resource-preflight.mjs +541 -0
- package/tools/skills/deploy-skills-codex.mjs +2 -1
- package/vscode-extension/schemas/aiwg.config.v1.json +1194 -231
|
@@ -202,8 +202,7 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
|
|
|
202
202
|
const { RuntimeDiscovery } = await import('../../smiths/toolsmith/runtime-discovery.mjs');
|
|
203
203
|
const discovery = new RuntimeDiscovery();
|
|
204
204
|
if (hasDiscover) {
|
|
205
|
-
|
|
206
|
-
const catalog = await discovery.discover();
|
|
205
|
+
const catalog = await discovery.discover({ force: args.includes('--force') });
|
|
207
206
|
if (hasJson) {
|
|
208
207
|
console.log(JSON.stringify(catalog, null, 2));
|
|
209
208
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @source @src/cli/router.ts
|
|
9
9
|
* @issue #33
|
|
10
10
|
*/
|
|
11
|
+
import { signalChild } from '../../process/signal-child.mjs';
|
|
11
12
|
import { spawn } from 'child_process';
|
|
12
13
|
import path from 'path';
|
|
13
14
|
/**
|
|
@@ -73,12 +74,12 @@ export class DefaultScriptRunner {
|
|
|
73
74
|
// does not exit within the deadline. Both kill() calls are wrapped
|
|
74
75
|
// because they can throw ESRCH on an already-exited child.
|
|
75
76
|
try {
|
|
76
|
-
child
|
|
77
|
+
signalChild(child, 'SIGTERM');
|
|
77
78
|
}
|
|
78
79
|
catch { /* already exited */ }
|
|
79
80
|
killEscalationId = setTimeout(() => {
|
|
80
81
|
try {
|
|
81
|
-
child
|
|
82
|
+
signalChild(child, 'SIGKILL');
|
|
82
83
|
}
|
|
83
84
|
catch { /* already exited */ }
|
|
84
85
|
}, killDeadlineMs);
|
|
@@ -32,10 +32,9 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import { spawnSync } from 'child_process';
|
|
34
34
|
import { readFile } from 'node:fs/promises';
|
|
35
|
-
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
36
|
-
import { tmpdir } from 'node:os';
|
|
35
|
+
import { mkdtempSync, rmSync, writeFileSync, realpathSync, statSync } from 'node:fs';
|
|
37
36
|
import { join } from 'node:path';
|
|
38
|
-
import { boundedSpawnSync } from '../../process/bounded-child-process.mjs';
|
|
37
|
+
import { boundedSpawn, boundedSpawnSync } from '../../process/bounded-child-process.mjs';
|
|
39
38
|
import { existsSync } from 'node:fs';
|
|
40
39
|
import { ensureRuntimeHome, writeProfileConfig, launchWithProfile } from '../../mcp/adapters/codex-runtime.js';
|
|
41
40
|
import { getFrameworkRoot } from '../../channel/manager.mjs';
|
|
@@ -314,8 +313,8 @@ function buildHeadlessLaunch(provider, binaryArgs, prompt) {
|
|
|
314
313
|
}
|
|
315
314
|
// File transport (opencode): the prompt never touches argv or stdin — it
|
|
316
315
|
// is written to a private temp file only this process can read, passed
|
|
317
|
-
// by path. `mkdtemp()` under the system temp
|
|
318
|
-
//
|
|
316
|
+
// by path. `mkdtemp()` under the independently verified system temp
|
|
317
|
+
// directory gives the
|
|
319
318
|
// directory itself a private, unpredictable name owned by this process;
|
|
320
319
|
// the file within it additionally gets an explicit `0600` mode via an
|
|
321
320
|
// exclusive create (`flag: 'wx'` — fails rather than silently
|
|
@@ -328,7 +327,15 @@ function buildHeadlessLaunch(provider, binaryArgs, prompt) {
|
|
|
328
327
|
// `launchProvider()`, keyed off `plan.tempDir`) handles the ordinary
|
|
329
328
|
// "launch ran, now clean up" path; this one exists only for the write
|
|
330
329
|
// itself failing before a `plan` is ever returned to that caller.
|
|
331
|
-
|
|
330
|
+
// os.tmpdir() trusts TMPDIR/TEMP/TMP, which can point into the project.
|
|
331
|
+
// Select and validate the OS location independently of those overrides.
|
|
332
|
+
const systemTemp = realpathSync(process.platform === 'win32' ? join(process.env.SystemRoot ?? 'C:/Windows', 'Temp') : '/tmp');
|
|
333
|
+
const info = statSync(systemTemp);
|
|
334
|
+
if (!info.isDirectory() || (process.platform !== 'win32'
|
|
335
|
+
&& (info.uid !== 0 && info.uid !== process.getuid?.() || (info.mode & 0o022) !== 0 && (info.mode & 0o1000) === 0))) {
|
|
336
|
+
throw new Error('Unsafe system temporary directory for session prompt');
|
|
337
|
+
}
|
|
338
|
+
const tempDir = mkdtempSync(join(systemTemp, 'aiwg-session-prompt-'));
|
|
332
339
|
try {
|
|
333
340
|
const promptPath = join(tempDir, 'prompt.txt');
|
|
334
341
|
writeFileSync(promptPath, prompt, { encoding: 'utf-8', mode: 0o600, flag: 'wx' });
|
|
@@ -355,7 +362,7 @@ function buildHeadlessLaunch(provider, binaryArgs, prompt) {
|
|
|
355
362
|
* and without a terminal, this refuses before spawning anything that would
|
|
356
363
|
* hang.
|
|
357
364
|
*/
|
|
358
|
-
function launchProvider(provider, mcpInjected, mcpConfigPath, profile, settingsPath, prompt, interactive) {
|
|
365
|
+
async function launchProvider(provider, mcpInjected, mcpConfigPath, profile, settingsPath, prompt, interactive) {
|
|
359
366
|
const cfg = getProviderConfig(provider);
|
|
360
367
|
if (!isSpawnableProvider(provider)) {
|
|
361
368
|
// Not spawnable — a prompt can never be delivered to a binary that does
|
|
@@ -424,11 +431,14 @@ ${cfg.guidanceMessage ?? `Open ${cfg.name} in your project directory to begin.`}
|
|
|
424
431
|
// 8); stdin-transport providers get it via `input` (never inherited
|
|
425
432
|
// from the parent), file-transport providers get it via a private
|
|
426
433
|
// temp file path already baked into `plan.args`.
|
|
427
|
-
const
|
|
434
|
+
const launchOptions = {
|
|
428
435
|
stdio: plan.input !== undefined ? ['pipe', 'inherit', 'inherit'] : ['ignore', 'inherit', 'inherit'],
|
|
429
436
|
env: process.env,
|
|
430
437
|
...(plan.input !== undefined ? { input: plan.input } : {}),
|
|
431
|
-
}
|
|
438
|
+
};
|
|
439
|
+
const result = plan.tempDir
|
|
440
|
+
? await boundedSpawn(cfg.binary, plan.args, 'long', { ...launchOptions, stdio: ['ignore', 'inherit', 'inherit'] }, () => rmSync(plan.tempDir, { recursive: true, force: true }))
|
|
441
|
+
: boundedSpawnSync(cfg.binary, plan.args, 'long', launchOptions);
|
|
432
442
|
const { exitCode, message } = exitCodeForSpawnResult(result, cfg.binary);
|
|
433
443
|
return message ? { exitCode, message } : { exitCode };
|
|
434
444
|
}
|
|
@@ -2,8 +2,12 @@ import { existsSync, linkSync, mkdirSync, readFileSync, realpathSync, renameSync
|
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { basename, dirname, isAbsolute, join, resolve, } from 'node:path';
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { providerScopeWarnings } from '../../sessions/coverage-preflight.js';
|
|
5
6
|
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, GROKBOT_ADAPTER_VERSION, GROKBOT_NATIVE_REPLICA_LOCATOR_CLASS, GrokbotSessionAdapter, GROK_BUILD_ADAPTER_VERSION, GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS, GrokBuildSessionAdapter, grokBuildList, grokBuildSearch, grokBuildExport, grokHeadlessSessionIdFromFile, MUSE_ADAPTER_VERSION, MuseSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, DEEPSEEK_HARNESS_ADAPTER_VERSION, DeepSeekHarnessSessionAdapter, OmpSessionAdapter, OMP_ADAPTER_VERSION, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, createSessionAdapterRegistry, coveragePreflight, expectedSessionProviders, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, buildSessionExportPlan, reverifySessionExportPlan, buildSessionAiwgFortemiIndexExport, recoverAiwgFortemiIndexFromFullV1Shard, embedAttachmentsInFullV1Shard, recoverEmbeddedAttachments, SESSION_EXPORT_PLAN_SCHEMA_VERSION, } from '../../sessions/index.js';
|
|
7
|
+
import { resolveImportExclusions } from '../../sessions/import-exclusions.js';
|
|
8
|
+
import { resolveImportLimits } from '../../sessions/import-limits.js';
|
|
6
9
|
import { classifyGrokbotBlobName } from '../../sessions/adapters/grokbot-locator.js';
|
|
10
|
+
import { readAiwgConfig } from '../../config/aiwg-config.js';
|
|
7
11
|
const JSON_CONTRACT_VERSION = '1.0.0';
|
|
8
12
|
async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
|
|
9
13
|
const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
|
|
@@ -48,28 +52,30 @@ Commands:
|
|
|
48
52
|
promote <id> <version> Preview promotion; use --confirm to write
|
|
49
53
|
tag <session-id> <tag> Add a catalog tag
|
|
50
54
|
relocate <source-id> <file> Update AIWG source-location metadata
|
|
51
|
-
reindex
|
|
55
|
+
reindex --workspace <path-or-id> | --all-workspaces Rebuild catalog indexes
|
|
52
56
|
delete <session-id> Preview deletion; use --confirm to tombstone
|
|
53
57
|
restore <session-id> Restore a reversible catalog tombstone
|
|
54
58
|
purge <session-id> Preview terminal AIWG-copy purge
|
|
55
59
|
audit --workspace <id> Read content-free mutation events
|
|
56
60
|
analytics <view> --workspace <id> Summary, tool-calls, escalations, or HITL
|
|
57
61
|
forensics <view> --workspace <id> Authorized timeline, indicators, or evidence
|
|
58
|
-
doctor Check catalog
|
|
62
|
+
doctor Check catalog integrity and configured provider scope
|
|
59
63
|
|
|
60
64
|
Options:
|
|
61
65
|
--json Emit the versioned JSON contract
|
|
62
66
|
--dry-run Preview a mutation without changing state
|
|
67
|
+
--all-workspaces Reindex every workspace in the selected catalog (reindex only)
|
|
63
68
|
--db <path> Select a catalog; relative paths resolve from cwd
|
|
64
69
|
--workspace <path-or-id> Select the workspace within that catalog for reads
|
|
65
70
|
(default: current project, matching cwd, or sole catalog workspace)
|
|
66
71
|
Catalog defaults to <project-or-cwd>/.aiwg/sessions/catalog.sqlite
|
|
67
72
|
Imports for other workspaces stay in the selected catalog;
|
|
68
73
|
use --db to read that catalog from another directory
|
|
69
|
-
--expected-providers <ids>
|
|
74
|
+
--expected-providers <ids> Explicit scope for this invocation; refresh re-reads workspace config
|
|
75
|
+
--carry-forward <catalog> Rebuild from sources plus re-redacted stored history (import-discovered)
|
|
70
76
|
--manifest <path> Override the discovery manifest path
|
|
71
77
|
--provider-home <path> Override the provider home root (testing/portable homes)
|
|
72
|
-
--codex-root <path>
|
|
78
|
+
--codex-root <path> Authorize a shared Codex sessions/export root (repeatable)
|
|
73
79
|
--omp-root <path> Explicitly authorize an OMP profile sessions root
|
|
74
80
|
--muse-root <path> Explicitly authorize a Muse Code sessions root
|
|
75
81
|
--dsh-root <path> Explicitly authorize a DeepSeek Harness sessions root
|
|
@@ -78,6 +84,10 @@ Options:
|
|
|
78
84
|
(default: grok on PATH, then $GROK_HOME/bin/grok)
|
|
79
85
|
--confirm, --yes Confirm a persistent discovered batch import
|
|
80
86
|
--lock-wait-ms <n> Maximum import-lease wait (default 5000)
|
|
87
|
+
--exclude <id-or-glob> Skip a session ID or absolute path glob (repeatable); adds to sessions.import.exclude and AIWG_SESSIONS_IMPORT_EXCLUDE
|
|
88
|
+
--max-record-bytes <n> Import record limit (default 67108864); overrides AIWG_SESSIONS_IMPORT_MAX_RECORD_BYTES and sessions.import.max_record_bytes
|
|
89
|
+
--max-source-bytes <n> Import source limit (default 1073741824, 1 GiB; 0 unlimited); overrides AIWG_SESSIONS_IMPORT_MAX_SOURCE_BYTES and sessions.import.max_source_bytes
|
|
90
|
+
Import limit precedence: CLI flag > env var > workspace config > default.
|
|
81
91
|
--inactivity-threshold <duration> Historical inactivity threshold (default 24h)
|
|
82
92
|
--min-coverage <0..1> Fail list/report commands below a coverage ratio
|
|
83
93
|
--provider <id> Filter list or select an import adapter
|
|
@@ -110,9 +120,9 @@ Analytics / forensics:
|
|
|
110
120
|
--group-by tool|session|provider, --limit <1..5000>
|
|
111
121
|
--authorize-forensics Required for each authorized forensic invocation
|
|
112
122
|
--markdown Render a sanitized forensic timeline table`;
|
|
113
|
-
function printHelp(ctx, exitCode = EXIT.ok) {
|
|
123
|
+
async function printHelp(ctx, exitCode = EXIT.ok) {
|
|
114
124
|
if (ctx.args.includes('--json'))
|
|
115
|
-
emit(envelope('sessions.help', 'ok', { usage: HELP }, null));
|
|
125
|
+
await emit(envelope('sessions.help', 'ok', { usage: HELP }, null));
|
|
116
126
|
else
|
|
117
127
|
console.log(HELP);
|
|
118
128
|
return { exitCode };
|
|
@@ -136,7 +146,7 @@ export const sessionsHandler = {
|
|
|
136
146
|
const normalized = normalizeError(error);
|
|
137
147
|
const output = envelope('sessions', 'error', null, normalized.error);
|
|
138
148
|
if (json)
|
|
139
|
-
emit(output);
|
|
149
|
+
await emit(output);
|
|
140
150
|
else
|
|
141
151
|
console.error(`${normalized.error.code}: ${normalized.error.message}`);
|
|
142
152
|
return { exitCode: normalized.exitCode, message: normalized.error.message };
|
|
@@ -148,7 +158,7 @@ export const sessionsHandler = {
|
|
|
148
158
|
try {
|
|
149
159
|
const result = await executeCommand(ctx, parsed);
|
|
150
160
|
if (json)
|
|
151
|
-
emit(result.envelope);
|
|
161
|
+
await emit(result.envelope);
|
|
152
162
|
else
|
|
153
163
|
printHuman(result.envelope);
|
|
154
164
|
return { exitCode: result.exitCode };
|
|
@@ -157,7 +167,7 @@ export const sessionsHandler = {
|
|
|
157
167
|
const normalized = normalizeError(error);
|
|
158
168
|
const output = envelope(`sessions.${parsed.command}`, 'error', null, normalized.error);
|
|
159
169
|
if (json)
|
|
160
|
-
emit(output);
|
|
170
|
+
await emit(output);
|
|
161
171
|
else
|
|
162
172
|
console.error(`${normalized.error.code}: ${normalized.error.message}`);
|
|
163
173
|
return { exitCode: normalized.exitCode, message: normalized.error.message };
|
|
@@ -590,11 +600,22 @@ async function executeCommand(ctx, args) {
|
|
|
590
600
|
return ok(command, { sourceId, redactedLocator });
|
|
591
601
|
}
|
|
592
602
|
case 'reindex': {
|
|
593
|
-
const
|
|
603
|
+
const allWorkspaces = args.flags.has('--all-workspaces');
|
|
604
|
+
if (allWorkspaces && args.values.has('--workspace')) {
|
|
605
|
+
throw new CliError('INVALID_ARGUMENT', '--all-workspaces cannot be combined with --workspace', EXIT.usage);
|
|
606
|
+
}
|
|
607
|
+
const workspaceId = allWorkspaces
|
|
608
|
+
? undefined
|
|
609
|
+
: authorizationContext(ctx, args, command).workspaceId;
|
|
610
|
+
const data = {
|
|
611
|
+
operation: 'reindex',
|
|
612
|
+
allWorkspaces,
|
|
613
|
+
workspaceIds: allWorkspaces ? repository.listWorkspaceIds() : [workspaceId],
|
|
614
|
+
};
|
|
594
615
|
if (isDryRun(ctx, args))
|
|
595
|
-
return preview(command,
|
|
616
|
+
return preview(command, data);
|
|
596
617
|
repository.reindex(workspaceId);
|
|
597
|
-
return ok(command,
|
|
618
|
+
return ok(command, data);
|
|
598
619
|
}
|
|
599
620
|
case 'audit': {
|
|
600
621
|
const { workspaceId } = readAuthorizationContext(ctx, args, command, repository);
|
|
@@ -706,12 +727,22 @@ async function executeCommand(ctx, args) {
|
|
|
706
727
|
providerLogsModified: false,
|
|
707
728
|
});
|
|
708
729
|
}
|
|
709
|
-
case 'doctor':
|
|
730
|
+
case 'doctor': {
|
|
731
|
+
const workspacePath = resolve(ctx.cwd, args.values.get('--workspace') ?? ctx.cwd);
|
|
732
|
+
const workspace = existsSync(workspacePath) ? realpathSync(workspacePath) : workspacePath;
|
|
733
|
+
const config = await readAiwgConfig(workspace);
|
|
734
|
+
const manifestPath = resolve(ctx.cwd, args.values.get('--manifest') ?? defaultDiscoveryManifestPath(workspace));
|
|
735
|
+
const preflight = existsSync(manifestPath)
|
|
736
|
+
? (await readDiscoveryManifest(manifestPath)).preflight
|
|
737
|
+
: repository.getCoverage(workspace).preflight;
|
|
738
|
+
const warnings = providerScopeWarnings(config?.providers ?? [], preflight?.expectedProviders ?? [], preflight?.scopeWarnings);
|
|
710
739
|
return ok(command, {
|
|
711
740
|
database: redactSourceLocator(databasePath(ctx, args)),
|
|
712
741
|
health: repository.doctor(),
|
|
742
|
+
warnings,
|
|
713
743
|
jsonContractVersion: JSON_CONTRACT_VERSION,
|
|
714
744
|
});
|
|
745
|
+
}
|
|
715
746
|
default:
|
|
716
747
|
throw new CliError('UNKNOWN_COMMAND', `unknown sessions command: ${command}`, EXIT.usage);
|
|
717
748
|
}
|
|
@@ -721,6 +752,7 @@ async function executeCommand(ctx, args) {
|
|
|
721
752
|
}
|
|
722
753
|
}
|
|
723
754
|
async function importSource(ctx, args) {
|
|
755
|
+
const limits = await configuredImportLimits(ctx, args);
|
|
724
756
|
const input = resolve(ctx.cwd, requiredPositional(args, 0, 'file'));
|
|
725
757
|
const providerInput = args.values.get('--provider') ?? 'generic';
|
|
726
758
|
const provider = assertSessionProviderId(providerInput);
|
|
@@ -753,37 +785,37 @@ async function importSource(ctx, args) {
|
|
|
753
785
|
const isDsh = provider === 'deepseek-harness';
|
|
754
786
|
const isWarp = provider === 'warp';
|
|
755
787
|
const isDevinDesktop = provider === 'devin-desktop';
|
|
756
|
-
const adapter = isDsh ? new DeepSeekHarnessSessionAdapter() : isOmp ? new OmpSessionAdapter() : isClaude
|
|
757
|
-
? new ClaudeSessionAdapter()
|
|
788
|
+
const adapter = isDsh ? new DeepSeekHarnessSessionAdapter(limits) : isOmp ? new OmpSessionAdapter(limits) : isClaude
|
|
789
|
+
? new ClaudeSessionAdapter(limits)
|
|
758
790
|
: isCodex
|
|
759
|
-
? new CodexSessionAdapter()
|
|
791
|
+
? new CodexSessionAdapter(limits)
|
|
760
792
|
: isCopilot
|
|
761
|
-
? new CopilotSessionAdapter()
|
|
793
|
+
? new CopilotSessionAdapter(limits)
|
|
762
794
|
: isCursor
|
|
763
|
-
? new CursorSessionAdapter()
|
|
795
|
+
? new CursorSessionAdapter(limits)
|
|
764
796
|
: isFactory
|
|
765
|
-
? new FactorySessionAdapter()
|
|
797
|
+
? new FactorySessionAdapter(limits)
|
|
766
798
|
: isHermes
|
|
767
|
-
? new HermesSessionAdapter()
|
|
799
|
+
? new HermesSessionAdapter(limits)
|
|
768
800
|
: isOpenCode
|
|
769
|
-
? new OpenCodeSessionAdapter()
|
|
801
|
+
? new OpenCodeSessionAdapter(limits)
|
|
770
802
|
: isOpenClaw
|
|
771
|
-
? new OpenClawSessionAdapter()
|
|
803
|
+
? new OpenClawSessionAdapter(limits)
|
|
772
804
|
: isOpenHuman
|
|
773
|
-
? new OpenHumanSessionAdapter()
|
|
805
|
+
? new OpenHumanSessionAdapter(limits)
|
|
774
806
|
: isGrokbot
|
|
775
|
-
? new GrokbotSessionAdapter()
|
|
807
|
+
? new GrokbotSessionAdapter(limits)
|
|
776
808
|
: isGrokBuild
|
|
777
|
-
? new GrokBuildSessionAdapter()
|
|
809
|
+
? new GrokBuildSessionAdapter(limits)
|
|
778
810
|
: isMuse
|
|
779
|
-
? new MuseSessionAdapter()
|
|
811
|
+
? new MuseSessionAdapter(limits)
|
|
780
812
|
: isPi
|
|
781
|
-
? new PiSessionAdapter()
|
|
813
|
+
? new PiSessionAdapter(limits)
|
|
782
814
|
: isWarp
|
|
783
|
-
? new WarpSessionAdapter()
|
|
815
|
+
? new WarpSessionAdapter(limits)
|
|
784
816
|
: isDevinDesktop
|
|
785
|
-
? new DevinDesktopSessionAdapter()
|
|
786
|
-
: new GenericSessionInterchangeAdapter();
|
|
817
|
+
? new DevinDesktopSessionAdapter(limits)
|
|
818
|
+
: new GenericSessionInterchangeAdapter(limits);
|
|
787
819
|
const locatorClass = isDsh ? 'deepseek-harness-session-v2-jsonl' : isOmp ? 'omp-session-v3-jsonl' : isClaude
|
|
788
820
|
? claudeLocatorClass(input)
|
|
789
821
|
: isCodex
|
|
@@ -932,8 +964,9 @@ async function importSource(ctx, args) {
|
|
|
932
964
|
try {
|
|
933
965
|
const repository = openRepository(ctx, args);
|
|
934
966
|
try {
|
|
967
|
+
const interruptedRuns = repository.interruptRunningBatchImports();
|
|
935
968
|
const receipts = await new IncrementalSessionImporter(repository).import({
|
|
936
|
-
source, selectedSource, adapter, workspaceId, policyVersion: '1.0.0',
|
|
969
|
+
source, selectedSource, adapter, workspaceId, policyVersion: '1.0.0', limits,
|
|
937
970
|
inactivityThresholdMs: inactivityThreshold(args.values.get('--inactivity-threshold')),
|
|
938
971
|
});
|
|
939
972
|
for (const warning of workspaceReport.warnings)
|
|
@@ -942,6 +975,7 @@ async function importSource(ctx, args) {
|
|
|
942
975
|
sourceId,
|
|
943
976
|
...workspaceReport,
|
|
944
977
|
receipts,
|
|
978
|
+
interruptedRuns,
|
|
945
979
|
totals: {
|
|
946
980
|
sessionsInserted: receipts.reduce((sum, item) => sum + item.sessionsInserted, 0),
|
|
947
981
|
eventsInserted: receipts.reduce((sum, item) => sum + item.eventsInserted, 0),
|
|
@@ -1234,8 +1268,15 @@ async function exportUnpack(ctx, args, command) {
|
|
|
1234
1268
|
}
|
|
1235
1269
|
async function discoverWorkspace(ctx, args) {
|
|
1236
1270
|
const workspace = resolve(ctx.cwd, requiredValue(args, '--workspace'));
|
|
1271
|
+
const config = await readAiwgConfig(workspace);
|
|
1272
|
+
const canonicalWorkspace = realpathSync(workspace);
|
|
1273
|
+
const manifestPath = resolve(ctx.cwd, args.values.get('--manifest') ?? defaultDiscoveryManifestPath(canonicalWorkspace));
|
|
1274
|
+
const exclude = resolveImportExclusions(config?.sessions?.import, args.exclude);
|
|
1275
|
+
const previous = exclude.length > 0 && existsSync(manifestPath) ? await readDiscoveryManifest(manifestPath) : undefined;
|
|
1237
1276
|
const manifest = await discoverWorkspaceHistories({
|
|
1238
1277
|
workspace,
|
|
1278
|
+
knownSources: previous?.workspaceId === canonicalWorkspace ? previous.sources : undefined,
|
|
1279
|
+
exclude,
|
|
1239
1280
|
expectedProviders: requestedProviders(args),
|
|
1240
1281
|
providerHome: args.values.has('--provider-home')
|
|
1241
1282
|
? resolve(ctx.cwd, args.values.get('--provider-home'))
|
|
@@ -1248,12 +1289,13 @@ async function discoverWorkspace(ctx, args) {
|
|
|
1248
1289
|
? resolve(ctx.cwd, args.values.get('--dsh-root')) : undefined,
|
|
1249
1290
|
grokbotRoot: args.values.has('--grokbot-root')
|
|
1250
1291
|
? resolve(ctx.cwd, args.values.get('--grokbot-root')) : undefined,
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1292
|
+
codexRoots: [
|
|
1293
|
+
...(config?.sessions?.codex_roots ?? []).map((root) => resolve(workspace, root)),
|
|
1294
|
+
...args.codexRoots.map((root) => resolve(ctx.cwd, root)),
|
|
1295
|
+
],
|
|
1254
1296
|
});
|
|
1255
|
-
const manifestPath = resolve(ctx.cwd, args.values.get('--manifest') ?? defaultDiscoveryManifestPath(manifest.workspacePath));
|
|
1256
1297
|
const data = {
|
|
1298
|
+
warnings: manifest.preflight?.scopeWarnings ?? [],
|
|
1257
1299
|
manifest: publicDiscoveryManifest(manifest),
|
|
1258
1300
|
manifestPath: redactSourceLocator(manifestPath),
|
|
1259
1301
|
exactManifestRequiredForImport: true,
|
|
@@ -1267,12 +1309,28 @@ async function discoverWorkspace(ctx, args) {
|
|
|
1267
1309
|
async function importDiscovered(ctx, args) {
|
|
1268
1310
|
const workspace = resolve(ctx.cwd, requiredValue(args, '--workspace'));
|
|
1269
1311
|
const canonicalWorkspace = realpathSync(workspace);
|
|
1312
|
+
const limits = await configuredImportLimits(ctx, args, canonicalWorkspace);
|
|
1313
|
+
const config = await readAiwgConfig(canonicalWorkspace);
|
|
1314
|
+
const exclude = resolveImportExclusions(config?.sessions?.import, args.exclude);
|
|
1270
1315
|
const manifestPath = resolve(ctx.cwd, args.values.get('--manifest') ?? defaultDiscoveryManifestPath(canonicalWorkspace));
|
|
1271
1316
|
const manifest = await readDiscoveryManifest(manifestPath);
|
|
1272
1317
|
if (manifest.workspaceId !== canonicalWorkspace) {
|
|
1273
1318
|
throw new CliError('MANIFEST_WORKSPACE_MISMATCH', 'discovery manifest does not belong to the explicitly authorized workspace', EXIT.contract);
|
|
1274
1319
|
}
|
|
1320
|
+
const carryPath = args.values.has('--carry-forward')
|
|
1321
|
+
? resolve(ctx.cwd, args.values.get('--carry-forward')) : undefined;
|
|
1322
|
+
if (carryPath) {
|
|
1323
|
+
const sourceStat = statSync(carryPath);
|
|
1324
|
+
const target = databasePath(ctx, args);
|
|
1325
|
+
if (existsSync(target)) {
|
|
1326
|
+
const targetStat = statSync(target);
|
|
1327
|
+
if (sourceStat.dev === targetStat.dev && sourceStat.ino === targetStat.ino) {
|
|
1328
|
+
throw new CliError('INVALID_ARGUMENT', 'carry-forward requires a separate destination catalog', EXIT.usage);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1275
1332
|
const expected = requestedProviders(args);
|
|
1333
|
+
const warnings = providerScopeWarnings(config?.providers ?? [], manifest.preflight?.expectedProviders ?? [], manifest.preflight?.scopeWarnings);
|
|
1276
1334
|
if (expected && JSON.stringify(expected) !== JSON.stringify(manifest.preflight?.expectedProviders)) {
|
|
1277
1335
|
throw new SessionContractError('INVALID_ARGUMENT', 'expected provider scope differs from the saved manifest; rediscover with --expected-providers');
|
|
1278
1336
|
}
|
|
@@ -1288,25 +1346,35 @@ async function importDiscovered(ctx, args) {
|
|
|
1288
1346
|
// A preview can still describe the exact manifest before a catalog exists.
|
|
1289
1347
|
}
|
|
1290
1348
|
return preview('import-discovered', {
|
|
1349
|
+
warnings,
|
|
1291
1350
|
manifest: publicDiscoveryManifest(manifest),
|
|
1292
|
-
receipt: previewDiscoveryImport(manifest, existing),
|
|
1351
|
+
receipt: previewDiscoveryImport(manifest, existing, new Date(), exclude),
|
|
1293
1352
|
confirmationRequired: !isDryRun(ctx, args),
|
|
1294
1353
|
wouldPersist: false,
|
|
1354
|
+
...(carryPath ? { carryForward: redactSourceLocator(carryPath) } : {}),
|
|
1295
1355
|
});
|
|
1296
1356
|
}
|
|
1297
1357
|
const lease = await acquireImportLease(databasePath(ctx, args), sha256(['discovered-import', manifest.manifestId, manifest.workspaceId].join('\0')), {
|
|
1298
1358
|
waitMs: boundedInteger(args.values.get('--lock-wait-ms'), 5_000, 0, 300_000, '--lock-wait-ms'),
|
|
1299
1359
|
});
|
|
1300
1360
|
try {
|
|
1301
|
-
const
|
|
1361
|
+
const previous = carryPath ? new SessionRepository(carryPath, { readonly: true }) : undefined;
|
|
1362
|
+
let repository;
|
|
1302
1363
|
try {
|
|
1364
|
+
repository = openRepository(ctx, args);
|
|
1365
|
+
const interruptedRuns = repository.interruptRunningBatchImports();
|
|
1303
1366
|
const receipt = await importDiscoveryManifest({
|
|
1304
1367
|
manifest,
|
|
1305
1368
|
repository,
|
|
1369
|
+
carryForward: previous,
|
|
1370
|
+
limits,
|
|
1371
|
+
exclude,
|
|
1306
1372
|
signal: ctx.signal,
|
|
1307
1373
|
inactivityThresholdMs: inactivityThreshold(args.values.get('--inactivity-threshold')),
|
|
1308
1374
|
});
|
|
1375
|
+
receipt.interruptedRuns = interruptedRuns;
|
|
1309
1376
|
return ok('import-discovered', {
|
|
1377
|
+
warnings,
|
|
1310
1378
|
manifestId: manifest.manifestId,
|
|
1311
1379
|
receipt,
|
|
1312
1380
|
resumable: receipt.run.status !== 'complete',
|
|
@@ -1318,7 +1386,8 @@ async function importDiscovered(ctx, args) {
|
|
|
1318
1386
|
});
|
|
1319
1387
|
}
|
|
1320
1388
|
finally {
|
|
1321
|
-
repository
|
|
1389
|
+
repository?.close();
|
|
1390
|
+
previous?.close();
|
|
1322
1391
|
}
|
|
1323
1392
|
}
|
|
1324
1393
|
finally {
|
|
@@ -1648,9 +1717,25 @@ function catalogScope(ctx, args, repository, workspaceId) {
|
|
|
1648
1717
|
: null,
|
|
1649
1718
|
};
|
|
1650
1719
|
}
|
|
1720
|
+
async function configuredImportLimits(ctx, args, workspace) {
|
|
1721
|
+
const selectedWorkspace = workspace ?? (args.values.has('--workspace')
|
|
1722
|
+
? resolve(ctx.cwd, args.values.get('--workspace')) : ctx.cwd);
|
|
1723
|
+
try {
|
|
1724
|
+
const config = await readAiwgConfig(selectedWorkspace);
|
|
1725
|
+
return resolveImportLimits(config?.sessions?.import, {
|
|
1726
|
+
maxRecordBytes: args.values.get('--max-record-bytes'),
|
|
1727
|
+
maxSourceBytes: args.values.get('--max-source-bytes'),
|
|
1728
|
+
});
|
|
1729
|
+
}
|
|
1730
|
+
catch (error) {
|
|
1731
|
+
throw new CliError('INVALID_ARGUMENT', error instanceof Error ? error.message : String(error), EXIT.usage);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1651
1734
|
function parseArgs(argv) {
|
|
1652
1735
|
const flags = new Set();
|
|
1653
1736
|
const values = new Map();
|
|
1737
|
+
const codexRoots = [];
|
|
1738
|
+
const exclude = [];
|
|
1654
1739
|
const positionals = [];
|
|
1655
1740
|
const valueFlags = new Set([
|
|
1656
1741
|
'--db', '--provider', '--workspace', '--tag', '--limit', '--cursor', '--source-id',
|
|
@@ -1658,8 +1743,8 @@ function parseArgs(argv) {
|
|
|
1658
1743
|
'--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
|
|
1659
1744
|
'--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
|
|
1660
1745
|
'--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
|
|
1661
|
-
'--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--grokbot-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1662
|
-
'--inactivity-threshold', '--expected-providers',
|
|
1746
|
+
'--carry-forward', '--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--grokbot-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1747
|
+
'--inactivity-threshold', '--expected-providers', '--exclude', '--max-record-bytes', '--max-source-bytes',
|
|
1663
1748
|
'--control-events',
|
|
1664
1749
|
'--session', '--status', '--actor', '--group-by',
|
|
1665
1750
|
'--out', '--plan', '--input', '--shard-name', '--max-attachment-bytes', '--format', '--grok-bin',
|
|
@@ -1673,6 +1758,10 @@ function parseArgs(argv) {
|
|
|
1673
1758
|
throw new CliError('MISSING_OPTION_VALUE', `missing value for ${arg}`, EXIT.usage);
|
|
1674
1759
|
}
|
|
1675
1760
|
values.set(arg, value);
|
|
1761
|
+
if (arg === '--codex-root')
|
|
1762
|
+
codexRoots.push(value);
|
|
1763
|
+
if (arg === '--exclude')
|
|
1764
|
+
exclude.push(value);
|
|
1676
1765
|
index += 1;
|
|
1677
1766
|
}
|
|
1678
1767
|
else if (arg.startsWith('-')) {
|
|
@@ -1685,7 +1774,7 @@ function parseArgs(argv) {
|
|
|
1685
1774
|
positionals.push(arg);
|
|
1686
1775
|
}
|
|
1687
1776
|
}
|
|
1688
|
-
return { command, positionals, flags, values };
|
|
1777
|
+
return { command, positionals, flags, values, codexRoots, exclude };
|
|
1689
1778
|
}
|
|
1690
1779
|
function requestedProviders(args) {
|
|
1691
1780
|
const value = args.values.get('--expected-providers');
|
|
@@ -1961,8 +2050,13 @@ function preview(command, data) {
|
|
|
1961
2050
|
function envelope(command, status, data, error) {
|
|
1962
2051
|
return { contractVersion: JSON_CONTRACT_VERSION, command, status, data, error };
|
|
1963
2052
|
}
|
|
1964
|
-
function emit(value) {
|
|
2053
|
+
async function emit(value) {
|
|
1965
2054
|
console.log(JSON.stringify(value, null, 2));
|
|
2055
|
+
// The launcher and router may force exit after the handler returns. A write
|
|
2056
|
+
// callback waits for the JSON already queued on stdout, including on pipes.
|
|
2057
|
+
await new Promise((resolve, reject) => {
|
|
2058
|
+
process.stdout.write('', (error) => error ? reject(error) : resolve());
|
|
2059
|
+
});
|
|
1966
2060
|
}
|
|
1967
2061
|
function printHuman(value) {
|
|
1968
2062
|
if (value.status === 'preview')
|
|
@@ -2015,7 +2109,7 @@ function normalizeError(error) {
|
|
|
2015
2109
|
}
|
|
2016
2110
|
if (error instanceof SessionContractError) {
|
|
2017
2111
|
const exitCode = error.code === 'UNSUPPORTED_OPERATION' ? EXIT.unsupported : EXIT.contract;
|
|
2018
|
-
return { error: { code: error.code, message: error.message }, exitCode };
|
|
2112
|
+
return { error: { code: error.code, message: error.message, ...(error.detail ? { details: error.detail } : {}) }, exitCode };
|
|
2019
2113
|
}
|
|
2020
2114
|
if (error instanceof ImportLeaseContentionError) {
|
|
2021
2115
|
return {
|
|
@@ -8,7 +8,7 @@ import { isInteractive } from '../env.js';
|
|
|
8
8
|
import { boundedSpawnSync } from '../../process/bounded-child-process.mjs';
|
|
9
9
|
import { sha256 } from '../../security/artifact-trust.js';
|
|
10
10
|
import { artifactVerifyHandler } from './artifact-verify.js';
|
|
11
|
-
import { requireFlagValue, MissingFlagValueError } from '../flag-parsing.js';
|
|
11
|
+
import { requireFlagValue, MissingFlagValueError, collectFlagValues, hasPositionalOrSwitch, argsTerminatorIndex, valueTokenIndexes } from '../flag-parsing.js';
|
|
12
12
|
import { exitCodeForSpawnResult } from '../child-process-result.js';
|
|
13
13
|
import { askString, createPromptInterface } from '../prompt-utils.js';
|
|
14
14
|
const SETUP_SCHEMA_REL = 'agentic/code/addons/agentic-installer/schemas/v1/setup-manifest.schema.json';
|
|
@@ -76,9 +76,8 @@ Safety:
|
|
|
76
76
|
Headless input steps (#3062):
|
|
77
77
|
A 'type: ask' step resolves its declared 'params' the same way a 'script'
|
|
78
78
|
step's env vars do (--param/--params-file/env/default); if every declared
|
|
79
|
-
param is already resolved it runs headless
|
|
80
|
-
|
|
81
|
-
mechanism for 'ask' steps, with or without a terminal. A step marked
|
|
79
|
+
param is already resolved it runs headless; otherwise a terminal prompts
|
|
80
|
+
for missing values. Without a terminal it refuses and names the missing params. A step marked
|
|
82
81
|
'interactive: true' runs an arbitrary script whose questions cannot be
|
|
83
82
|
enumerated; without a terminal it is refused outright. Every selected
|
|
84
83
|
step (including nested 'platform-route' steps) is preflighted for both
|
|
@@ -96,40 +95,17 @@ Headless input steps (#3062):
|
|
|
96
95
|
function flagValue(args, name) {
|
|
97
96
|
return requireFlagValue(args, {}, name);
|
|
98
97
|
}
|
|
98
|
+
const VALUE_FLAGS = [
|
|
99
|
+
'--manifest', '--schema', '--platform', '--distro', '--params-file', '--param', '--set',
|
|
100
|
+
'--step', '--skip', '--type', '--output', '--name', '--attestation', '--policy', '--state',
|
|
101
|
+
'--asset-type', '--namespace', '--channel',
|
|
102
|
+
];
|
|
99
103
|
function hasFlag(args, ...names) {
|
|
100
|
-
return
|
|
104
|
+
return names.some(name => hasPositionalOrSwitch(args, name, VALUE_FLAGS));
|
|
101
105
|
}
|
|
102
106
|
function positionalManifest(args) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
'--schema',
|
|
106
|
-
'--platform',
|
|
107
|
-
'--distro',
|
|
108
|
-
'--params-file',
|
|
109
|
-
'--param',
|
|
110
|
-
'--set',
|
|
111
|
-
'--step',
|
|
112
|
-
'--skip',
|
|
113
|
-
'--type',
|
|
114
|
-
'--output',
|
|
115
|
-
'--name',
|
|
116
|
-
'--attestation',
|
|
117
|
-
'--policy',
|
|
118
|
-
'--state',
|
|
119
|
-
'--asset-type',
|
|
120
|
-
'--namespace',
|
|
121
|
-
'--channel',
|
|
122
|
-
]);
|
|
123
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
124
|
-
const arg = args[i];
|
|
125
|
-
if (valueFlags.has(arg)) {
|
|
126
|
-
i += 1;
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (!arg.startsWith('-'))
|
|
130
|
-
return arg;
|
|
131
|
-
}
|
|
132
|
-
return undefined;
|
|
107
|
+
const consumed = valueTokenIndexes(args, VALUE_FLAGS);
|
|
108
|
+
return args.slice(0, argsTerminatorIndex(args)).find((arg, index) => !consumed.has(index) && !arg.startsWith('-'));
|
|
133
109
|
}
|
|
134
110
|
function resolveSchemaPath(frameworkRoot, cwd, override) {
|
|
135
111
|
if (override)
|
|
@@ -472,15 +448,12 @@ function renderValidationText(result) {
|
|
|
472
448
|
}
|
|
473
449
|
function parseParamValues(args) {
|
|
474
450
|
const values = {};
|
|
475
|
-
for (
|
|
476
|
-
if (args[i] !== '--param' && args[i] !== '--set')
|
|
477
|
-
continue;
|
|
478
|
-
const raw = args[i + 1] ?? '';
|
|
451
|
+
for (const raw of collectFlagValues(args, {}, '--param', '--set')) {
|
|
479
452
|
const eq = raw.indexOf('=');
|
|
480
|
-
if (eq <= 0)
|
|
481
|
-
throw new
|
|
453
|
+
if (eq <= 0 || !raw.slice(0, eq).trim())
|
|
454
|
+
throw new MissingFlagValueError('--param KEY=VALUE');
|
|
455
|
+
// An empty parameter value is supported (e.g. explicitly clearing a default).
|
|
482
456
|
values[raw.slice(0, eq)] = raw.slice(eq + 1);
|
|
483
|
-
i += 1;
|
|
484
457
|
}
|
|
485
458
|
return values;
|
|
486
459
|
}
|
|
@@ -1068,10 +1041,21 @@ export async function runSetupManifest(options) {
|
|
|
1068
1041
|
return { exitCode: 1, message: `setup-run: platform ${target.os}${target.distro ? `/${target.distro}` : ''}/${target.arch}/${target.shell} is not declared in the manifest` };
|
|
1069
1042
|
}
|
|
1070
1043
|
const params = resolveParams(manifest, options);
|
|
1071
|
-
|
|
1044
|
+
const steps = selectedSteps(manifest, options);
|
|
1045
|
+
const askSteps = [];
|
|
1046
|
+
const collectAsks = (selected) => {
|
|
1047
|
+
for (const step of selected) {
|
|
1048
|
+
if (step.type === 'ask')
|
|
1049
|
+
askSteps.push(step);
|
|
1050
|
+
if (step.type === 'platform-route')
|
|
1051
|
+
collectAsks(step.routes?.find(route => route.platform === target.os)?.steps ?? []);
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
collectAsks(steps);
|
|
1055
|
+
const promptable = new Set(isInteractive() ? askSteps.flatMap(askStepParams) : []);
|
|
1056
|
+
if (params.missing.some(name => !promptable.has(name))) {
|
|
1072
1057
|
return { exitCode: 1, message: `setup-run: required params missing before execution: ${params.missing.join(', ')}` };
|
|
1073
1058
|
}
|
|
1074
|
-
const steps = selectedSteps(manifest, options);
|
|
1075
1059
|
if (options.step && steps.length === 0)
|
|
1076
1060
|
return { exitCode: 1, message: `setup-run: step '${options.step}' not found` };
|
|
1077
1061
|
if (options.dryRun) {
|
|
@@ -1095,6 +1079,17 @@ export async function runSetupManifest(options) {
|
|
|
1095
1079
|
message: `setup-run: refusing before executing any step:\n${blockers.map((b) => ` - ${b}`).join('\n')}`,
|
|
1096
1080
|
};
|
|
1097
1081
|
}
|
|
1082
|
+
// Resolve required ask inputs before any scripts can consume them.
|
|
1083
|
+
for (const step of askSteps) {
|
|
1084
|
+
const missing = missingAskParams(step, params.values).filter(name => params.missing.includes(name));
|
|
1085
|
+
if (!missing.length)
|
|
1086
|
+
continue;
|
|
1087
|
+
Object.assign(params.values, await promptForAskStep(step, missing));
|
|
1088
|
+
}
|
|
1089
|
+
const checked = resolveParams(manifest, { ...options, paramValues: { ...options.paramValues, ...params.values } });
|
|
1090
|
+
if (checked.missing.length)
|
|
1091
|
+
return { exitCode: 1, message: `setup-run: required params missing before execution: ${checked.missing.join(', ')}` };
|
|
1092
|
+
Object.assign(params.values, checked.values);
|
|
1098
1093
|
for (const step of steps) {
|
|
1099
1094
|
const result = await runStep(step, manifest, validation.manifestDir, params.values, target.os, options.yes);
|
|
1100
1095
|
if (!result.ok) {
|