@aiwg/cli 2026.10.8 → 2026.10.10
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/agentic/code/providers/model-capabilities.v1.json +197 -3
- package/bin/aiwg.mjs +8 -0
- package/dist/src/artifacts/cli.js +9 -5
- package/dist/src/auth/config.js +3 -8
- package/dist/src/auth/resource-credentials.js +35 -2
- package/dist/src/cli/handlers/diagnose.js +13 -0
- package/dist/src/cli/handlers/mc-admission.js +39 -0
- package/dist/src/cli/handlers/mc.js +2 -31
- package/dist/src/cli/handlers/models-help.js +52 -0
- package/dist/src/cli/handlers/models.js +11 -81
- package/dist/src/cli/handlers/resource-versions.js +8 -5
- package/dist/src/cli/handlers/script-runner.js +13 -1
- package/dist/src/cli/handlers/use-addon-profile.js +72 -0
- package/dist/src/cli/handlers/use.js +209 -233
- package/dist/src/cli/ui.js +1 -0
- package/dist/src/config/aiwg-config.js +38 -184
- package/dist/src/config/cli-help.js +54 -0
- package/dist/src/config/cli.js +5 -69
- package/dist/src/config/config-normalization.js +10 -0
- package/dist/src/config/worker-activation-gate.js +26 -0
- package/dist/src/config/worker-adoption-cli.js +102 -0
- package/dist/src/config/worker-adoption.js +368 -0
- package/dist/src/config/worker-config-digest.js +14 -0
- package/dist/src/config/worker-group-templates.js +150 -0
- package/dist/src/config/worker-guidance-warning.js +28 -0
- package/dist/src/config/worker-owner-lock.js +152 -0
- package/dist/src/config/worker-parallelism.js +154 -0
- package/dist/src/config/worker-write.js +75 -0
- package/dist/src/decision/telemetry/exporter.js +2 -1
- package/dist/src/decision/telemetry/index.js +1 -0
- package/dist/src/decision/telemetry/mapping.js +43 -0
- package/dist/src/decision/telemetry/otlp-http.js +5 -2
- package/dist/src/decision/telemetry/redaction.js +6 -1
- package/dist/src/decision/telemetry/types.js +3 -0
- package/dist/src/decision/telemetry/worker.js +69 -0
- package/dist/src/lint/rule-activation.js +15 -7
- package/dist/src/lint/runner.js +2 -2
- package/dist/src/mcp/server.mjs +2 -11
- package/dist/src/mcp/stdio-lifecycle.mjs +27 -0
- package/dist/src/mcp/tools/worker-failure-diagnostics.mjs +9 -0
- package/dist/src/mcp/tools/worker-invoke.mjs +6 -6
- package/dist/src/mission-protocol/codecs.js +8 -38
- package/dist/src/mission-protocol/worker-contract-diagnostics.js +62 -0
- package/dist/src/mission-protocol/worker-invocation-types.js +2 -0
- package/dist/src/models/conductor-data-policy.d.mts +8 -0
- package/dist/src/models/conductor-data-policy.mjs +190 -0
- package/dist/src/models/config-loader.js +19 -3
- package/dist/src/models/config-writer.js +27 -0
- package/dist/src/models/model-capabilities.v1.json +197 -3
- package/dist/src/models/provider-policy.js +7 -155
- package/dist/src/models/resolver.js +2 -293
- package/dist/src/models/worker-artifact-binding.mjs +12 -0
- package/dist/src/models/worker-direct-readiness-policy.js +155 -0
- package/dist/src/models/worker-direct-readiness.js +9 -218
- package/dist/src/models/worker-health-readiness.js +105 -26
- package/dist/src/models/worker-installation.mjs +12 -14
- package/dist/src/models/worker-member-references.js +64 -0
- package/dist/src/models/worker-plan.js +317 -0
- package/dist/src/models/worker-selection-policy.js +217 -0
- package/dist/src/models/wrapper-deployment.js +1 -1
- package/dist/src/resources/web-release.js +76 -65
- package/dist/src/serve/shared-host-admission-checks.js +116 -0
- package/dist/src/serve/shared-host-scheduler.js +25 -107
- package/dist/src/serve/shared-host-starvation.js +73 -0
- package/dist/src/serve/worker-artifacts.d.mts +4 -0
- package/dist/src/serve/worker-artifacts.mjs +56 -0
- package/dist/src/serve/worker-command-request.js +68 -0
- package/dist/src/serve/worker-invocation-paths.js +144 -0
- package/dist/src/serve/worker-invocation-preparation.js +169 -0
- package/dist/src/serve/worker-invocation.js +24 -291
- package/dist/src/serve/worker-stdin-frame.d.mts +2 -2
- package/dist/src/serve/worker-stdin-frame.mjs +6 -6
- package/dist/src/smiths/context-pipeline/parallelism-section.js +19 -7
- package/dist/src/storage/backends/fortemi.js +33 -29
- package/dist/src/storage/backends/logseq.js +16 -3
- package/dist/src/storage/backends/postgres.js +74 -33
- package/dist/src/storage/backends/postgrest.js +37 -13
- package/dist/src/storage/config.js +6 -1
- package/dist/src/uhp/config.js +4 -0
- package/package.json +9 -1
- package/schemas/mission-v1.schema.json +20 -19
- package/schemas/models/model-config-compatibility.v1.schema.json +16 -0
- package/tools/agents/providers/claude-post-deploy.mjs +35 -0
- package/tools/agents/providers/claude.mjs +3 -30
- package/tools/agents/providers/codex-post-deploy.mjs +13 -0
- package/tools/agents/providers/codex.mjs +2 -8
- package/tools/agents/providers/conductor-data-guard.mjs +61 -0
- package/tools/agents/providers/rule-delivery.mjs +3 -16
- package/tools/agents/providers/rule-presentation.mjs +38 -0
- package/tools/plugin/package-plugins.mjs +1 -1
- package/tools/ralph-external/lib/claude-adapter.mjs +2 -2
- package/tools/ralph-external/lib/codex-adapter.mjs +3 -3
- package/tools/ralph-external/lib/managed-worker-attempt.mjs +86 -0
- package/tools/ralph-external/lib/provider-adapter.mjs +11 -260
- package/tools/ralph-external/lib/session-attempt.mjs +85 -0
- package/tools/ralph-external/lib/strict-worker-json.mjs +190 -0
- package/tools/ralph-external/lib/worker-artifacts.mjs +209 -0
- package/tools/ralph-external/lib/worker-final.mjs +143 -0
- package/tools/ralph-external/lib/worker-inputs.mjs +55 -0
- package/tools/ralph-external/lib/worker-isolation.mjs +2 -44
- package/tools/ralph-external/lib/worker-launch-cli.mjs +47 -0
- package/tools/ralph-external/lib/worker-native-sandbox.mjs +83 -0
- package/tools/ralph-external/session-launcher.mjs +73 -217
- package/vscode-extension/schemas/aiwg.config.v1.json +161 -2
|
@@ -12,6 +12,7 @@ import { trackTemporaryDirectory } from '../../utils/temporary-directory.js';
|
|
|
12
12
|
* @issue #33
|
|
13
13
|
*/
|
|
14
14
|
import fs from 'fs/promises';
|
|
15
|
+
import { existsSync, rmSync, rmdirSync } from 'fs';
|
|
15
16
|
import path from 'path';
|
|
16
17
|
import os from 'os';
|
|
17
18
|
import { pathToFileURL } from 'node:url';
|
|
@@ -27,11 +28,12 @@ import { registerDeployedExtensions } from '../../extensions/deployment-registra
|
|
|
27
28
|
import { loadCliCommandsContribution, registerCliCommands, registerHooks, } from '../cli-extension-loader.js';
|
|
28
29
|
import { translateSkillsToCommands, providerNeedsCommands } from '../../plugin/skill-command-translator.js';
|
|
29
30
|
import * as ui from '../ui.js';
|
|
30
|
-
import { readAiwgConfig, writeAiwgConfig, updateInstalled, hashManifest, emptyConfig, getProjectDir } from '../../config/aiwg-config.js';
|
|
31
|
+
import { readAiwgConfig, writeAiwgConfig, updateInstalled, hashManifest, emptyConfig, getProjectDir, getConfigPath } from '../../config/aiwg-config.js';
|
|
31
32
|
import { appendGitignore } from '../../config/gitignore.js';
|
|
32
33
|
import { getLogger } from '../log.js';
|
|
33
34
|
import { installCockpit } from './cockpit.js';
|
|
34
35
|
import { initHandler } from './init.js';
|
|
36
|
+
import { selectAddonProfile } from './use-addon-profile.js';
|
|
35
37
|
import { checkCollisions, formatCollisionReport, hasBlockingCollisions, } from '../../smiths/skillsmith/collision-detector.js';
|
|
36
38
|
import { discoverProjectLocalBundles, } from '../../extensions/project-local-discovery.js';
|
|
37
39
|
import { PROJECT_LOCAL_TYPE_TO_DIR } from '../../extensions/project-local-paths.js';
|
|
@@ -65,7 +67,7 @@ import { verifyModelWrapperDeployment } from '../../models/wrapper-deployment.js
|
|
|
65
67
|
import { aggregateUseDeploymentResult, buildDryRunUseResult, renderUseDeploymentResult, verifyProviderDeployment, } from '../services/deployment-verification.js';
|
|
66
68
|
import { finalizeProviderTransformationReceipt, providerReceiptHasLocalSources, sourceVerificationsFromSignedWebRelease, } from '../../providers/transformation-receipt-integration.js';
|
|
67
69
|
import { loadResourceTrustRootFile, resolveWebRelease, } from '../../resources/web-release.js';
|
|
68
|
-
import { createResourceCredentialProvider } from '../../auth/resource-credentials.js';
|
|
70
|
+
import { createResourceCredentialProvider, prepareResourceCredentials } from '../../auth/resource-credentials.js';
|
|
69
71
|
/**
|
|
70
72
|
* Valid framework identifiers
|
|
71
73
|
*/
|
|
@@ -102,7 +104,7 @@ export async function resolveProviderReceiptSource(options) {
|
|
|
102
104
|
release = await resolveWebRelease({ ...releaseOptions, selector: versionInfo.version, offline: true });
|
|
103
105
|
}
|
|
104
106
|
catch {
|
|
105
|
-
const credentialProvider = createResourceCredentialProvider(process.env);
|
|
107
|
+
const credentialProvider = options.credentialProvider ?? createResourceCredentialProvider(process.env);
|
|
106
108
|
const token = await credentialProvider();
|
|
107
109
|
// Protected production resources require the authenticated release
|
|
108
110
|
// credential. A configured alternate endpoint may intentionally be public.
|
|
@@ -1697,6 +1699,7 @@ function createUseScriptRunner(frameworkRoot) {
|
|
|
1697
1699
|
const runner = createScriptRunner(frameworkRoot);
|
|
1698
1700
|
return {
|
|
1699
1701
|
async run(script, args, options = {}) {
|
|
1702
|
+
options = { ...options, omitEnv: useDeployment?.resourceCredentials?.omitEnv ?? ['AIWG_RESOURCE_TOKEN'] };
|
|
1700
1703
|
if (script === 'tools/agents/deploy-agents.mjs')
|
|
1701
1704
|
args = useDeploymentArgs(args);
|
|
1702
1705
|
if (!usePreviewActions)
|
|
@@ -2472,6 +2475,9 @@ Bundles:
|
|
|
2472
2475
|
<addon> | <extension> Any installed addon or extension name
|
|
2473
2476
|
|
|
2474
2477
|
Options:
|
|
2478
|
+
--resource-token-stdin | --resource-token-file <path> | --resource-token-store <name>
|
|
2479
|
+
--resource-token-env <NAME> | --resource-token-interactive
|
|
2480
|
+
Select the optional protected release bearer
|
|
2475
2481
|
--provider <name> Target provider (default: .aiwg/aiwg.config providers)
|
|
2476
2482
|
--target <dir> Deploy into <dir> instead of the current directory
|
|
2477
2483
|
--scope project|user Deploy to the project (default) or the user scope
|
|
@@ -2543,11 +2549,22 @@ export class UseHandler {
|
|
|
2543
2549
|
return { exitCode: 0, message: USE_HELP, rawOutput: true };
|
|
2544
2550
|
}
|
|
2545
2551
|
async execute(ctx) {
|
|
2552
|
+
let resourceCredentials = useDeployment?.resourceCredentials;
|
|
2553
|
+
try {
|
|
2554
|
+
if (!resourceCredentials) {
|
|
2555
|
+
resourceCredentials = await prepareResourceCredentials(ctx.args);
|
|
2556
|
+
ctx = { ...ctx, args: resourceCredentials.args };
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
catch (error) {
|
|
2560
|
+
return { exitCode: 2, message: error instanceof Error ? error.message : String(error) };
|
|
2561
|
+
}
|
|
2546
2562
|
const invalidOption = validateUseOptions(ctx.args, this.preparedProviderContinuations);
|
|
2547
2563
|
if (invalidOption)
|
|
2548
2564
|
return { exitCode: 2, message: invalidOption };
|
|
2549
2565
|
const previousDeployment = useDeployment;
|
|
2550
2566
|
useDeployment = {
|
|
2567
|
+
resourceCredentials,
|
|
2551
2568
|
version: previousDeployment?.version ?? resolveDeployVersion(ctx.frameworkRoot || await getFrameworkRoot()),
|
|
2552
2569
|
skipContextFiles: previousDeployment?.skipContextFiles || ctx.args.includes('--no-context-files'),
|
|
2553
2570
|
contextFiles: previousDeployment?.contextFiles ?? [],
|
|
@@ -2672,7 +2689,7 @@ export class UseHandler {
|
|
|
2672
2689
|
}
|
|
2673
2690
|
let coreResult;
|
|
2674
2691
|
try {
|
|
2675
|
-
coreResult = await this.executeCore({ ...ctx, args: coreArgs });
|
|
2692
|
+
coreResult = await this.executeCore({ ...ctx, args: coreArgs }, providers);
|
|
2676
2693
|
}
|
|
2677
2694
|
catch (error) {
|
|
2678
2695
|
coreResult = { exitCode: 1, message: error instanceof Error ? error.message : String(error) };
|
|
@@ -2730,7 +2747,7 @@ export class UseHandler {
|
|
|
2730
2747
|
scope: effectiveScope,
|
|
2731
2748
|
requestedBundles: [requestedBundle],
|
|
2732
2749
|
};
|
|
2733
|
-
const sourceResolution = await resolveProviderReceiptSource(receiptOptions);
|
|
2750
|
+
const sourceResolution = await resolveProviderReceiptSource({ ...receiptOptions, credentialProvider: useDeployment?.resourceCredentials?.credentialProvider });
|
|
2734
2751
|
await finalizeProviderTransformationReceipt({ ...receiptOptions, ...sourceResolution });
|
|
2735
2752
|
}
|
|
2736
2753
|
catch (error) {
|
|
@@ -2807,7 +2824,7 @@ export class UseHandler {
|
|
|
2807
2824
|
message: [coreResult.message, rendered, ...(previewActions ? [...previewActions].sort() : [])].filter(Boolean).join('\n'),
|
|
2808
2825
|
};
|
|
2809
2826
|
}
|
|
2810
|
-
async executeCore(ctx) {
|
|
2827
|
+
async executeCore(ctx, resolvedProviders) {
|
|
2811
2828
|
const explicitTarget = firstUsePositional(ctx.args);
|
|
2812
2829
|
if (ctx.args.includes('--workspace-signals')) {
|
|
2813
2830
|
const signalArgs = ctx.args.filter((a) => a !== '--workspace-signals');
|
|
@@ -2974,6 +2991,13 @@ export class UseHandler {
|
|
|
2974
2991
|
|| remainingArgs.includes('--yes')
|
|
2975
2992
|
|| remainingArgs.includes('-y')
|
|
2976
2993
|
|| remainingArgs.includes('--non-interactive');
|
|
2994
|
+
// An auto-created config is removed again if the target turns out to be unknown,
|
|
2995
|
+
// so a mistyped `aiwg use <name>` leaves the project untouched.
|
|
2996
|
+
let autoCreatedConfig = null;
|
|
2997
|
+
if (!config && !_isDryRun) {
|
|
2998
|
+
const configPath = getConfigPath(projectDir);
|
|
2999
|
+
autoCreatedConfig = { path: configPath, controlDirExisted: existsSync(path.dirname(configPath)) };
|
|
3000
|
+
}
|
|
2977
3001
|
if (!config) {
|
|
2978
3002
|
if (_providersValue) {
|
|
2979
3003
|
// --providers shorthand: write config without wizard
|
|
@@ -3291,6 +3315,15 @@ export class UseHandler {
|
|
|
3291
3315
|
message: totalFailed > 0 ? `${totalFailed} project-local deploy(s) failed` : '',
|
|
3292
3316
|
};
|
|
3293
3317
|
}
|
|
3318
|
+
if (autoCreatedConfig) {
|
|
3319
|
+
rmSync(autoCreatedConfig.path, { force: true });
|
|
3320
|
+
if (!autoCreatedConfig.controlDirExisted) {
|
|
3321
|
+
try {
|
|
3322
|
+
rmdirSync(path.dirname(autoCreatedConfig.path));
|
|
3323
|
+
}
|
|
3324
|
+
catch { /* not empty or already gone */ }
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3294
3327
|
return {
|
|
3295
3328
|
exitCode: 1,
|
|
3296
3329
|
message: `Error: Unknown target '${framework}'\nFrameworks: ${VALID_FRAMEWORKS.join(', ')}\n\n'all' deploys the kernel surface (kernel skills, kernel and core rules, behaviors).\nFor a single addon, run 'aiwg list' to see available addons.\nFor extensions (sys, net, it, sec, stream, dev), see $AIWG_ROOT/agentic/code/extensions/.\nFor project-local artifacts, run 'aiwg list --project-local'.\nRun 'aiwg help' for usage information.`,
|
|
@@ -3301,7 +3334,8 @@ export class UseHandler {
|
|
|
3301
3334
|
if (isAddon || isExtension) {
|
|
3302
3335
|
const providerIdx = remainingArgs.findIndex(a => a === '--provider' || a === '--platform');
|
|
3303
3336
|
const explicitAddonProvider = providerIdx >= 0 && remainingArgs[providerIdx + 1] ? remainingArgs[providerIdx + 1] : null;
|
|
3304
|
-
const
|
|
3337
|
+
const providers = resolvedProviders ?? [...new Set(configuredGlobalProviders(remainingArgs, config)
|
|
3338
|
+
.map(provider => resolveBuiltInProviderForUse(provider).provider))];
|
|
3305
3339
|
const targetIdx = remainingArgs.findIndex(a => a === '--target');
|
|
3306
3340
|
const target = targetIdx >= 0 && remainingArgs[targetIdx + 1] ? remainingArgs[targetIdx + 1] : process.cwd();
|
|
3307
3341
|
const dryRunAddon = remainingArgs.includes('--dry-run');
|
|
@@ -3314,264 +3348,206 @@ export class UseHandler {
|
|
|
3314
3348
|
catch (error) {
|
|
3315
3349
|
return { exitCode: 1, message: `Error: ${error instanceof Error ? error.message : String(error)}` };
|
|
3316
3350
|
}
|
|
3317
|
-
if (addonScope === 'user' && !USER_SCOPE_PATHS[provider]) {
|
|
3318
|
-
return {
|
|
3319
|
-
exitCode: 1,
|
|
3320
|
-
message: `--scope user not supported for provider '${provider}' — see docs/customization/user-scope-deployment.md for the supported list`,
|
|
3321
|
-
};
|
|
3322
|
-
}
|
|
3323
|
-
const runner = createUseScriptRunner(frameworkRoot);
|
|
3324
|
-
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
3325
|
-
if (remainingArgs.includes('--allow-over-budget'))
|
|
3326
|
-
addonBaseArgs.push('--allow-over-budget');
|
|
3327
|
-
if (addonScope === 'user')
|
|
3328
|
-
addonBaseArgs.push('--scope', 'user');
|
|
3329
|
-
// An explicitly selected upstream addon must be self-contained in the
|
|
3330
|
-
// project. Unlike a full framework deploy, its standard skills cannot be
|
|
3331
|
-
// left index-only: the user asked to install this specific bundle and
|
|
3332
|
-
// its supporting scripts must travel with the skill directory.
|
|
3333
|
-
addonBaseArgs.push('--copy-all');
|
|
3334
|
-
addonBaseArgs.push(...modelDeployArgs);
|
|
3335
|
-
if (provider)
|
|
3336
|
-
addonBaseArgs.push('--provider', provider);
|
|
3337
|
-
if (target)
|
|
3338
|
-
addonBaseArgs.push('--target', target);
|
|
3339
|
-
// Forward --copy-all (#1219) so addon-only deploys also honor it.
|
|
3340
|
-
if ((remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills'))
|
|
3341
|
-
&& !addonBaseArgs.includes('--copy-all')) {
|
|
3342
|
-
addonBaseArgs.push('--copy-all');
|
|
3343
|
-
}
|
|
3344
|
-
if (dryRunAddon)
|
|
3345
|
-
addonBaseArgs.push('--dry-run');
|
|
3346
|
-
if (remainingArgs.includes('--force'))
|
|
3347
|
-
addonBaseArgs.push('--force');
|
|
3348
3351
|
const kind = isExtension ? 'extension' : 'addon';
|
|
3349
|
-
const
|
|
3350
|
-
?
|
|
3351
|
-
:
|
|
3352
|
-
|
|
3353
|
-
for (const
|
|
3352
|
+
const addonSource = isExtension
|
|
3353
|
+
? extensionPath(frameworkRoot, framework)
|
|
3354
|
+
: addonPath(frameworkRoot, framework);
|
|
3355
|
+
// Deploy, reconcile, and record exactly the provider set verification checks.
|
|
3356
|
+
for (const provider of providers) {
|
|
3357
|
+
if (addonScope === 'user' && !USER_SCOPE_PATHS[provider]) {
|
|
3358
|
+
return {
|
|
3359
|
+
exitCode: 1,
|
|
3360
|
+
message: `--scope user not supported for provider '${provider}' — see docs/customization/user-scope-deployment.md for the supported list`,
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
const runner = createUseScriptRunner(frameworkRoot);
|
|
3364
|
+
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
3365
|
+
if (remainingArgs.includes('--allow-over-budget'))
|
|
3366
|
+
addonBaseArgs.push('--allow-over-budget');
|
|
3367
|
+
if (addonScope === 'user')
|
|
3368
|
+
addonBaseArgs.push('--scope', 'user');
|
|
3369
|
+
// An explicitly selected upstream addon must be self-contained in the
|
|
3370
|
+
// project. Unlike a full framework deploy, its standard skills cannot be
|
|
3371
|
+
// left index-only: the user asked to install this specific bundle and
|
|
3372
|
+
// its supporting scripts must travel with the skill directory.
|
|
3373
|
+
addonBaseArgs.push('--copy-all');
|
|
3374
|
+
addonBaseArgs.push(...modelDeployArgs);
|
|
3375
|
+
if (provider)
|
|
3376
|
+
addonBaseArgs.push('--provider', provider);
|
|
3377
|
+
if (target)
|
|
3378
|
+
addonBaseArgs.push('--target', target);
|
|
3379
|
+
// Forward --copy-all (#1219) so addon-only deploys also honor it.
|
|
3380
|
+
if ((remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills'))
|
|
3381
|
+
&& !addonBaseArgs.includes('--copy-all')) {
|
|
3382
|
+
addonBaseArgs.push('--copy-all');
|
|
3383
|
+
}
|
|
3384
|
+
if (dryRunAddon)
|
|
3385
|
+
addonBaseArgs.push('--dry-run');
|
|
3386
|
+
if (remainingArgs.includes('--force'))
|
|
3387
|
+
addonBaseArgs.push('--force');
|
|
3388
|
+
const activationOrder = isAddon
|
|
3389
|
+
? await resolveRequiredAddonActivationOrder(frameworkRoot, framework)
|
|
3390
|
+
: [framework];
|
|
3391
|
+
const requiredAddons = activationOrder.slice(0, -1);
|
|
3392
|
+
for (const dependency of requiredAddons) {
|
|
3393
|
+
ui.blank();
|
|
3394
|
+
ui.header(` Deploying required ${dependency} addon...`);
|
|
3395
|
+
const dependencySource = addonPath(frameworkRoot, dependency);
|
|
3396
|
+
const dependencyResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3397
|
+
'--quiet', '--source', dependencySource,
|
|
3398
|
+
...addonBaseArgs,
|
|
3399
|
+
], { capture: true });
|
|
3400
|
+
if (dependencyResult.exitCode !== 0) {
|
|
3401
|
+
return {
|
|
3402
|
+
...dependencyResult,
|
|
3403
|
+
message: dependencyResult.message
|
|
3404
|
+
|| `Failed to deploy required addon '${dependency}'`,
|
|
3405
|
+
};
|
|
3406
|
+
}
|
|
3407
|
+
if (!dryRunAddon) {
|
|
3408
|
+
try {
|
|
3409
|
+
await reconcileDeployedSkillAssets(dependencySource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3410
|
+
}
|
|
3411
|
+
catch (error) {
|
|
3412
|
+
return {
|
|
3413
|
+
exitCode: 1,
|
|
3414
|
+
message: `Required addon '${dependency}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3415
|
+
};
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
try {
|
|
3419
|
+
await registerSourceCliCommands({
|
|
3420
|
+
source: dependencySource,
|
|
3421
|
+
target,
|
|
3422
|
+
provider,
|
|
3423
|
+
dryRun: dryRunAddon,
|
|
3424
|
+
fallbackDescription: `${dependency} addon commands`,
|
|
3425
|
+
});
|
|
3426
|
+
}
|
|
3427
|
+
catch (error) {
|
|
3428
|
+
return {
|
|
3429
|
+
exitCode: 1,
|
|
3430
|
+
message: `Failed to register required addon '${dependency}' CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
ui.success(dryRunAddon
|
|
3434
|
+
? `Required ${dependency} addon activation previewed`
|
|
3435
|
+
: `Required ${dependency} addon deployed`);
|
|
3436
|
+
}
|
|
3354
3437
|
ui.blank();
|
|
3355
|
-
ui.header(` Deploying
|
|
3356
|
-
const
|
|
3357
|
-
|
|
3358
|
-
'--quiet', '--source', dependencySource,
|
|
3438
|
+
ui.header(` Deploying ${framework} ${kind}...`);
|
|
3439
|
+
const addonResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3440
|
+
'--quiet', '--source', addonSource,
|
|
3359
3441
|
...addonBaseArgs,
|
|
3360
3442
|
], { capture: true });
|
|
3361
|
-
if (
|
|
3362
|
-
return
|
|
3363
|
-
...dependencyResult,
|
|
3364
|
-
message: dependencyResult.message
|
|
3365
|
-
|| `Failed to deploy required addon '${dependency}'`,
|
|
3366
|
-
};
|
|
3443
|
+
if (addonResult.exitCode !== 0) {
|
|
3444
|
+
return addonResult;
|
|
3367
3445
|
}
|
|
3368
3446
|
if (!dryRunAddon) {
|
|
3369
3447
|
try {
|
|
3370
|
-
await reconcileDeployedSkillAssets(
|
|
3448
|
+
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3371
3449
|
}
|
|
3372
3450
|
catch (error) {
|
|
3373
3451
|
return {
|
|
3374
3452
|
exitCode: 1,
|
|
3375
|
-
message:
|
|
3453
|
+
message: `${kind} '${framework}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3376
3454
|
};
|
|
3377
3455
|
}
|
|
3378
3456
|
}
|
|
3457
|
+
if (!dryRunAddon && provider === 'omp' && (detectScope(remainingArgs) === 'user' || remainingArgs.includes('--user'))) {
|
|
3458
|
+
try {
|
|
3459
|
+
await deployOmpUserSource({ frameworkRoot, source: addonSource, target, bundle: framework, copyAll: true });
|
|
3460
|
+
}
|
|
3461
|
+
catch (error) {
|
|
3462
|
+
return { exitCode: 1, message: `OMP user deployment failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
// Register only artifacts actually written by a confirmed deployment.
|
|
3466
|
+
if (!dryRunAddon) {
|
|
3467
|
+
try {
|
|
3468
|
+
const registry = getRegistry();
|
|
3469
|
+
const paths = getProviderPaths(provider);
|
|
3470
|
+
await registerDeployedExtensions(registry, {
|
|
3471
|
+
agentsPath: paths.agents,
|
|
3472
|
+
skillsPath: paths.skills,
|
|
3473
|
+
commandsPath: paths.commands,
|
|
3474
|
+
rulesPath: paths.rules,
|
|
3475
|
+
behaviorsPath: paths.behaviors,
|
|
3476
|
+
provider,
|
|
3477
|
+
cwd: target,
|
|
3478
|
+
});
|
|
3479
|
+
ui.success('Extension registration complete');
|
|
3480
|
+
}
|
|
3481
|
+
catch (error) {
|
|
3482
|
+
ui.warn(`Failed to register extensions: ${error instanceof Error ? error.message : String(error)}`);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
// Register CLI commands if addon declares them
|
|
3379
3486
|
try {
|
|
3380
3487
|
await registerSourceCliCommands({
|
|
3381
|
-
source:
|
|
3488
|
+
source: addonSource,
|
|
3382
3489
|
target,
|
|
3383
3490
|
provider,
|
|
3384
3491
|
dryRun: dryRunAddon,
|
|
3385
|
-
fallbackDescription: `${
|
|
3492
|
+
fallbackDescription: `${framework} addon commands`,
|
|
3386
3493
|
});
|
|
3387
3494
|
}
|
|
3388
3495
|
catch (error) {
|
|
3389
3496
|
return {
|
|
3390
3497
|
exitCode: 1,
|
|
3391
|
-
message: `Failed to register
|
|
3392
|
-
};
|
|
3393
|
-
}
|
|
3394
|
-
ui.success(dryRunAddon
|
|
3395
|
-
? `Required ${dependency} addon activation previewed`
|
|
3396
|
-
: `Required ${dependency} addon deployed`);
|
|
3397
|
-
}
|
|
3398
|
-
ui.blank();
|
|
3399
|
-
ui.header(` Deploying ${framework} ${kind}...`);
|
|
3400
|
-
const addonSource = isExtension
|
|
3401
|
-
? extensionPath(frameworkRoot, framework)
|
|
3402
|
-
: addonPath(frameworkRoot, framework);
|
|
3403
|
-
const addonResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3404
|
-
'--quiet', '--source', addonSource,
|
|
3405
|
-
...addonBaseArgs,
|
|
3406
|
-
], { capture: true });
|
|
3407
|
-
if (addonResult.exitCode !== 0) {
|
|
3408
|
-
return addonResult;
|
|
3409
|
-
}
|
|
3410
|
-
if (!dryRunAddon) {
|
|
3411
|
-
try {
|
|
3412
|
-
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3413
|
-
}
|
|
3414
|
-
catch (error) {
|
|
3415
|
-
return {
|
|
3416
|
-
exitCode: 1,
|
|
3417
|
-
message: `${kind} '${framework}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3498
|
+
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3418
3499
|
};
|
|
3419
3500
|
}
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
await deployOmpUserSource({ frameworkRoot, source: addonSource, target, bundle: framework, copyAll: true });
|
|
3424
|
-
}
|
|
3425
|
-
catch (error) {
|
|
3426
|
-
return { exitCode: 1, message: `OMP user deployment failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3427
|
-
}
|
|
3428
|
-
}
|
|
3429
|
-
// Register only artifacts actually written by a confirmed deployment.
|
|
3430
|
-
if (!dryRunAddon) {
|
|
3431
|
-
try {
|
|
3432
|
-
const registry = getRegistry();
|
|
3433
|
-
const paths = getProviderPaths(provider);
|
|
3434
|
-
await registerDeployedExtensions(registry, {
|
|
3435
|
-
agentsPath: paths.agents,
|
|
3436
|
-
skillsPath: paths.skills,
|
|
3437
|
-
commandsPath: paths.commands,
|
|
3438
|
-
rulesPath: paths.rules,
|
|
3439
|
-
behaviorsPath: paths.behaviors,
|
|
3440
|
-
provider,
|
|
3441
|
-
cwd: target,
|
|
3442
|
-
});
|
|
3443
|
-
ui.success('Extension registration complete');
|
|
3444
|
-
}
|
|
3445
|
-
catch (error) {
|
|
3446
|
-
ui.warn(`Failed to register extensions: ${error instanceof Error ? error.message : String(error)}`);
|
|
3447
|
-
}
|
|
3448
|
-
}
|
|
3449
|
-
// Register CLI commands if addon declares them
|
|
3450
|
-
try {
|
|
3451
|
-
await registerSourceCliCommands({
|
|
3452
|
-
source: addonSource,
|
|
3453
|
-
target,
|
|
3454
|
-
provider,
|
|
3455
|
-
dryRun: dryRunAddon,
|
|
3456
|
-
fallbackDescription: `${framework} addon commands`,
|
|
3457
|
-
});
|
|
3458
|
-
}
|
|
3459
|
-
catch (error) {
|
|
3460
|
-
return {
|
|
3461
|
-
exitCode: 1,
|
|
3462
|
-
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3463
|
-
};
|
|
3464
|
-
}
|
|
3465
|
-
if (!dryRunAddon && (provider === 'openclaw' || (provider === 'grokbot' && addonScope === 'user'))) {
|
|
3466
|
-
try {
|
|
3467
|
-
await recordNativeAddonDeploy(addonSource, target, provider, framework);
|
|
3468
|
-
}
|
|
3469
|
-
catch (error) {
|
|
3470
|
-
return { exitCode: 1, message: `Addon user registry update failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3471
|
-
}
|
|
3472
|
-
}
|
|
3473
|
-
// Persist the same lifecycle record frameworks and project-local bundles
|
|
3474
|
-
// receive so status, refresh, doctor, and remove can account for this
|
|
3475
|
-
// upstream addon and every provider artifact it actually deployed.
|
|
3476
|
-
if (!dryRunAddon && config) {
|
|
3477
|
-
try {
|
|
3478
|
-
const manifestPath = path.join(addonSource, 'manifest.json');
|
|
3479
|
-
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
3480
|
-
// Provider rule aggregation may rename many source rules into one
|
|
3481
|
-
// managed index. Record this addon's contributed artifact counts,
|
|
3482
|
-
// matching framework registry semantics, rather than trying to
|
|
3483
|
-
// attribute shared aggregate filenames after deployment.
|
|
3484
|
-
const counts = await countBundleSourceArtifacts(addonSource);
|
|
3485
|
-
const updated = updateInstalled(config, framework, provider, counts, {
|
|
3486
|
-
version: manifest.version ?? (await getVersionInfo()).version,
|
|
3487
|
-
source: 'bundled',
|
|
3488
|
-
manifestHash: await hashManifest(manifestPath),
|
|
3489
|
-
asPrimary: Boolean(explicitAddonProvider),
|
|
3490
|
-
});
|
|
3491
|
-
await writeAiwgConfig(projectDir, updated);
|
|
3492
|
-
config = updated;
|
|
3493
|
-
}
|
|
3494
|
-
catch (error) {
|
|
3495
|
-
ui.warn(`Addon registry update failed for '${framework}': ${error instanceof Error ? error.message : String(error)}`);
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
// Profile picker for addons with memory topology and multiple templates
|
|
3499
|
-
try {
|
|
3500
|
-
const profileManifestPath = path.join(addonSource, 'manifest.json');
|
|
3501
|
-
const profileManifestContent = await fs.readFile(profileManifestPath, 'utf-8');
|
|
3502
|
-
const profileManifest = JSON.parse(profileManifestContent);
|
|
3503
|
-
const topology = profileManifest.memory?.topology;
|
|
3504
|
-
const templates = profileManifest.templates;
|
|
3505
|
-
if (topology && templates && templates.length > 1) {
|
|
3506
|
-
const profileIdx = remainingArgs.findIndex(a => a === '--profile');
|
|
3507
|
-
let selectedProfile;
|
|
3508
|
-
if (profileIdx >= 0 && remainingArgs[profileIdx + 1]) {
|
|
3509
|
-
// Explicit --profile flag
|
|
3510
|
-
selectedProfile = remainingArgs[profileIdx + 1];
|
|
3511
|
-
const templateFile = templates.find((t) => t.replace('.md', '') === selectedProfile || t === selectedProfile);
|
|
3512
|
-
if (!templateFile) {
|
|
3513
|
-
ui.warn(`Unknown profile "${selectedProfile}". Available: ${templates.map((t) => t.replace('.md', '')).join(', ')}`);
|
|
3514
|
-
selectedProfile = undefined;
|
|
3515
|
-
}
|
|
3501
|
+
if (!dryRunAddon && (provider === 'openclaw' || (provider === 'grokbot' && addonScope === 'user'))) {
|
|
3502
|
+
try {
|
|
3503
|
+
await recordNativeAddonDeploy(addonSource, target, provider, framework);
|
|
3516
3504
|
}
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
// The profile picker is annoying during `aiwg use all`.
|
|
3520
|
-
selectedProfile = 'generic';
|
|
3505
|
+
catch (error) {
|
|
3506
|
+
return { exitCode: 1, message: `Addon user registry update failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3521
3507
|
}
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
const
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
}
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
}
|
|
3508
|
+
}
|
|
3509
|
+
// Persist the same lifecycle record frameworks and project-local bundles
|
|
3510
|
+
// receive so status, refresh, doctor, and remove can account for this
|
|
3511
|
+
// upstream addon and every provider artifact it actually deployed.
|
|
3512
|
+
if (!dryRunAddon && config) {
|
|
3513
|
+
try {
|
|
3514
|
+
const manifestPath = path.join(addonSource, 'manifest.json');
|
|
3515
|
+
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
3516
|
+
// Provider rule aggregation may rename many source rules into one
|
|
3517
|
+
// managed index. Record this addon's contributed artifact counts,
|
|
3518
|
+
// matching framework registry semantics, rather than trying to
|
|
3519
|
+
// attribute shared aggregate filenames after deployment.
|
|
3520
|
+
const counts = await countBundleSourceArtifacts(addonSource);
|
|
3521
|
+
const updated = updateInstalled(config, framework, provider, counts, {
|
|
3522
|
+
version: manifest.version ?? (await getVersionInfo()).version,
|
|
3523
|
+
source: 'bundled',
|
|
3524
|
+
manifestHash: await hashManifest(manifestPath),
|
|
3525
|
+
asPrimary: Boolean(explicitAddonProvider),
|
|
3526
|
+
});
|
|
3527
|
+
await writeAiwgConfig(projectDir, updated);
|
|
3528
|
+
config = updated;
|
|
3544
3529
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
const namespace = topology.namespace || `.aiwg/${framework}`;
|
|
3548
|
-
const configDir = path.join(target, namespace);
|
|
3549
|
-
await fs.mkdir(configDir, { recursive: true });
|
|
3550
|
-
const profileConfig = {
|
|
3551
|
-
profile: selectedProfile,
|
|
3552
|
-
pageTemplate: `templates/${selectedProfile}.md`,
|
|
3553
|
-
selectedAt: new Date().toISOString(),
|
|
3554
|
-
};
|
|
3555
|
-
await fs.writeFile(path.join(configDir, 'config.json'), JSON.stringify(profileConfig, null, 2) + '\n');
|
|
3556
|
-
ui.success(`Profile "${selectedProfile}" selected → ${namespace}/config.json`);
|
|
3530
|
+
catch (error) {
|
|
3531
|
+
ui.warn(`Addon registry update failed for '${framework}': ${error instanceof Error ? error.message : String(error)}`);
|
|
3557
3532
|
}
|
|
3558
3533
|
}
|
|
3534
|
+
if (framework === 'aiwg-utils' && !['pi', 'omp'].includes(provider) && !remainingArgs.includes('--dry-run')) {
|
|
3535
|
+
const wrapperValidation = await validateDeployedModelWrappers({
|
|
3536
|
+
provider: normalizeProviderDefinitionId(provider) ?? provider,
|
|
3537
|
+
target,
|
|
3538
|
+
frameworkRoot,
|
|
3539
|
+
modelDeployArgs,
|
|
3540
|
+
filtered: remainingArgs.includes('--filter') || remainingArgs.includes('--filter-role'),
|
|
3541
|
+
verbose: remainingArgs.includes('--verbose') || remainingArgs.includes('-v'),
|
|
3542
|
+
});
|
|
3543
|
+
if (wrapperValidation)
|
|
3544
|
+
return wrapperValidation;
|
|
3545
|
+
}
|
|
3559
3546
|
}
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
const wrapperValidation = await validateDeployedModelWrappers({
|
|
3565
|
-
provider: normalizeProviderDefinitionId(provider) ?? provider,
|
|
3566
|
-
target,
|
|
3567
|
-
frameworkRoot,
|
|
3568
|
-
modelDeployArgs,
|
|
3569
|
-
filtered: remainingArgs.includes('--filter') || remainingArgs.includes('--filter-role'),
|
|
3570
|
-
verbose: remainingArgs.includes('--verbose') || remainingArgs.includes('-v'),
|
|
3571
|
-
});
|
|
3572
|
-
if (wrapperValidation)
|
|
3573
|
-
return wrapperValidation;
|
|
3574
|
-
}
|
|
3547
|
+
await selectAddonProfile({
|
|
3548
|
+
addonSource, framework, target, args: remainingArgs,
|
|
3549
|
+
dryRunAddon, bulkIntent: _isBulkIntent, signal: ctx.signal,
|
|
3550
|
+
});
|
|
3575
3551
|
ui.blank();
|
|
3576
3552
|
ui.success(dryRunAddon
|
|
3577
3553
|
? `${framework} addon activation preview complete`
|
package/dist/src/cli/ui.js
CHANGED
|
@@ -44,6 +44,7 @@ export function success(msg) {
|
|
|
44
44
|
console.log(isTTY ? chalk.hex(SUCCESS_HEX)(` ✓ ${msg}`) : ` OK ${msg}`);
|
|
45
45
|
}
|
|
46
46
|
export function error(msg) {
|
|
47
|
+
msg = msg.trimStart();
|
|
47
48
|
console.error(isTTY ? chalk.red(` ✗ ${msg}`) : ` ERROR ${msg}`);
|
|
48
49
|
}
|
|
49
50
|
export function warn(msg) {
|