@aiwg/cli 2026.10.1 → 2026.10.4
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/capability-matrix.yaml +270 -0
- package/agentic/code/providers/model-capabilities.v1.json +3183 -24
- package/bin/aiwg.mjs +135 -47
- package/dist/src/a2a/codecs.js +9 -0
- 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 +57 -18
- package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
- package/dist/src/artifacts/corpus-tools/vision-extract.js +107 -15
- 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 +285 -131
- package/dist/src/artifacts/index-files.js +132 -18
- package/dist/src/artifacts/index-preparation.js +65 -0
- package/dist/src/artifacts/index-refresh.js +576 -0
- package/dist/src/artifacts/index-worker.mjs +9 -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/repair.js +9 -4
- 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 +78 -12
- package/dist/src/cli/child-process-result.js +40 -0
- package/dist/src/cli/command-log.js +2 -3
- package/dist/src/cli/env.js +38 -16
- package/dist/src/cli/flag-parsing.js +236 -0
- 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 +218 -5
- package/dist/src/cli/handlers/diagnose.js +13 -5
- package/dist/src/cli/handlers/effect.js +4 -2
- package/dist/src/cli/handlers/evidence.js +3 -0
- package/dist/src/cli/handlers/feedback.js +14 -5
- 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 +248 -30
- package/dist/src/cli/handlers/lint.js +5 -0
- package/dist/src/cli/handlers/mc.js +23 -0
- package/dist/src/cli/handlers/models.js +169 -10
- package/dist/src/cli/handlers/ralph-launcher.js +2 -0
- package/dist/src/cli/handlers/ralph.js +3 -0
- package/dist/src/cli/handlers/refresh.js +28 -0
- package/dist/src/cli/handlers/regenerate.js +14 -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 +25 -11
- package/dist/src/cli/handlers/script-runner.js +19 -8
- package/dist/src/cli/handlers/session.js +406 -62
- package/dist/src/cli/handlers/sessions.js +243 -76
- package/dist/src/cli/handlers/setup-manifest.js +474 -79
- package/dist/src/cli/handlers/setup.js +180 -39
- package/dist/src/cli/handlers/steward.js +11 -0
- package/dist/src/cli/handlers/subcommands.js +60 -3
- package/dist/src/cli/handlers/team.js +18 -8
- package/dist/src/cli/handlers/uhp.js +3 -0
- package/dist/src/cli/handlers/use.js +307 -55
- package/dist/src/cli/handlers/utilities.js +125 -26
- package/dist/src/cli/handlers/version.js +8 -0
- package/dist/src/cli/prompt-utils.js +72 -0
- package/dist/src/cli/provider-resolution.js +11 -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 +349 -35
- package/dist/src/config/cli.js +256 -23
- package/dist/src/config/decision-config.js +106 -0
- package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
- package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -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-health.mjs +14 -3
- 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 +38 -11
- package/dist/src/config/user-registry.js +23 -15
- package/dist/src/config/user-state.js +7 -0
- package/dist/src/decision/adapters/jev.js +75 -27
- package/dist/src/decision/ask.js +203 -43
- package/dist/src/decision/context-live-qualification.js +2 -2
- package/dist/src/decision/driver.js +14 -7
- 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 +25 -6
- 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 +15 -14
- package/dist/src/decision/heldout/contract.js +30 -7
- package/dist/src/decision/index.js +1 -0
- package/dist/src/decision/interop.js +60 -8
- package/dist/src/decision/jev-credentials.js +15 -1
- package/dist/src/decision/ledger.js +942 -0
- 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/decision/validate.js +6 -3
- package/dist/src/effects/dispatch-verifier.js +252 -0
- package/dist/src/effects/index.js +1 -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/features/installer.js +2 -2
- package/dist/src/flow/graph-metadata.js +5 -0
- package/dist/src/gates/providers/loader.js +64 -18
- package/dist/src/installation/manager-command.d.mts +18 -0
- package/dist/src/installation/manager-command.mjs +15 -3
- package/dist/src/installation/manager.d.mts +49 -0
- package/dist/src/installation/manager.mjs +95 -5
- 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 +366 -56
- 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 +620 -85
- package/dist/src/mcp/config-file.d.mts +28 -0
- package/dist/src/mcp/config-file.mjs +279 -0
- package/dist/src/mcp/config-layers.d.mts +36 -0
- package/dist/src/mcp/config-layers.mjs +348 -0
- package/dist/src/mcp/credentials.d.mts +51 -0
- package/dist/src/mcp/credentials.mjs +484 -0
- package/dist/src/mcp/grok-build-config.d.mts +6 -0
- package/dist/src/mcp/grok-build-config.mjs +17 -27
- package/dist/src/mcp/helpers.mjs +109 -4
- 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/omp-config.mjs +50 -29
- package/dist/src/mcp/profiles.js +97 -23
- package/dist/src/mcp/profiles.mjs +99 -27
- package/dist/src/mcp/registry.js +248 -131
- package/dist/src/mcp/registry.mjs +169 -100
- 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 +127 -82
- 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-string.mjs +9 -0
- package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
- package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
- package/dist/src/mcp/tool-filters.d.mts +46 -0
- package/dist/src/mcp/tool-filters.mjs +357 -0
- package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
- package/dist/src/mcp/tools/decision.mjs +22 -3
- package/dist/src/mcp/tools/discovery.mjs +62 -55
- package/dist/src/mcp/tools/orchestration.mjs +50 -2
- package/dist/src/mcp/tools/subsystems.mjs +39 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +2856 -0
- package/dist/src/mcp/tools/worker-shell-control.mjs +289 -0
- package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
- package/dist/src/memory/project-registry.js +2 -2
- package/dist/src/mission-protocol/codecs.js +647 -1
- package/dist/src/mission-protocol/types.js +110 -0
- package/dist/src/mission-protocol/worker-status.js +2 -0
- package/dist/src/models/config-loader.js +76 -14
- package/dist/src/models/grok-build-models.js +93 -41
- package/dist/src/models/model-capabilities.v1.json +3183 -24
- package/dist/src/models/model-discovery.js +931 -67
- package/dist/src/models/provider-policy.js +719 -11
- package/dist/src/models/qualification-digest.d.mts +2 -0
- package/dist/src/models/qualification-digest.mjs +17 -0
- package/dist/src/models/resolver.js +261 -0
- package/dist/src/models/worker-direct-readiness.js +550 -0
- package/dist/src/models/worker-dispatch-offer.js +169 -0
- package/dist/src/models/worker-health-readiness.js +144 -0
- package/dist/src/models/worker-installation.d.mts +39 -0
- package/dist/src/models/worker-installation.mjs +986 -0
- package/dist/src/models/wrapper-route.js +18 -0
- package/dist/src/ops/registry.js +9 -14
- package/dist/src/plugins/standalone-packager.js +4 -3
- package/dist/src/process/bounded-child-process.d.mts +84 -0
- package/dist/src/process/bounded-child-process.mjs +430 -0
- package/dist/src/process/cli-command.d.mts +16 -0
- package/dist/src/process/cli-command.mjs +75 -0
- package/dist/src/process/signal-child.d.mts +6 -0
- package/dist/src/process/signal-child.mjs +7 -0
- package/dist/src/providers/capability-matrix.js +8 -0
- package/dist/src/providers/capability-matrix.yaml +270 -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 +53 -23
- 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/provider-definitions.js +9 -1
- package/dist/src/providers/provider-definitions.mjs +9 -2
- 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/executor-registry.js +16 -24
- package/dist/src/serve/fleet-mission-conductor.js +9 -0
- package/dist/src/serve/mission-conductor.js +47 -12
- package/dist/src/serve/shared-host-scheduler.js +2 -0
- package/dist/src/serve/worker-invocation.js +558 -0
- package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
- package/dist/src/serve/worker-stdin-frame.mjs +107 -0
- package/dist/src/sessions/adapter-registry.js +49 -0
- package/dist/src/sessions/adapters/claude.js +39 -54
- package/dist/src/sessions/adapters/codex.js +82 -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 +43 -9
- package/dist/src/sessions/adapters/grok-build.js +11 -11
- package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
- package/dist/src/sessions/adapters/grokbot.js +434 -24
- package/dist/src/sessions/adapters/hermes.js +27 -29
- package/dist/src/sessions/adapters/muse-workspace-scan.js +128 -0
- package/dist/src/sessions/adapters/muse.js +200 -104
- 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 +30 -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 +25 -5
- package/dist/src/sessions/batch-import.js +72 -51
- package/dist/src/sessions/candidates.js +47 -11
- package/dist/src/sessions/contracts.js +75 -2
- package/dist/src/sessions/coverage-preflight.js +134 -0
- package/dist/src/sessions/discovery.js +3 -0
- package/dist/src/sessions/export-plan.js +4 -3
- package/dist/src/sessions/grok-build-cli.js +67 -5
- 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 +84 -46
- package/dist/src/sessions/index.js +2 -0
- package/dist/src/sessions/lifecycle.js +45 -0
- package/dist/src/sessions/policy.js +133 -25
- package/dist/src/sessions/readers.js +106 -53
- package/dist/src/sessions/refresh.js +106 -0
- package/dist/src/sessions/repository.js +199 -63
- package/dist/src/sessions/workspace-discovery.js +315 -88
- package/dist/src/sessions/workspace-matching.js +107 -0
- package/dist/src/skills/adapters/clawhub.js +10 -8
- package/dist/src/skills/adapters/openclaw.js +10 -7
- 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 +195 -14
- package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
- package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
- package/dist/src/smiths/mcpsmith/example.js +1 -1
- 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 +85 -31
- package/dist/src/storage/backends/fs.js +18 -76
- package/dist/src/storage/backends/logseq.js +68 -7
- package/dist/src/storage/backends/obsidian.js +1 -0
- package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
- package/dist/src/testing/generators/test-code-generator.js +57 -30
- package/dist/src/tracker/forge-http.js +2 -1
- package/dist/src/uhp/client.js +11 -1
- package/dist/src/uhp/mission.js +5 -0
- package/dist/src/update/checker.d.mts +2 -0
- package/dist/src/update/checker.mjs +5 -5
- package/dist/src/update/notifier.mjs +54 -2
- 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/dist/src/writing/fidelity.js +18 -1
- package/package.json +32 -2
- package/schemas/mission-v1.schema.json +2429 -0
- package/schemas/models/model-catalog.v1.schema.json +301 -0
- package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
- package/schemas/models/model-policy.v1.schema.json +14 -0
- package/schemas/models/provider-model-capabilities.v1.schema.json +1072 -0
- package/tools/_resolve-impl.mjs +39 -2
- package/tools/agents/deploy-agents.mjs +64 -23
- package/tools/agents/providers/base.mjs +153 -166
- 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/grokbot.mjs +11 -12
- package/tools/agents/providers/hermes.mjs +62 -49
- package/tools/agents/providers/omp.mjs +5 -2
- package/tools/agents/providers/openclaw-translator.mjs +19 -5
- 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 +360 -0
- package/tools/providers/omp-transport.mjs +194 -0
- package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
- package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
- package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
- package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
- package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
- package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
- package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
- package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
- package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
- package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
- package/tools/ralph-external/lib/pi-adapter.mjs +329 -0
- package/tools/ralph-external/lib/provider-adapter.mjs +748 -0
- 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 +439 -0
- 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 +2916 -0
|
@@ -9,13 +9,15 @@
|
|
|
9
9
|
* @version 2024.12.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { signalChild } from '../process/signal-child.mjs';
|
|
12
13
|
import fs from 'fs/promises';
|
|
13
14
|
import { readFileSync, existsSync } from 'fs';
|
|
14
15
|
import path from 'path';
|
|
15
16
|
import { fileURLToPath } from 'url';
|
|
16
|
-
import {
|
|
17
|
+
import { spawn } from 'child_process';
|
|
17
18
|
import os from 'os';
|
|
18
19
|
import { resolveUserConfigDir } from '../config/user-config-dir.mjs';
|
|
20
|
+
import { boundedExecFileSync } from '../process/bounded-child-process.mjs';
|
|
19
21
|
import {
|
|
20
22
|
assertCanonicalInstallation,
|
|
21
23
|
createInstallationIdentity,
|
|
@@ -52,9 +54,9 @@ async function runWithTimeout(cmd, args, options = {}) {
|
|
|
52
54
|
let settled = false;
|
|
53
55
|
const timer = setTimeout(() => {
|
|
54
56
|
if (settled) return;
|
|
55
|
-
try { child
|
|
57
|
+
try { signalChild(child, 'SIGTERM'); } catch { /* already exited */ }
|
|
56
58
|
const kill9 = setTimeout(() => {
|
|
57
|
-
try { child
|
|
59
|
+
try { signalChild(child, 'SIGKILL'); } catch { /* already exited */ }
|
|
58
60
|
}, 5_000);
|
|
59
61
|
kill9.unref?.();
|
|
60
62
|
settled = true;
|
|
@@ -135,6 +137,50 @@ export function getPackageRoot() {
|
|
|
135
137
|
return path.resolve(__dirname, '..', '..');
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Resolve the installation root bin/aiwg.mjs actually dispatches to.
|
|
142
|
+
*
|
|
143
|
+
* This is the exact decision `resolveRouterPath()` in bin/aiwg.mjs makes
|
|
144
|
+
* when picking which `dist/` to load the compiled router (and therefore
|
|
145
|
+
* every compiled-dist module it imports, including the MCP server) from:
|
|
146
|
+
* the dev-mode edge checkout when configured and present and distinct from
|
|
147
|
+
* the package root, otherwise the package root itself. Shared so health
|
|
148
|
+
* checks (doctor) validate the layout the launcher will actually execute
|
|
149
|
+
* instead of re-deriving — and risking drifting from — the same decision
|
|
150
|
+
* (#276).
|
|
151
|
+
*
|
|
152
|
+
* @param {string} packageRoot - This install's own package root (`getPackageRoot()`).
|
|
153
|
+
* @param {{devMode?: boolean, edgePath?: string}} config - Channel config (`loadConfig()`).
|
|
154
|
+
* @returns {string} The effective root whose `dist/src/...` the launcher loads from.
|
|
155
|
+
*/
|
|
156
|
+
export function resolveEffectiveInstallationRoot(packageRoot, config) {
|
|
157
|
+
if (config?.devMode && config.edgePath && config.edgePath !== packageRoot) {
|
|
158
|
+
return config.edgePath;
|
|
159
|
+
}
|
|
160
|
+
return packageRoot;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Resolve the absolute path to the MCP server entrypoint the production
|
|
165
|
+
* launcher actually loads: `bin/aiwg.mjs` always dispatches to the
|
|
166
|
+
* *compiled* router (`resolveRouterPath()`, never an uncompiled `src/`
|
|
167
|
+
* tree), whose MCP handler imports `../../mcp/cli.mjs` relative to its own
|
|
168
|
+
* compiled location, which in turn imports `./server.mjs` relative to
|
|
169
|
+
* itself — i.e. always `<effective root>/dist/src/mcp/server.mjs`, in every
|
|
170
|
+
* layout (npm install, source checkout, dev-mode edge checkout). There is
|
|
171
|
+
* no runtime path that falls back to `src/mcp/server.mjs` directly, so a
|
|
172
|
+
* health check that also accepts that source path can report OK for a
|
|
173
|
+
* layout where `aiwg mcp serve` will actually fail (#276).
|
|
174
|
+
*
|
|
175
|
+
* @param {string} packageRoot - This install's own package root (`getPackageRoot()`).
|
|
176
|
+
* @param {{devMode?: boolean, edgePath?: string}} config - Channel config (`loadConfig()`).
|
|
177
|
+
* @returns {string} Absolute path to the compiled MCP server entrypoint.
|
|
178
|
+
*/
|
|
179
|
+
export function resolveMcpServerEntrypointPath(packageRoot, config) {
|
|
180
|
+
const root = resolveEffectiveInstallationRoot(packageRoot, config);
|
|
181
|
+
return path.join(root, 'dist', 'src', 'mcp', 'server.mjs');
|
|
182
|
+
}
|
|
183
|
+
|
|
138
184
|
/**
|
|
139
185
|
* Load channel configuration
|
|
140
186
|
* @returns {Promise<object>} Channel configuration
|
|
@@ -237,6 +283,9 @@ export async function getFrameworkRoot(options = {}) {
|
|
|
237
283
|
*/
|
|
238
284
|
export async function switchToEdge() {
|
|
239
285
|
const config = await loadConfig();
|
|
286
|
+
if (typeof config.edgePath !== 'string' || !path.isAbsolute(config.edgePath)) {
|
|
287
|
+
throw new Error('Edge installation path must be absolute');
|
|
288
|
+
}
|
|
240
289
|
|
|
241
290
|
console.log('Switching to edge channel (bleeding edge from main branch)...');
|
|
242
291
|
console.log('');
|
|
@@ -256,8 +305,8 @@ export async function switchToEdge() {
|
|
|
256
305
|
const sparseConfig = path.join(config.edgePath, '.git', 'info', 'sparse-checkout');
|
|
257
306
|
const hasSparse = await fs.access(sparseConfig).then(() => true).catch(() => false);
|
|
258
307
|
if (!hasSparse) {
|
|
259
|
-
|
|
260
|
-
|
|
308
|
+
boundedExecFileSync('git', ['sparse-checkout', 'init', '--cone'], 'quick', { cwd: config.edgePath, stdio: 'pipe' });
|
|
309
|
+
boundedExecFileSync('git', ['sparse-checkout', 'set', '--no-cone', '/*', '!/.aiwg'], 'quick', { cwd: config.edgePath, stdio: 'pipe' });
|
|
261
310
|
}
|
|
262
311
|
} catch {
|
|
263
312
|
// Sparse checkout is optional — older git may not support it
|
|
@@ -275,11 +324,12 @@ export async function switchToEdge() {
|
|
|
275
324
|
console.log(`Cloning repository to ${config.edgePath}...`);
|
|
276
325
|
await fs.mkdir(path.dirname(config.edgePath), { recursive: true });
|
|
277
326
|
try {
|
|
278
|
-
|
|
327
|
+
// Cloning the full repository; long tier (#3062).
|
|
328
|
+
boundedExecFileSync('git', ['clone', '--branch', 'main', '--', REPO_URL, config.edgePath], 'long', { stdio: 'inherit' });
|
|
279
329
|
// Exclude dogfooding artifacts from edge clones — users want framework source only
|
|
280
330
|
try {
|
|
281
|
-
|
|
282
|
-
|
|
331
|
+
boundedExecFileSync('git', ['sparse-checkout', 'init', '--cone'], 'quick', { cwd: config.edgePath, stdio: 'pipe' });
|
|
332
|
+
boundedExecFileSync('git', ['sparse-checkout', 'set', '--no-cone', '/*', '!/.aiwg'], 'quick', { cwd: config.edgePath, stdio: 'pipe' });
|
|
283
333
|
} catch {
|
|
284
334
|
// Sparse checkout is optional — older git versions may not support it
|
|
285
335
|
console.log('Note: sparse checkout not available, .aiwg/ will be present in edge install.');
|
|
@@ -375,7 +425,7 @@ export async function switchToNext() {
|
|
|
375
425
|
console.log('');
|
|
376
426
|
|
|
377
427
|
try {
|
|
378
|
-
|
|
428
|
+
boundedExecFileSync(status.identity.managerExecutable, ['install', '--global', 'aiwg@next'], 'long', { stdio: 'inherit' });
|
|
379
429
|
} catch (error) {
|
|
380
430
|
console.error('Failed to install aiwg@next:', error.message);
|
|
381
431
|
console.error('Check that npm is available and you have write access to the global prefix.');
|
|
@@ -409,7 +459,7 @@ export async function switchToNightly() {
|
|
|
409
459
|
console.log('');
|
|
410
460
|
|
|
411
461
|
try {
|
|
412
|
-
|
|
462
|
+
boundedExecFileSync(status.identity.managerExecutable, ['install', '--global', 'aiwg@nightly'], 'long', { stdio: 'inherit' });
|
|
413
463
|
} catch (error) {
|
|
414
464
|
console.error('Failed to install aiwg@nightly:', error.message);
|
|
415
465
|
console.error('Check that npm is available and you have write access to the global prefix.');
|
|
@@ -491,6 +541,19 @@ export async function getVersionInfo() {
|
|
|
491
541
|
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
492
542
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
493
543
|
|
|
544
|
+
const launcherRoot = process.env.AIWG_LAUNCHER_ROOT || packageRoot;
|
|
545
|
+
const runtimePath = resolveEffectiveInstallationRoot(launcherRoot, config);
|
|
546
|
+
const readVersion = async (root) => {
|
|
547
|
+
try {
|
|
548
|
+
const pkg = JSON.parse(await fs.readFile(path.join(root, 'package.json'), 'utf8'));
|
|
549
|
+
return typeof pkg.version === 'string' ? pkg.version : '(unknown)';
|
|
550
|
+
} catch {
|
|
551
|
+
return '(unknown)';
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
const launcherVersion = await readVersion(launcherRoot);
|
|
555
|
+
const runtimeVersion = await readVersion(runtimePath);
|
|
556
|
+
|
|
494
557
|
// Detect pre-release channel from version string when channel.json says 'stable'
|
|
495
558
|
// This handles the case where a user ran `npm install -g aiwg@next` directly —
|
|
496
559
|
// npm updates the binary but channel.json stays as 'stable'.
|
|
@@ -510,6 +573,9 @@ export async function getVersionInfo() {
|
|
|
510
573
|
|
|
511
574
|
const info = {
|
|
512
575
|
version,
|
|
576
|
+
launcherVersion,
|
|
577
|
+
runtimeVersion,
|
|
578
|
+
runtimePath,
|
|
513
579
|
channel,
|
|
514
580
|
packageRoot,
|
|
515
581
|
installation,
|
|
@@ -526,11 +592,11 @@ export async function getVersionInfo() {
|
|
|
526
592
|
if (config.channel === 'edge') {
|
|
527
593
|
// Get git info for edge channel
|
|
528
594
|
try {
|
|
529
|
-
const gitHash =
|
|
595
|
+
const gitHash = boundedExecFileSync('git', ['rev-parse', '--short', 'HEAD'], 'quick', {
|
|
530
596
|
cwd: config.edgePath,
|
|
531
597
|
encoding: 'utf8',
|
|
532
598
|
}).trim();
|
|
533
|
-
const gitBranch =
|
|
599
|
+
const gitBranch = boundedExecFileSync('git', ['branch', '--show-current'], 'quick', {
|
|
534
600
|
cwd: config.edgePath,
|
|
535
601
|
encoding: 'utf8',
|
|
536
602
|
}).trim();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared `spawnSync`/`boundedSpawnSync` result-to-exit-code mapping (#3062
|
|
3
|
+
* review item 7).
|
|
4
|
+
*
|
|
5
|
+
* `SpawnSyncReturns.status` is `null` on spawn failure, timeout, or signal
|
|
6
|
+
* termination — not `0`. Several call sites derived a CLI exit code with
|
|
7
|
+
* `result.status ?? 0`, which reports *success* for exactly those failure
|
|
8
|
+
* cases. This helper never does that: a `status` of `null` defaults to a
|
|
9
|
+
* non-zero exit, and when the bounded helper's `error`/`signal` fields are
|
|
10
|
+
* present, their message (already enriched with the tier/bound/override
|
|
11
|
+
* guidance for a timeout) is surfaced instead of being silently dropped.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately lives under `src/cli/` rather than `src/process/` so it
|
|
14
|
+
* composes with, but does not modify, the bounded helper itself.
|
|
15
|
+
*
|
|
16
|
+
* @module src/cli/child-process-result
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Map one spawn result to `{ exitCode, message? }`.
|
|
20
|
+
*
|
|
21
|
+
* - `result.error` set (spawn failure, or a bounded-helper timeout with its
|
|
22
|
+
* enriched message) → non-zero, `message` is `error.message` (optionally
|
|
23
|
+
* prefixed with `context`).
|
|
24
|
+
* - No `error`, but `result.signal` set (child killed by a signal, with no
|
|
25
|
+
* separate error object) → non-zero, `message` names the signal.
|
|
26
|
+
* - Otherwise → `result.status ?? 1` (a `null`/`undefined` status with
|
|
27
|
+
* neither `error` nor `signal` set is still treated as a failure, never
|
|
28
|
+
* as success).
|
|
29
|
+
*/
|
|
30
|
+
export function exitCodeForSpawnResult(result, context) {
|
|
31
|
+
const prefix = context ? `${context}: ` : '';
|
|
32
|
+
if (result.error) {
|
|
33
|
+
return { exitCode: 1, message: `${prefix}${result.error.message}` };
|
|
34
|
+
}
|
|
35
|
+
if (result.signal) {
|
|
36
|
+
return { exitCode: 1, message: `${prefix}terminated by signal ${result.signal}` };
|
|
37
|
+
}
|
|
38
|
+
return { exitCode: result.status ?? 1 };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=child-process-result.js.map
|
|
@@ -2,7 +2,7 @@ import { mkdir, readFile, rename, stat, writeFile, appendFile } from 'fs/promise
|
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { createHash } from 'crypto';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import
|
|
5
|
+
import { getUserStateDir } from '../config/user-state.js';
|
|
6
6
|
import { readAiwgConfig } from '../config/aiwg-config.js';
|
|
7
7
|
import { PROJECT_AIWG_LOCATION_FILE, projectAiwgPath, projectControlPath, } from '../config/project-artifacts.js';
|
|
8
8
|
const DEFAULT_MAX_BYTES = 1_048_576;
|
|
@@ -170,8 +170,7 @@ function resolveLogPath(scope, projectRoot, env) {
|
|
|
170
170
|
return null;
|
|
171
171
|
return projectAiwgPath(projectRoot, 'telemetry', 'cli-commands.jsonl');
|
|
172
172
|
}
|
|
173
|
-
|
|
174
|
-
return path.join(stateHome, 'aiwg', 'cli-commands.jsonl');
|
|
173
|
+
return path.join(getUserStateDir(env), 'cli-commands.jsonl');
|
|
175
174
|
}
|
|
176
175
|
async function appendBoundedJsonl(filePath, event, maxBytes) {
|
|
177
176
|
await mkdir(path.dirname(filePath), { recursive: true });
|
package/dist/src/cli/env.js
CHANGED
|
@@ -25,9 +25,24 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Handlers MUST call this helper instead of re-deriving the check locally.
|
|
27
27
|
* Divergent isTTY checks scattered across handlers have caused bugs in the
|
|
28
|
-
* past (#918 audit findings
|
|
28
|
+
* past (#918 audit findings, and #3062 review item 12: `init` only checked
|
|
29
|
+
* `CI === 'true'`, `setup project` ignored CI/TERM entirely, and `session`
|
|
30
|
+
* ignored its own `--non-interactive` flag — each reinventing a narrower
|
|
31
|
+
* version of this same check instead of using it).
|
|
32
|
+
*
|
|
33
|
+
* @param explicitNonInteractive When `true`, short-circuits to `false`
|
|
34
|
+
* without inspecting the environment at all. Pass the caller's own
|
|
35
|
+
* explicit non-interactive flag here (e.g. `--non-interactive`, or
|
|
36
|
+
* `--yes` where it means "don't prompt") so the single interactive
|
|
37
|
+
* decision takes the command's explicit flags as input, rather than
|
|
38
|
+
* every call site re-deriving its own mix of flag-vs-environment
|
|
39
|
+
* precedence. Omit it (or pass `false`) to fall through to the
|
|
40
|
+
* environment-only checks below, unchanged from before this parameter
|
|
41
|
+
* existed.
|
|
29
42
|
*/
|
|
30
|
-
export function isInteractive() {
|
|
43
|
+
export function isInteractive(explicitNonInteractive = false) {
|
|
44
|
+
if (explicitNonInteractive)
|
|
45
|
+
return false;
|
|
31
46
|
if (!process.stdin.isTTY)
|
|
32
47
|
return false;
|
|
33
48
|
if (!process.stdout.isTTY)
|
|
@@ -40,25 +55,32 @@ export function isInteractive() {
|
|
|
40
55
|
return false;
|
|
41
56
|
return true;
|
|
42
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Variables that mark a continuous-integration environment. Exported so tests
|
|
60
|
+
* that need the interactive path can clear exactly what `isCI()` reads.
|
|
61
|
+
*/
|
|
62
|
+
export const CI_ENV_VARS = [
|
|
63
|
+
'CI',
|
|
64
|
+
'CONTINUOUS_INTEGRATION',
|
|
65
|
+
'BUILD_NUMBER',
|
|
66
|
+
'RUN_ID',
|
|
67
|
+
'GITHUB_ACTIONS',
|
|
68
|
+
'GITLAB_CI',
|
|
69
|
+
'CIRCLECI',
|
|
70
|
+
'TRAVIS',
|
|
71
|
+
'BUILDKITE',
|
|
72
|
+
'JENKINS_URL',
|
|
73
|
+
'TF_BUILD', // Azure DevOps
|
|
74
|
+
'TEAMCITY_VERSION',
|
|
75
|
+
];
|
|
76
|
+
/** Other variables `isInteractive()` reads. */
|
|
77
|
+
export const INTERACTIVE_ENV_VARS = ['TERM', 'DEBIAN_FRONTEND'];
|
|
43
78
|
/**
|
|
44
79
|
* Return true iff we're running in a continuous-integration environment.
|
|
45
80
|
* Checks the common CI env vars set by major CI systems.
|
|
46
81
|
*/
|
|
47
82
|
export function isCI() {
|
|
48
|
-
const ciVars =
|
|
49
|
-
'CI',
|
|
50
|
-
'CONTINUOUS_INTEGRATION',
|
|
51
|
-
'BUILD_NUMBER',
|
|
52
|
-
'RUN_ID',
|
|
53
|
-
'GITHUB_ACTIONS',
|
|
54
|
-
'GITLAB_CI',
|
|
55
|
-
'CIRCLECI',
|
|
56
|
-
'TRAVIS',
|
|
57
|
-
'BUILDKITE',
|
|
58
|
-
'JENKINS_URL',
|
|
59
|
-
'TF_BUILD', // Azure DevOps
|
|
60
|
-
'TEAMCITY_VERSION',
|
|
61
|
-
];
|
|
83
|
+
const ciVars = CI_ENV_VARS;
|
|
62
84
|
for (const v of ciVars) {
|
|
63
85
|
const val = process.env[v];
|
|
64
86
|
if (val && val !== '0' && val.toLowerCase() !== 'false')
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared strict CLI flag/value parsing (#3062 review item 11, and the
|
|
3
|
+
* second-round review's finding 4).
|
|
4
|
+
*
|
|
5
|
+
* Several handlers (`init`, `setup`, `session`, `setup-run`) each grew
|
|
6
|
+
* their own small `flagValue(args, name)` helper, and every one of them
|
|
7
|
+
* treated a flag that is present but missing its value the same as a flag
|
|
8
|
+
* that was never given at all — `--prompt` as the very last token, or
|
|
9
|
+
* immediately followed by another flag, silently resolved to `undefined`
|
|
10
|
+
* instead of erroring. At a terminal that let the handler fall through
|
|
11
|
+
* into an interactive prompt instead of reporting the mistake; without one
|
|
12
|
+
* it could proceed on a silently-wrong default.
|
|
13
|
+
*
|
|
14
|
+
* The first-round shared parser fixed that but introduced its own gaps,
|
|
15
|
+
* found by the second review:
|
|
16
|
+
*
|
|
17
|
+
* - It validated only the *first* occurrence of a repeated single-value
|
|
18
|
+
* flag, so `--provider claude --provider` (a malformed second
|
|
19
|
+
* occurrence) silently passed.
|
|
20
|
+
* - It always resolved a repeated flag to its first occurrence, which
|
|
21
|
+
* silently changed `aiwg session`'s pre-existing last-occurrence-wins
|
|
22
|
+
* precedence for `--provider`/`--profile` to first-wins — a real
|
|
23
|
+
* behavior regression, not just a new validation gap.
|
|
24
|
+
* - `--flag=value` was never recognized at all.
|
|
25
|
+
* - Scanning never stopped at a bare `--` terminator.
|
|
26
|
+
* - An empty-string value (`--prompt ''`) was accepted as a valid value
|
|
27
|
+
* for flags where that is never meaningful.
|
|
28
|
+
*
|
|
29
|
+
* {@link scanFlagOccurrences} is the single-pass tokenizer every other
|
|
30
|
+
* helper here is built on: it finds *every* occurrence of the named
|
|
31
|
+
* flag(s), in one scan, validating each one independently, and stops
|
|
32
|
+
* recognizing flags entirely once it sees a bare `--` token (everything
|
|
33
|
+
* after that point is positional, per POSIX convention). `--flag value`
|
|
34
|
+
* and `--flag=value` are both accepted; in the space-separated form a
|
|
35
|
+
* value that itself looks like another flag (starts with `--`) is treated
|
|
36
|
+
* as a missing value — pass it via the `=` form instead
|
|
37
|
+
* (`--flag=--literal`) when a value must start with `--`. A value starting
|
|
38
|
+
* with a single `-` is always accepted in either form.
|
|
39
|
+
*
|
|
40
|
+
* Callers choose `precedence: 'first' | 'last'` to match whatever
|
|
41
|
+
* precedence the command already had before this module existed — see
|
|
42
|
+
* each call site's own comment for which one applies and why. Callers
|
|
43
|
+
* MUST catch {@link MissingFlagValueError} (or let it propagate to a
|
|
44
|
+
* handler-level catch) and report it before any preflight check, spawn,
|
|
45
|
+
* or write — never after.
|
|
46
|
+
*/
|
|
47
|
+
/** Thrown when a recognized flag is present but has no usable value following it. */
|
|
48
|
+
export class MissingFlagValueError extends Error {
|
|
49
|
+
/** The exact flag token that was missing its value (e.g. `--prompt`). */
|
|
50
|
+
flagName;
|
|
51
|
+
constructor(flagName) {
|
|
52
|
+
super(`${flagName} requires a value`);
|
|
53
|
+
this.name = 'MissingFlagValueError';
|
|
54
|
+
this.flagName = flagName;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function splitEquals(token) {
|
|
58
|
+
const eq = token.indexOf('=');
|
|
59
|
+
if (eq === -1)
|
|
60
|
+
return null;
|
|
61
|
+
return [token.slice(0, eq), token.slice(eq + 1)];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Single-pass scan for every occurrence of any of `names` in `args`. See
|
|
65
|
+
* the module doc comment for the full set of semantics this implements.
|
|
66
|
+
*
|
|
67
|
+
* Throws {@link MissingFlagValueError} on the *first* occurrence (in
|
|
68
|
+
* left-to-right order) that has no usable value or an empty one (when
|
|
69
|
+
* `options.rejectEmpty`) — every occurrence is checked, not just the
|
|
70
|
+
* first one found overall, so a malformed *later* occurrence is still an
|
|
71
|
+
* error even when an earlier one was valid.
|
|
72
|
+
*/
|
|
73
|
+
export function scanFlagOccurrences(args, names, options = {}) {
|
|
74
|
+
const occurrences = [];
|
|
75
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
76
|
+
const token = args[i];
|
|
77
|
+
if (token === undefined)
|
|
78
|
+
continue;
|
|
79
|
+
if (token === '--')
|
|
80
|
+
break; // bare terminator — stop recognizing flags entirely
|
|
81
|
+
if (token.startsWith('--')) {
|
|
82
|
+
const eqSplit = splitEquals(token);
|
|
83
|
+
if (eqSplit && names.includes(eqSplit[0])) {
|
|
84
|
+
const [flag, value] = eqSplit;
|
|
85
|
+
if (options.rejectEmpty && value === '')
|
|
86
|
+
throw new MissingFlagValueError(flag);
|
|
87
|
+
occurrences.push({ index: i, flag, value });
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (names.includes(token)) {
|
|
92
|
+
const next = args[i + 1];
|
|
93
|
+
if (next === undefined || next.startsWith('--')) {
|
|
94
|
+
throw new MissingFlagValueError(token);
|
|
95
|
+
}
|
|
96
|
+
if (options.rejectEmpty && next === '') {
|
|
97
|
+
throw new MissingFlagValueError(token);
|
|
98
|
+
}
|
|
99
|
+
occurrences.push({ index: i, flag: token, value: next });
|
|
100
|
+
i += 1; // skip the consumed value token
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return occurrences;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Look up the value of a (possibly repeated) single-value flag.
|
|
107
|
+
*
|
|
108
|
+
* - None of `names` appear at all → `undefined` (the flag was never
|
|
109
|
+
* given; not an error).
|
|
110
|
+
* - `names` appear once or more, every occurrence validated → the first
|
|
111
|
+
* or last occurrence's value, per `options.precedence` (default
|
|
112
|
+
* `'first'`). Pass `'last'` only for a command whose pre-existing
|
|
113
|
+
* behavior (before this module existed) already let a later occurrence
|
|
114
|
+
* override an earlier one — see the call site's comment.
|
|
115
|
+
*/
|
|
116
|
+
export function requireFlagValue(args, options, ...names) {
|
|
117
|
+
const occurrences = scanFlagOccurrences(args, names, options);
|
|
118
|
+
if (occurrences.length === 0)
|
|
119
|
+
return undefined;
|
|
120
|
+
return options.precedence === 'last'
|
|
121
|
+
? occurrences[occurrences.length - 1].value
|
|
122
|
+
: occurrences[0].value;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Same validation contract as {@link requireFlagValue}, but collects the
|
|
126
|
+
* value of *every* occurrence in left-to-right order — for repeatable
|
|
127
|
+
* flags such as `--param`/`--script`. Returns `[]` when the flag never
|
|
128
|
+
* appears.
|
|
129
|
+
*/
|
|
130
|
+
export function collectFlagValues(args, options, ...names) {
|
|
131
|
+
return scanFlagOccurrences(args, names, options).map((occurrence) => occurrence.value);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Parse a strict `true`/`false` flag value. `undefined` in means the flag
|
|
135
|
+
* was not given (not an error, and not a default — callers decide the
|
|
136
|
+
* default). Anything other than exactly `true`/`false` throws, naming
|
|
137
|
+
* `flagName` in the message.
|
|
138
|
+
*/
|
|
139
|
+
export function parseBooleanFlagValue(value, flagName) {
|
|
140
|
+
if (value === undefined)
|
|
141
|
+
return undefined;
|
|
142
|
+
if (value === 'true')
|
|
143
|
+
return true;
|
|
144
|
+
if (value === 'false')
|
|
145
|
+
return false;
|
|
146
|
+
throw new Error(`${flagName} must be true or false (got '${value}')`);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Parse a comma-separated list flag value, trimming whitespace and
|
|
150
|
+
* dropping empty entries. Returns `undefined` when `raw` is `undefined`
|
|
151
|
+
* (flag not given); returns `[]` only if every entry was empty.
|
|
152
|
+
*/
|
|
153
|
+
export function parseListFlagValue(raw) {
|
|
154
|
+
if (raw === undefined)
|
|
155
|
+
return undefined;
|
|
156
|
+
return raw.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Split one repeatable `<name>=<value>` entry (as used by `--script`,
|
|
160
|
+
* `--param`) into its parts. Throws, naming `flagName`, when `entry` has
|
|
161
|
+
* no `=`, an empty name, or an empty value.
|
|
162
|
+
*/
|
|
163
|
+
export function parseKeyValueEntry(entry, flagName) {
|
|
164
|
+
const eq = entry.indexOf('=');
|
|
165
|
+
if (eq <= 0 || eq === entry.length - 1) {
|
|
166
|
+
throw new Error(`${flagName} requires the form <name>=<value> (got '${entry}')`);
|
|
167
|
+
}
|
|
168
|
+
return [entry.slice(0, eq).trim(), entry.slice(eq + 1).trim()];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The index of the first bare `--` terminator in `args`, or `args.length`
|
|
172
|
+
* when there is none — a loop bounded by this never looks at anything
|
|
173
|
+
* after the terminator, which per POSIX convention is never a flag or a
|
|
174
|
+
* command word again (#3062 go/no-go review, blocker 4).
|
|
175
|
+
*/
|
|
176
|
+
export function argsTerminatorIndex(args) {
|
|
177
|
+
const index = args.indexOf('--');
|
|
178
|
+
return index === -1 ? args.length : index;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The set of array indexes in `args` consumed as the *value* of a
|
|
182
|
+
* `--flag value` (two-token) occurrence of any name in `valueFlagNames`
|
|
183
|
+
* (#3062 go/no-go review, blocker 4). A `--flag=value` (one-token) form
|
|
184
|
+
* has no separate value index to report — the value is part of the same
|
|
185
|
+
* token, so it can never coincidentally equal a bare positional word or a
|
|
186
|
+
* different flag's own name the way a space-separated value can.
|
|
187
|
+
*
|
|
188
|
+
* This does not validate occurrences (a missing/malformed value is the
|
|
189
|
+
* paired value-flag parser's own job — e.g. {@link requireFlagValue} on
|
|
190
|
+
* the same `args` and `valueFlagNames`, called separately); it exists
|
|
191
|
+
* purely so a positional/switch scan knows which indexes are already
|
|
192
|
+
* spoken for and must not be reinterpreted as something else.
|
|
193
|
+
*/
|
|
194
|
+
export function valueTokenIndexes(args, valueFlagNames) {
|
|
195
|
+
const consumed = new Set();
|
|
196
|
+
const limit = args.length;
|
|
197
|
+
for (let i = 0; i < limit; i += 1) {
|
|
198
|
+
const token = args[i];
|
|
199
|
+
if (token === undefined)
|
|
200
|
+
continue;
|
|
201
|
+
if (token === '--')
|
|
202
|
+
break;
|
|
203
|
+
if (token.startsWith('--') && token.includes('='))
|
|
204
|
+
continue; // value is part of this same token
|
|
205
|
+
if (valueFlagNames.includes(token) && i + 1 < limit) {
|
|
206
|
+
consumed.add(i + 1);
|
|
207
|
+
i += 1; // the value token itself is spoken for; do not also treat it as a flag name
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return consumed;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* True iff `name` appears as a bare positional token or an exact-match
|
|
214
|
+
* boolean switch anywhere in `args` *before* the `--` terminator, and is
|
|
215
|
+
* not itself the already-consumed value of one of `valueFlagNames` (#3062
|
|
216
|
+
* go/no-go review, blocker 4).
|
|
217
|
+
*
|
|
218
|
+
* Use this instead of `args.includes(name)` (or an equivalent hand-rolled
|
|
219
|
+
* loop) for any boolean switch or positional command word that a value-
|
|
220
|
+
* taking flag's own value could coincidentally equal — e.g. a free-text
|
|
221
|
+
* `--prompt` argument that happens to contain the literal word a command
|
|
222
|
+
* also uses as a switch, or a value that collides with another flag's own
|
|
223
|
+
* name.
|
|
224
|
+
*/
|
|
225
|
+
export function hasPositionalOrSwitch(args, name, valueFlagNames) {
|
|
226
|
+
const consumed = valueTokenIndexes(args, valueFlagNames);
|
|
227
|
+
const limit = argsTerminatorIndex(args);
|
|
228
|
+
for (let i = 0; i < limit; i += 1) {
|
|
229
|
+
if (consumed.has(i))
|
|
230
|
+
continue;
|
|
231
|
+
if (args[i] === name)
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=flag-parsing.js.map
|
|
@@ -32,6 +32,9 @@ export const artifactsHandler = {
|
|
|
32
32
|
description: 'Move or inspect the configured project AIWG artifact root',
|
|
33
33
|
category: 'index',
|
|
34
34
|
aliases: ['artifact'],
|
|
35
|
+
async help() {
|
|
36
|
+
return { exitCode: 0, message: usage(), rawOutput: true };
|
|
37
|
+
},
|
|
35
38
|
async execute(ctx) {
|
|
36
39
|
const action = ctx.args.find(arg => !arg.startsWith('-')) ?? 'help';
|
|
37
40
|
if (action === 'help' || ctx.args.includes('--help') || ctx.args.includes('-h')) {
|
|
@@ -37,6 +37,9 @@ export function createAuthHandler(dependencies = {}) {
|
|
|
37
37
|
description: "Log in, inspect access, and log out of paid AIWG web resources",
|
|
38
38
|
category: "maintenance",
|
|
39
39
|
aliases: [],
|
|
40
|
+
async help() {
|
|
41
|
+
return { exitCode: 0, message: usage(), rawOutput: true };
|
|
42
|
+
},
|
|
40
43
|
async execute(ctx) {
|
|
41
44
|
if (!ctx.args.length || ["help", "--help", "-h"].includes(ctx.args[0])) {
|
|
42
45
|
console.log(usage());
|