@aiwg/cli 2026.10.3 → 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/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 +57 -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 +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/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 +98 -37
- 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 +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 +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 +51 -11
- package/dist/src/sessions/contracts.js +40 -2
- package/dist/src/sessions/coverage-preflight.js +1 -1
- 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 +133 -25
- package/dist/src/sessions/readers.js +106 -53
- package/dist/src/sessions/refresh.js +106 -0
- package/dist/src/sessions/repository.js +147 -52
- package/dist/src/sessions/workspace-discovery.js +221 -56
- 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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { trackTemporaryDirectory } from '../../utils/temporary-directory.js';
|
|
1
2
|
/**
|
|
2
3
|
* Use Command Handler
|
|
3
4
|
*
|
|
@@ -13,9 +14,12 @@ import fs from 'fs/promises';
|
|
|
13
14
|
import path from 'path';
|
|
14
15
|
import os from 'os';
|
|
15
16
|
import { pathToFileURL } from 'node:url';
|
|
17
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
18
|
+
import { canDeploySkill, sameSkillOwner, extractFrameworkSlug } from '../../providers/skill-ownership.mjs';
|
|
16
19
|
import { resolveOmpPaths } from '../../providers/omp-paths.mjs';
|
|
17
20
|
import YAML from 'yaml';
|
|
18
21
|
import { createScriptRunner } from './script-runner.js';
|
|
22
|
+
import { finalizePreparedProvider, prepareProviderDeployments } from '../services/provider-prepare-coordinator.js';
|
|
19
23
|
import { getFrameworkRoot, getVersionInfo } from '../../channel/manager.mjs';
|
|
20
24
|
import { getRegistry } from '../../extensions/registry.js';
|
|
21
25
|
import { registerDeployedExtensions } from '../../extensions/deployment-registration.js';
|
|
@@ -39,6 +43,7 @@ import { detectScope, mirrorToUserScope, rejectOpenClawProjectScope, USER_SCOPE_
|
|
|
39
43
|
import { maybeWarnProjectIsolation } from '../project-isolation/index.js';
|
|
40
44
|
import { formatWorkspaceSignalPlan, includedBundleIds, resolveWorkspaceSignalPlan, writeWorkspaceSignalPlan, } from '../workspace-signals.js';
|
|
41
45
|
import { getProviderArtifactPathStrings, getProviderDefinition, getProviderKernelSkillPath, normalizeProviderDefinitionId, } from '../../providers/provider-definitions.js';
|
|
46
|
+
import { deployedSkillRoots } from '../../providers/deployed-skill-roots.js';
|
|
42
47
|
// Module-level guard so the iteration loops further down (which re-enter
|
|
43
48
|
// execute() per framework/provider) don't re-emit the warning each pass.
|
|
44
49
|
// Reset is not needed: a single CLI process is one user invocation.
|
|
@@ -47,12 +52,14 @@ let projectIsolationChecked = false;
|
|
|
47
52
|
// collecting child-process output. The CLI is single-command-per-process;
|
|
48
53
|
// recursive provider expansion shares this guard intentionally.
|
|
49
54
|
let machineReadableUseDepth = 0;
|
|
55
|
+
// Providers whose complete project projection is covered by the transferable
|
|
56
|
+
// rule-delivery transaction. Other built-ins retain their serial deploy path.
|
|
57
|
+
const PREPARABLE_BUILTIN_PROVIDERS = new Set(['claude', 'codex', 'cursor', 'hermes', 'pi', 'warp']);
|
|
50
58
|
// Context-pipeline: emits WORKSPACE.md + AIWG.md + provider adapters last.
|
|
51
59
|
// for non-Claude providers per ADR-1 (.aiwg/architecture/adr-agents-md-aggregation.md).
|
|
52
60
|
// Distinct from agentsmith (which creates subagent personas).
|
|
53
61
|
import { generate as generateContextFiles, discoverDeployedArtifacts, } from '../../smiths/context-pipeline/index.js';
|
|
54
62
|
import { verifyModelWrapperDeployment } from '../../models/wrapper-deployment.js';
|
|
55
|
-
import { loadGraphIndexFile } from '../../artifacts/index-reader.js';
|
|
56
63
|
import { aggregateUseDeploymentResult, buildDryRunUseResult, renderUseDeploymentResult, verifyProviderDeployment, } from '../services/deployment-verification.js';
|
|
57
64
|
import { finalizeProviderTransformationReceipt, providerReceiptHasLocalSources, sourceVerificationsFromSignedWebRelease, } from '../../providers/transformation-receipt-integration.js';
|
|
58
65
|
import { loadResourceTrustRootFile, resolveWebRelease, } from '../../resources/web-release.js';
|
|
@@ -246,7 +253,7 @@ const FRAMEWORK_DIR_MAP = {
|
|
|
246
253
|
all: 'sdlc-complete',
|
|
247
254
|
};
|
|
248
255
|
/** Resolve actual framework directory name for a given user-facing name. */
|
|
249
|
-
function resolveFrameworkDir(framework) {
|
|
256
|
+
export function resolveFrameworkDir(framework) {
|
|
250
257
|
return FRAMEWORK_DIR_MAP[framework];
|
|
251
258
|
}
|
|
252
259
|
/**
|
|
@@ -397,6 +404,18 @@ export function addonPath(frameworkRoot, name) {
|
|
|
397
404
|
const folderName = resolveAddonFolderName(name);
|
|
398
405
|
return path.join(frameworkRoot, 'agentic/code/addons', folderName);
|
|
399
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* Whether the provider's root deployment already collects every eligible
|
|
409
|
+
* addon for this mode. The caller still registers addon CLI contributions;
|
|
410
|
+
* this only suppresses redundant deploy-agents subprocesses.
|
|
411
|
+
*/
|
|
412
|
+
export function mainDeploymentIncludesAddons(provider, selectedMode, providerDeployArgs) {
|
|
413
|
+
return (((provider === 'claude' || provider === 'pi')
|
|
414
|
+
&& ['general', 'sdlc', 'both', 'all'].includes(selectedMode))
|
|
415
|
+
|| (provider === 'codex' && selectedMode === 'all'))
|
|
416
|
+
&& !providerDeployArgs.some(arg => arg === '--source' || arg.startsWith('--source='))
|
|
417
|
+
&& providerDeployArgs.filter(arg => arg === '--mode').length === 1;
|
|
418
|
+
}
|
|
400
419
|
/**
|
|
401
420
|
* Resolve a selected addon's required addon dependencies in deterministic
|
|
402
421
|
* dependency-first order. Optional dependencies remain descriptive and are
|
|
@@ -1047,17 +1066,11 @@ async function listBundleSkillNameCandidates(bundlePath) {
|
|
|
1047
1066
|
return [];
|
|
1048
1067
|
}
|
|
1049
1068
|
}
|
|
1050
|
-
async function countDeployedBundleSkills(bundlePath, target, provider
|
|
1069
|
+
async function countDeployedBundleSkills(bundlePath, target, provider) {
|
|
1051
1070
|
const skillCandidates = await listBundleSkillNameCandidates(bundlePath);
|
|
1052
1071
|
if (skillCandidates.length === 0)
|
|
1053
1072
|
return 0;
|
|
1054
|
-
const
|
|
1055
|
-
paths.skills,
|
|
1056
|
-
getProviderKernelSkillsPath(provider),
|
|
1057
|
-
]
|
|
1058
|
-
.filter(Boolean)
|
|
1059
|
-
.map(dir => resolveDeployPath(target, dir));
|
|
1060
|
-
const uniqueCandidateDirs = [...new Set(candidateDirs)];
|
|
1073
|
+
const uniqueCandidateDirs = deployedSkillRoots(target, provider);
|
|
1061
1074
|
let count = 0;
|
|
1062
1075
|
for (const names of skillCandidates) {
|
|
1063
1076
|
let found = false;
|
|
@@ -1080,16 +1093,35 @@ async function countBundleDeployedArtifacts(bundlePath, target, provider) {
|
|
|
1080
1093
|
return {
|
|
1081
1094
|
agents: await countDeployedBundleFiles(bundlePath, 'agents', target, paths.agents, ['.md', '.toml']),
|
|
1082
1095
|
commands: await countDeployedBundleFiles(bundlePath, 'commands', target, paths.commands, ['.md']),
|
|
1083
|
-
skills: await countDeployedBundleSkills(bundlePath, target, provider
|
|
1096
|
+
skills: await countDeployedBundleSkills(bundlePath, target, provider),
|
|
1084
1097
|
rules: await countDeployedBundleFiles(bundlePath, 'rules', target, paths.rules, ['.md', '.mdc']),
|
|
1085
1098
|
};
|
|
1086
1099
|
}
|
|
1087
1100
|
const SKILL_SUPPORT_REFERENCE = /(?:^|[\s`('"\[])((?:templates|references|scripts|assets)\/[A-Za-z0-9._@/+\-]+)(?=$|[\s`)'"\],:;])/gm;
|
|
1088
1101
|
/** Copy one support file, preserving its executable bit. */
|
|
1089
|
-
async function copySkillSupportFile(source, destination) {
|
|
1102
|
+
async function copySkillSupportFile(source, destination, skillDir) {
|
|
1090
1103
|
await fs.mkdir(path.dirname(destination), { recursive: true });
|
|
1091
1104
|
await fs.copyFile(source, destination);
|
|
1092
1105
|
await fs.chmod(destination, (await fs.stat(source)).mode & 0o777);
|
|
1106
|
+
// Extend the shared copier's receipt for bundle-root assets too. Adapters
|
|
1107
|
+
// without that receipt keep their own ownership and cleanup contract.
|
|
1108
|
+
if (!skillDir)
|
|
1109
|
+
return;
|
|
1110
|
+
const manifestPath = path.join(skillDir, '.aiwg-manifest.json');
|
|
1111
|
+
let manifest;
|
|
1112
|
+
try {
|
|
1113
|
+
manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
1114
|
+
}
|
|
1115
|
+
catch {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
if (!manifest.skillSource || !manifest.managed?.['SKILL.md'])
|
|
1119
|
+
return;
|
|
1120
|
+
manifest.managed[path.relative(skillDir, destination)] = {
|
|
1121
|
+
...manifest.managed['SKILL.md'],
|
|
1122
|
+
hash: `sha256:${createHash('sha256').update(await fs.readFile(destination)).digest('hex')}`,
|
|
1123
|
+
};
|
|
1124
|
+
await fs.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
1093
1125
|
}
|
|
1094
1126
|
/**
|
|
1095
1127
|
* Materialize a directory-valued support-asset reference (#2503).
|
|
@@ -1099,7 +1131,7 @@ async function copySkillSupportFile(source, destination) {
|
|
|
1099
1131
|
* file modes are preserved so script packs stay executable. Empty directories
|
|
1100
1132
|
* are still created — a reference to an empty pack is odd but not an error.
|
|
1101
1133
|
*/
|
|
1102
|
-
async function copySkillSupportTree(source, destination, sourceSkillMd, reference, deployFile) {
|
|
1134
|
+
async function copySkillSupportTree(source, destination, sourceSkillMd, reference, deployFile, skillDir) {
|
|
1103
1135
|
await fs.mkdir(destination, { recursive: true });
|
|
1104
1136
|
const label = reference.replace(/\/+$/, '');
|
|
1105
1137
|
const entries = await fs.readdir(source, { withFileTypes: true });
|
|
@@ -1110,7 +1142,7 @@ async function copySkillSupportTree(source, destination, sourceSkillMd, referenc
|
|
|
1110
1142
|
throw new Error(`unsafe skill support asset '${label}/${entry.name}' referenced by ${sourceSkillMd}: symbolic links are not deployed`);
|
|
1111
1143
|
}
|
|
1112
1144
|
if (entry.isDirectory()) {
|
|
1113
|
-
await copySkillSupportTree(from, to, sourceSkillMd, `${label}/${entry.name}`, deployFile);
|
|
1145
|
+
await copySkillSupportTree(from, to, sourceSkillMd, `${label}/${entry.name}`, deployFile, skillDir);
|
|
1114
1146
|
continue;
|
|
1115
1147
|
}
|
|
1116
1148
|
if (!entry.isFile())
|
|
@@ -1119,7 +1151,7 @@ async function copySkillSupportTree(source, destination, sourceSkillMd, referenc
|
|
|
1119
1151
|
deployFile(from, to);
|
|
1120
1152
|
continue;
|
|
1121
1153
|
}
|
|
1122
|
-
await copySkillSupportFile(from, to);
|
|
1154
|
+
await copySkillSupportFile(from, to, skillDir);
|
|
1123
1155
|
}
|
|
1124
1156
|
}
|
|
1125
1157
|
/**
|
|
@@ -1140,12 +1172,9 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1140
1172
|
catch {
|
|
1141
1173
|
return;
|
|
1142
1174
|
}
|
|
1143
|
-
const paths = getProviderPaths(provider);
|
|
1144
|
-
const kernelSkillsPath = getProviderKernelSkillsPath(provider);
|
|
1145
1175
|
const deployRoots = provider === 'omp' && options.scope === 'user'
|
|
1146
1176
|
? [path.join(resolveOmpPaths({ cwd: target }).agentDir, 'skills')]
|
|
1147
|
-
:
|
|
1148
|
-
.filter((value) => Boolean(value)).map(value => resolveDeployPath(target, value)))];
|
|
1177
|
+
: deployedSkillRoots(target, provider);
|
|
1149
1178
|
for (const skillName of skillDirs) {
|
|
1150
1179
|
const sourceSkillDir = path.join(skillsRoot, skillName);
|
|
1151
1180
|
const sourceSkillMd = path.join(sourceSkillDir, 'SKILL.md');
|
|
@@ -1156,7 +1185,35 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1156
1185
|
catch {
|
|
1157
1186
|
continue;
|
|
1158
1187
|
}
|
|
1159
|
-
|
|
1188
|
+
// Check each deployed tier independently: a foreign mirror must not block
|
|
1189
|
+
// support assets for a tier already owned by this source.
|
|
1190
|
+
const ownedRoots = [];
|
|
1191
|
+
for (const root of deployRoots) {
|
|
1192
|
+
const skillDir = path.join(root, skillName);
|
|
1193
|
+
try {
|
|
1194
|
+
const manifestPath = path.join(skillDir, '.aiwg-manifest.json');
|
|
1195
|
+
const receipt = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
1196
|
+
if (!canDeploySkill(receipt, sourceSkillDir, options))
|
|
1197
|
+
continue;
|
|
1198
|
+
if (!sameSkillOwner(receipt, sourceSkillDir)) {
|
|
1199
|
+
receipt.skillSource = path.resolve(sourceSkillDir);
|
|
1200
|
+
const slug = extractFrameworkSlug(sourceSkillMd);
|
|
1201
|
+
for (const record of Object.values(receipt.managed ?? {})) {
|
|
1202
|
+
if (slug)
|
|
1203
|
+
record.frameworkSlug = slug;
|
|
1204
|
+
else
|
|
1205
|
+
delete record.frameworkSlug;
|
|
1206
|
+
}
|
|
1207
|
+
await fs.writeFile(manifestPath, `${JSON.stringify(receipt, null, 2)}\n`);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
catch { /* adapters without shared ownership receipts keep their own contract */ }
|
|
1211
|
+
if (await fileExists(path.join(skillDir, 'SKILL.md')))
|
|
1212
|
+
ownedRoots.push(root);
|
|
1213
|
+
}
|
|
1214
|
+
if (ownedRoots.length === 0)
|
|
1215
|
+
continue;
|
|
1216
|
+
if (options.skipUndeployed && !(await Promise.all(ownedRoots.map(root => fileExists(path.join(root, skillName, 'SKILL.md'))))).some(Boolean))
|
|
1160
1217
|
continue;
|
|
1161
1218
|
const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? '';
|
|
1162
1219
|
const declaredEntrypoint = frontmatter
|
|
@@ -1199,7 +1256,7 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1199
1256
|
throw new Error(`skill entrypoint '${relative}' in ${sourceSkillMd} resolves to a directory; an entrypoint must be a file`);
|
|
1200
1257
|
}
|
|
1201
1258
|
let deployedSkillRoot;
|
|
1202
|
-
for (const root of
|
|
1259
|
+
for (const root of ownedRoots) {
|
|
1203
1260
|
// The deployer may select the bulk or kernel tier; use the tier that
|
|
1204
1261
|
// actually contains this skill's transformed SKILL.md.
|
|
1205
1262
|
if (await fileExists(path.join(root, skillName, 'SKILL.md'))) {
|
|
@@ -1217,14 +1274,14 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1217
1274
|
})()
|
|
1218
1275
|
: null;
|
|
1219
1276
|
if (sourceIsDirectory) {
|
|
1220
|
-
await copySkillSupportTree(source, destination, sourceSkillMd, relative, deployFile);
|
|
1277
|
+
await copySkillSupportTree(source, destination, sourceSkillMd, relative, deployFile, path.join(deployedSkillRoot, skillName));
|
|
1221
1278
|
continue;
|
|
1222
1279
|
}
|
|
1223
1280
|
if (deployFile) {
|
|
1224
1281
|
deployFile(source, destination);
|
|
1225
1282
|
continue;
|
|
1226
1283
|
}
|
|
1227
|
-
await copySkillSupportFile(source, destination);
|
|
1284
|
+
await copySkillSupportFile(source, destination, path.join(deployedSkillRoot, skillName));
|
|
1228
1285
|
}
|
|
1229
1286
|
}
|
|
1230
1287
|
}
|
|
@@ -1297,6 +1354,8 @@ async function deployOneProjectLocalBundle(opts) {
|
|
|
1297
1354
|
...modelArgs,
|
|
1298
1355
|
];
|
|
1299
1356
|
args.push(...collectUseScopeDeployArgs(ctx.args));
|
|
1357
|
+
if (ctx.args.includes('--force'))
|
|
1358
|
+
args.push('--force');
|
|
1300
1359
|
if (dryRun)
|
|
1301
1360
|
args.push('--dry-run');
|
|
1302
1361
|
if (verbose)
|
|
@@ -1322,7 +1381,7 @@ async function deployOneProjectLocalBundle(opts) {
|
|
|
1322
1381
|
exitCode = result.exitCode;
|
|
1323
1382
|
if (exitCode === 0 && !dryRun) {
|
|
1324
1383
|
try {
|
|
1325
|
-
await reconcileDeployedSkillAssets(bundle.artifactPath, target, provider);
|
|
1384
|
+
await reconcileDeployedSkillAssets(bundle.artifactPath, target, provider, { force: ctx.args.includes('--force') });
|
|
1326
1385
|
}
|
|
1327
1386
|
catch (error) {
|
|
1328
1387
|
ui.warn(`Project-local skill asset deployment failed for '${bundle.id}': ${error.message}`);
|
|
@@ -1973,18 +2032,30 @@ async function generateGlobalProjectContext(opts) {
|
|
|
1973
2032
|
},
|
|
1974
2033
|
});
|
|
1975
2034
|
}
|
|
2035
|
+
/** Receipt reuse applies to complete packages; selected partial sources still need an actual build. */
|
|
2036
|
+
async function reconcileSelectedFrameworkSource(root) {
|
|
2037
|
+
const { refreshFrameworkCapabilities, resolveFrameworkCorpusRoot } = await import('../../artifacts/framework-capabilities.js');
|
|
2038
|
+
if (resolveFrameworkCorpusRoot(root)) {
|
|
2039
|
+
const { loadPrebuiltDeploymentIndex } = await import('../../artifacts/prebuilt-deployment.js');
|
|
2040
|
+
if (loadPrebuiltDeploymentIndex(root, { strictRoot: true }))
|
|
2041
|
+
return;
|
|
2042
|
+
await refreshFrameworkCapabilities(root, true, { force: true });
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
const { buildIndex } = await import('../../artifacts/index-builder.js');
|
|
2046
|
+
await buildIndex(root, { graph: 'framework', explicit: false });
|
|
2047
|
+
const { syncFortemiCoreIndex } = await import('../../artifacts/fortemi-core-sync.js');
|
|
2048
|
+
syncFortemiCoreIndex(root, { graph: 'framework' });
|
|
2049
|
+
}
|
|
1976
2050
|
async function ensurePostDeployPhases(opts) {
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
catch {
|
|
1986
|
-
// The shared verifier reports the index failure with stable remediation.
|
|
1987
|
-
}
|
|
2051
|
+
// Validate source files once after deployment, including uncommitted edits
|
|
2052
|
+
// that the cheap HEAD/manifest receipt intentionally cannot detect. Earlier
|
|
2053
|
+
// deployment/query phases can reuse that receipt instead of rescanning.
|
|
2054
|
+
try {
|
|
2055
|
+
await reconcileSelectedFrameworkSource(opts.frameworkRoot);
|
|
2056
|
+
}
|
|
2057
|
+
catch {
|
|
2058
|
+
// The shared verifier reports the index failure with stable remediation.
|
|
1988
2059
|
}
|
|
1989
2060
|
// The Fortemi export is the default discovery backend. Rebuilding only the
|
|
1990
2061
|
// source graph makes any existing export stale, so every successful use
|
|
@@ -1992,8 +2063,9 @@ async function ensurePostDeployPhases(opts) {
|
|
|
1992
2063
|
// materializes a fresh-install cache without requiring a manual index sync.
|
|
1993
2064
|
try {
|
|
1994
2065
|
const { getFortemiCoreSyncStatus, syncFortemiCoreIndex, } = await import('../../artifacts/fortemi-core-sync.js');
|
|
2066
|
+
const { loadPrebuiltDeploymentIndex } = await import('../../artifacts/prebuilt-deployment.js');
|
|
1995
2067
|
const status = getFortemiCoreSyncStatus(opts.frameworkRoot, 'framework');
|
|
1996
|
-
if (!status.built || status.stale) {
|
|
2068
|
+
if (!loadPrebuiltDeploymentIndex(opts.frameworkRoot, { strictRoot: true }) && (!status.built || status.stale)) {
|
|
1997
2069
|
syncFortemiCoreIndex(opts.frameworkRoot, { graph: 'framework' });
|
|
1998
2070
|
}
|
|
1999
2071
|
}
|
|
@@ -2189,6 +2261,55 @@ async function deployOmpUserSource(opts) {
|
|
|
2189
2261
|
counts: { agents: entries.agents.length, commands: entries.commands.length,
|
|
2190
2262
|
skills: entries.skills.length, rules: entries.rules.length }, entries });
|
|
2191
2263
|
}
|
|
2264
|
+
/** Record native home writes without mirroring or changing user-scope removal roots. */
|
|
2265
|
+
async function recordNativeAddonDeploy(bundlePath, target, provider, bundle) {
|
|
2266
|
+
const userPaths = USER_SCOPE_PATHS[provider];
|
|
2267
|
+
const paths = getProviderPaths(provider);
|
|
2268
|
+
const entries = {
|
|
2269
|
+
agents: [], commands: [], skills: [], rules: [],
|
|
2270
|
+
};
|
|
2271
|
+
for (const names of await listBundleSkillNameCandidates(bundlePath)) {
|
|
2272
|
+
for (const root of deployedSkillRoots(target, provider)) {
|
|
2273
|
+
let name;
|
|
2274
|
+
for (const candidate of names) {
|
|
2275
|
+
if (await fileExists(path.join(root, candidate, 'SKILL.md'))) {
|
|
2276
|
+
name = candidate;
|
|
2277
|
+
break;
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
if (!name)
|
|
2281
|
+
continue;
|
|
2282
|
+
try {
|
|
2283
|
+
const receipt = JSON.parse(await fs.readFile(path.join(root, name, '.aiwg-manifest.json'), 'utf8'));
|
|
2284
|
+
const sourceDir = path.join(bundlePath, 'skills', names[names.length - 1]);
|
|
2285
|
+
if (!sameSkillOwner(receipt, sourceDir))
|
|
2286
|
+
continue;
|
|
2287
|
+
}
|
|
2288
|
+
catch { /* legacy adapters may not write a shared ownership receipt */ }
|
|
2289
|
+
entries.skills.push(path.relative(userPaths.skills, path.join(root, name)));
|
|
2290
|
+
break;
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
for (const kind of ['agents', 'commands', 'rules']) {
|
|
2294
|
+
if (!paths[kind] || !userPaths[kind])
|
|
2295
|
+
continue;
|
|
2296
|
+
for (const stem of await listBundleMdStems(bundlePath, kind)) {
|
|
2297
|
+
const filename = `${stem}.md`;
|
|
2298
|
+
const destination = path.join(resolveDeployPath(target, paths[kind]), filename);
|
|
2299
|
+
if (await fileExists(destination))
|
|
2300
|
+
entries[kind].push(path.relative(userPaths[kind], destination));
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
const manifestPath = path.join(bundlePath, 'manifest.json');
|
|
2304
|
+
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
2305
|
+
const { recordUserDeploy } = await import('../../config/user-registry.js');
|
|
2306
|
+
await recordUserDeploy({
|
|
2307
|
+
framework: bundle, provider, version: manifest.version ?? (await getVersionInfo()).version,
|
|
2308
|
+
source: 'bundled', manifestHash: await hashManifest(manifestPath), entries,
|
|
2309
|
+
counts: { agents: entries.agents.length, commands: entries.commands.length,
|
|
2310
|
+
skills: entries.skills.length, rules: entries.rules.length },
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2192
2313
|
async function mirrorProjectLocalBundleToUserScope(opts) {
|
|
2193
2314
|
const paths = getProviderPaths(opts.provider);
|
|
2194
2315
|
const resolveProjectPath = (value) => !value ? '' : path.isAbsolute(value) ? value : path.join(opts.target, value);
|
|
@@ -2269,6 +2390,7 @@ export class UseHandler {
|
|
|
2269
2390
|
category = 'framework';
|
|
2270
2391
|
aliases = [];
|
|
2271
2392
|
orchestrationDepth = 0;
|
|
2393
|
+
preparedProviderContinuations = new Set();
|
|
2272
2394
|
async help() {
|
|
2273
2395
|
return { exitCode: 0, message: USE_HELP, rawOutput: true };
|
|
2274
2396
|
}
|
|
@@ -2281,12 +2403,24 @@ export class UseHandler {
|
|
|
2281
2403
|
|| ctx.args.includes('--workspace-signals');
|
|
2282
2404
|
if (bypassOrchestration)
|
|
2283
2405
|
return this.executeCore(ctx);
|
|
2406
|
+
// Child deployers share one source-index snapshot for this invocation. Each
|
|
2407
|
+
// addon still resolves and validates its bindings through the common query
|
|
2408
|
+
// engine, without rebuilding the entire corpus on every additive pass.
|
|
2409
|
+
const previousBindingCache = process.env.AIWG_RULE_BINDING_INDEX_CACHE;
|
|
2410
|
+
const bindingCache = previousBindingCache || await fs.mkdtemp(path.join(os.tmpdir(), 'aiwg-use-bindings-'));
|
|
2411
|
+
const removeBindingCache = previousBindingCache ? () => { } : trackTemporaryDirectory(bindingCache);
|
|
2412
|
+
process.env.AIWG_RULE_BINDING_INDEX_CACHE = bindingCache;
|
|
2284
2413
|
this.orchestrationDepth += 1;
|
|
2285
2414
|
try {
|
|
2286
2415
|
return await this.executeOrchestrated(ctx, requestedBundle);
|
|
2287
2416
|
}
|
|
2288
2417
|
finally {
|
|
2289
2418
|
this.orchestrationDepth -= 1;
|
|
2419
|
+
if (previousBindingCache === undefined)
|
|
2420
|
+
delete process.env.AIWG_RULE_BINDING_INDEX_CACHE;
|
|
2421
|
+
else
|
|
2422
|
+
process.env.AIWG_RULE_BINDING_INDEX_CACHE = previousBindingCache;
|
|
2423
|
+
removeBindingCache();
|
|
2290
2424
|
}
|
|
2291
2425
|
}
|
|
2292
2426
|
async executeOrchestrated(ctx, requestedBundle) {
|
|
@@ -2362,7 +2496,6 @@ export class UseHandler {
|
|
|
2362
2496
|
projectPath: projectDir,
|
|
2363
2497
|
provider,
|
|
2364
2498
|
args: remainingArgs,
|
|
2365
|
-
invocationStartedAt: startedAt,
|
|
2366
2499
|
});
|
|
2367
2500
|
}
|
|
2368
2501
|
}
|
|
@@ -2982,6 +3115,8 @@ export class UseHandler {
|
|
|
2982
3115
|
}
|
|
2983
3116
|
const runner = createScriptRunner(frameworkRoot);
|
|
2984
3117
|
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
3118
|
+
if (remainingArgs.includes('--allow-over-budget'))
|
|
3119
|
+
addonBaseArgs.push('--allow-over-budget');
|
|
2985
3120
|
if (addonScope === 'user')
|
|
2986
3121
|
addonBaseArgs.push('--scope', 'user');
|
|
2987
3122
|
// An explicitly selected upstream addon must be self-contained in the
|
|
@@ -3001,6 +3136,8 @@ export class UseHandler {
|
|
|
3001
3136
|
}
|
|
3002
3137
|
if (dryRunAddon)
|
|
3003
3138
|
addonBaseArgs.push('--dry-run');
|
|
3139
|
+
if (remainingArgs.includes('--force'))
|
|
3140
|
+
addonBaseArgs.push('--force');
|
|
3004
3141
|
const kind = isExtension ? 'extension' : 'addon';
|
|
3005
3142
|
const activationOrder = isAddon
|
|
3006
3143
|
? await resolveRequiredAddonActivationOrder(frameworkRoot, framework)
|
|
@@ -3023,7 +3160,7 @@ export class UseHandler {
|
|
|
3023
3160
|
}
|
|
3024
3161
|
if (!dryRunAddon) {
|
|
3025
3162
|
try {
|
|
3026
|
-
await reconcileDeployedSkillAssets(dependencySource, target, provider, { strictReferences: false });
|
|
3163
|
+
await reconcileDeployedSkillAssets(dependencySource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3027
3164
|
}
|
|
3028
3165
|
catch (error) {
|
|
3029
3166
|
return {
|
|
@@ -3065,7 +3202,7 @@ export class UseHandler {
|
|
|
3065
3202
|
}
|
|
3066
3203
|
if (!dryRunAddon) {
|
|
3067
3204
|
try {
|
|
3068
|
-
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false });
|
|
3205
|
+
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3069
3206
|
}
|
|
3070
3207
|
catch (error) {
|
|
3071
3208
|
return {
|
|
@@ -3118,6 +3255,14 @@ export class UseHandler {
|
|
|
3118
3255
|
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3119
3256
|
};
|
|
3120
3257
|
}
|
|
3258
|
+
if (!dryRunAddon && (provider === 'openclaw' || (provider === 'grokbot' && addonScope === 'user'))) {
|
|
3259
|
+
try {
|
|
3260
|
+
await recordNativeAddonDeploy(addonSource, target, provider, framework);
|
|
3261
|
+
}
|
|
3262
|
+
catch (error) {
|
|
3263
|
+
return { exitCode: 1, message: `Addon user registry update failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3121
3266
|
// Persist the same lifecycle record frameworks and project-local bundles
|
|
3122
3267
|
// receive so status, refresh, doctor, and remove can account for this
|
|
3123
3268
|
// upstream addon and every provider artifact it actually deployed.
|
|
@@ -3240,6 +3385,16 @@ export class UseHandler {
|
|
|
3240
3385
|
const force = remainingArgs.includes('--force');
|
|
3241
3386
|
const skipConflicts = remainingArgs.includes('--skip-conflicts');
|
|
3242
3387
|
const explicitHarnessAgentSelectors = parseOpenHumanHarnessAgentSelector(remainingArgs);
|
|
3388
|
+
const preparedFlag = '--aiwg-provider-main-prepared';
|
|
3389
|
+
const preparedFlagIndex = remainingArgs.indexOf(preparedFlag);
|
|
3390
|
+
const preparedCapability = preparedFlagIndex >= 0 ? remainingArgs[preparedFlagIndex + 1] : undefined;
|
|
3391
|
+
let mainProviderPrepared = false;
|
|
3392
|
+
if (preparedFlagIndex >= 0) {
|
|
3393
|
+
if (!preparedCapability || !this.preparedProviderContinuations.delete(preparedCapability)) {
|
|
3394
|
+
return { exitCode: 1, message: 'Invalid prepared-provider continuation capability.' };
|
|
3395
|
+
}
|
|
3396
|
+
mainProviderPrepared = true;
|
|
3397
|
+
}
|
|
3243
3398
|
// PUW-027 (#1128): --scope user|project per ADR-4. Default project.
|
|
3244
3399
|
// #1156 Phase 1: --user is a shorthand for --scope user.
|
|
3245
3400
|
let scope;
|
|
@@ -3264,7 +3419,7 @@ export class UseHandler {
|
|
|
3264
3419
|
}
|
|
3265
3420
|
if (scope === 'user' && !deployArgs.includes('--scope'))
|
|
3266
3421
|
deployArgs.push('--scope', 'user');
|
|
3267
|
-
const filteredArgs = deployArgs.filter(a => a !== '--no-utils' && a !== '--no-project-local' && a !== '--ci-hooks-enabled' && a !== '--
|
|
3422
|
+
const filteredArgs = removeFlagWithOptionalValue(deployArgs, preparedFlag).filter(a => a !== '--no-utils' && a !== '--no-project-local' && a !== '--ci-hooks-enabled' && a !== '--skip-conflicts' && a !== '--no-harness-agents');
|
|
3268
3423
|
const deployFilteredArgs = removeFlagWithOptionalValue(filteredArgs, '--harness-agents');
|
|
3269
3424
|
// Pass --quiet to suppress deploy-agents.mjs header/footer in default mode (#460)
|
|
3270
3425
|
// Human dry-run remains verbose; machine-readable dry-run captures the
|
|
@@ -3289,8 +3444,70 @@ export class UseHandler {
|
|
|
3289
3444
|
ui.warn("No .aiwg/aiwg.config found. Run 'aiwg init', then ask your AIWG agent to configure this project properly.");
|
|
3290
3445
|
}
|
|
3291
3446
|
}
|
|
3292
|
-
|
|
3447
|
+
const targetIdx = remainingArgs.findIndex(a => a === '--target');
|
|
3448
|
+
const target = targetIdx >= 0 && remainingArgs[targetIdx + 1] ? remainingArgs[targetIdx + 1] : process.cwd();
|
|
3449
|
+
// Multi-provider: prepare built-in project-scope projections in at most two
|
|
3450
|
+
// subprocesses, then preserve the existing provider/addon commit order.
|
|
3451
|
+
// User-scope, dry-run, harness-special and project-local adapters retain the
|
|
3452
|
+
// established serial path because their lifecycle is not stage-only.
|
|
3293
3453
|
if (providers.length > 1) {
|
|
3454
|
+
const preparedJobs = [];
|
|
3455
|
+
let canPrepareConcurrently = !dryRun && scope === 'project' && explicitHarnessAgentSelectors.length === 0;
|
|
3456
|
+
for (const [order, requested] of providers.entries()) {
|
|
3457
|
+
const local = await resolveProjectLocalProviderAdapter(projectDir, requested);
|
|
3458
|
+
if (local.requestedProvider) {
|
|
3459
|
+
canPrepareConcurrently = false;
|
|
3460
|
+
break;
|
|
3461
|
+
}
|
|
3462
|
+
const unsupported = unsupportedProviderMessage(requested);
|
|
3463
|
+
if (unsupported)
|
|
3464
|
+
return { exitCode: 1, message: unsupported };
|
|
3465
|
+
const resolved = resolveBuiltInProviderForUse(local.provider);
|
|
3466
|
+
if (!PREPARABLE_BUILTIN_PROVIDERS.has(resolved.provider)) {
|
|
3467
|
+
canPrepareConcurrently = false;
|
|
3468
|
+
break;
|
|
3469
|
+
}
|
|
3470
|
+
const args = withProviderOverride([...deployFilteredArgs], resolved.provider);
|
|
3471
|
+
if (framework === 'all' && !['pi', 'omp'].includes(resolved.provider)
|
|
3472
|
+
&& !remainingArgs.includes('--copy-all') && !remainingArgs.includes('--copy-standard-skills'))
|
|
3473
|
+
args.push('--kernel-only');
|
|
3474
|
+
preparedJobs.push({ order, provider: resolved.provider, target: path.resolve(target), args });
|
|
3475
|
+
}
|
|
3476
|
+
if (canPrepareConcurrently && preparedJobs.length === providers.length) {
|
|
3477
|
+
if (!skipConflicts) {
|
|
3478
|
+
for (const job of preparedJobs) {
|
|
3479
|
+
const canDeploy = await runPreDeployCollisionCheck({
|
|
3480
|
+
frameworkRoot, framework, target, provider: job.provider, force, skipConflicts, verbose,
|
|
3481
|
+
});
|
|
3482
|
+
if (!canDeploy)
|
|
3483
|
+
return { exitCode: 1, message: 'Deployment blocked due to name collisions. See above for details.' };
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
let session;
|
|
3487
|
+
try {
|
|
3488
|
+
session = await prepareProviderDeployments(frameworkRoot, preparedJobs);
|
|
3489
|
+
for (const [order, requested] of providers.entries()) {
|
|
3490
|
+
await session.commit(order);
|
|
3491
|
+
const capability = randomUUID();
|
|
3492
|
+
this.preparedProviderContinuations.add(capability);
|
|
3493
|
+
try {
|
|
3494
|
+
const result = await this.execute({ ...ctx, args: [framework, '--provider', requested, preparedFlag, capability, ...remainingArgs] });
|
|
3495
|
+
if (result.exitCode !== 0)
|
|
3496
|
+
return result;
|
|
3497
|
+
}
|
|
3498
|
+
finally {
|
|
3499
|
+
this.preparedProviderContinuations.delete(capability);
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
return { exitCode: 0 };
|
|
3503
|
+
}
|
|
3504
|
+
catch (error) {
|
|
3505
|
+
return { exitCode: 1, message: `Concurrent provider preparation failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3506
|
+
}
|
|
3507
|
+
finally {
|
|
3508
|
+
await session?.dispose();
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3294
3511
|
for (const p of providers) {
|
|
3295
3512
|
const result = await this.execute({ ...ctx, args: [framework, '--provider', p, ...remainingArgs] });
|
|
3296
3513
|
if (result.exitCode !== 0)
|
|
@@ -3322,8 +3539,6 @@ export class UseHandler {
|
|
|
3322
3539
|
&& !remainingArgs.includes('--copy-standard-skills');
|
|
3323
3540
|
if (bulkKernelOnly)
|
|
3324
3541
|
providerDeployArgs.push('--kernel-only');
|
|
3325
|
-
const targetIdx = remainingArgs.findIndex(a => a === '--target');
|
|
3326
|
-
const target = targetIdx >= 0 && remainingArgs[targetIdx + 1] ? remainingArgs[targetIdx + 1] : process.cwd();
|
|
3327
3542
|
if ((verbose || dryRun) && projectLocalProviderResolution.requestedProvider) {
|
|
3328
3543
|
ui.dim(` project-local provider '${projectLocalProviderResolution.requestedProvider}' extends '${provider}'`);
|
|
3329
3544
|
}
|
|
@@ -3412,7 +3627,19 @@ export class UseHandler {
|
|
|
3412
3627
|
ui.blank();
|
|
3413
3628
|
}
|
|
3414
3629
|
const runner = createScriptRunner(ctx.frameworkRoot);
|
|
3415
|
-
|
|
3630
|
+
let mainResult;
|
|
3631
|
+
if (mainProviderPrepared) {
|
|
3632
|
+
try {
|
|
3633
|
+
await finalizePreparedProvider(frameworkRoot, providerDeployArgs);
|
|
3634
|
+
mainResult = { exitCode: 0 };
|
|
3635
|
+
}
|
|
3636
|
+
catch (error) {
|
|
3637
|
+
mainResult = { exitCode: 1, message: `Prepared provider finalization failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
else {
|
|
3641
|
+
mainResult = await runner.run('tools/agents/deploy-agents.mjs', providerDeployArgs, captureOpts);
|
|
3642
|
+
}
|
|
3416
3643
|
if (mainResult.exitCode !== 0) {
|
|
3417
3644
|
return mainResult;
|
|
3418
3645
|
}
|
|
@@ -3441,6 +3668,8 @@ export class UseHandler {
|
|
|
3441
3668
|
}
|
|
3442
3669
|
// Build common args for addon deployments (inherit provider and target)
|
|
3443
3670
|
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
3671
|
+
if (remainingArgs.includes('--allow-over-budget'))
|
|
3672
|
+
addonBaseArgs.push('--allow-over-budget');
|
|
3444
3673
|
if (scope === 'user')
|
|
3445
3674
|
addonBaseArgs.push('--scope', 'user');
|
|
3446
3675
|
if (bulkKernelOnly)
|
|
@@ -3462,6 +3691,12 @@ export class UseHandler {
|
|
|
3462
3691
|
// Deploy all addons (excluding disallow list) unless --no-utils
|
|
3463
3692
|
if (!skipUtils) {
|
|
3464
3693
|
const allAddons = await getAllAddons(frameworkRoot);
|
|
3694
|
+
// These root collectors already deploy every eligible addon. Re-staging
|
|
3695
|
+
// the entire deployment per addon duplicates that work. Codex's skills
|
|
3696
|
+
// helper includes addons only in all mode; other modes retain their pass.
|
|
3697
|
+
// CLI contribution registration below still runs for every addon.
|
|
3698
|
+
const selectedMode = MODE_MAP[framework];
|
|
3699
|
+
const mainIncludesAddons = mainDeploymentIncludesAddons(provider, selectedMode, providerDeployArgs);
|
|
3465
3700
|
for (const addon of allAddons) {
|
|
3466
3701
|
if (verbose) {
|
|
3467
3702
|
console.log('');
|
|
@@ -3471,9 +3706,10 @@ export class UseHandler {
|
|
|
3471
3706
|
const addonArgs = quiet
|
|
3472
3707
|
? ['--quiet', '--source', source, ...addonBaseArgs]
|
|
3473
3708
|
: ['--source', source, ...addonBaseArgs];
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3709
|
+
if (!mainIncludesAddons) {
|
|
3710
|
+
const result = await runner.run('tools/agents/deploy-agents.mjs', addonArgs, captureOpts);
|
|
3711
|
+
if (result.exitCode !== 0)
|
|
3712
|
+
return result;
|
|
3477
3713
|
}
|
|
3478
3714
|
try {
|
|
3479
3715
|
await registerSourceCliCommands({
|
|
@@ -3690,7 +3926,14 @@ export class UseHandler {
|
|
|
3690
3926
|
// progress through; otherwise we show a single-line spinner-
|
|
3691
3927
|
// style message and capture the noisy stat lines.
|
|
3692
3928
|
ui.blank();
|
|
3693
|
-
|
|
3929
|
+
const { loadPrebuiltDeploymentIndex } = await import('../../artifacts/prebuilt-deployment.js');
|
|
3930
|
+
const prebuilt = loadPrebuiltDeploymentIndex(aiwgRootForIndex, { strictRoot: true });
|
|
3931
|
+
ui.info(prebuilt ? 'Validating packaged capability index…' : 'Building capability index…');
|
|
3932
|
+
if (!prebuilt && await fs.access(path.join(aiwgRootForIndex, 'prebuilt', 'framework-relations', 'manifest.json')).then(() => true).catch(() => false)) {
|
|
3933
|
+
const { selectPrebuiltRelations } = await import('../../artifacts/relations.js');
|
|
3934
|
+
const reason = selectPrebuiltRelations(aiwgRootForIndex).reason ?? 'packaged search index is missing, stale, or does not match the source';
|
|
3935
|
+
ui.dim(` Packaged index unavailable: ${reason}.`);
|
|
3936
|
+
}
|
|
3694
3937
|
ui.dim(' Indexing operational assets for agent-side lookup.');
|
|
3695
3938
|
const indexStart = Date.now();
|
|
3696
3939
|
// Capture buildIndex's own console.log noise unless verbose
|
|
@@ -3698,13 +3941,9 @@ export class UseHandler {
|
|
|
3698
3941
|
if (!verbose)
|
|
3699
3942
|
console.log = () => { };
|
|
3700
3943
|
try {
|
|
3701
|
-
|
|
3702
|
-
//
|
|
3703
|
-
|
|
3704
|
-
// regardless of build cwd.
|
|
3705
|
-
await buildIndex(aiwgRootForIndex, { graph: 'framework', explicit: false });
|
|
3706
|
-
const { syncFortemiCoreIndex } = await import('../../artifacts/fortemi-core-sync.js');
|
|
3707
|
-
syncFortemiCoreIndex(aiwgRootForIndex, { graph: 'framework' });
|
|
3944
|
+
// Validate uncommitted sources once and publish the receipt so
|
|
3945
|
+
// verification/discovery do not immediately scan the corpus again.
|
|
3946
|
+
await reconcileSelectedFrameworkSource(aiwgRootForIndex);
|
|
3708
3947
|
console.log = origLog;
|
|
3709
3948
|
const indexElapsedSec = ((Date.now() - indexStart) / 1000).toFixed(1);
|
|
3710
3949
|
ui.success(`Capability index ready (${indexElapsedSec}s).`);
|