@aiwg/cli 2026.10.9 → 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/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/use-addon-profile.js +72 -0
- package/dist/src/cli/handlers/use.js +191 -230
- 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/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/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';
|
|
@@ -2687,7 +2689,7 @@ export class UseHandler {
|
|
|
2687
2689
|
}
|
|
2688
2690
|
let coreResult;
|
|
2689
2691
|
try {
|
|
2690
|
-
coreResult = await this.executeCore({ ...ctx, args: coreArgs });
|
|
2692
|
+
coreResult = await this.executeCore({ ...ctx, args: coreArgs }, providers);
|
|
2691
2693
|
}
|
|
2692
2694
|
catch (error) {
|
|
2693
2695
|
coreResult = { exitCode: 1, message: error instanceof Error ? error.message : String(error) };
|
|
@@ -2822,7 +2824,7 @@ export class UseHandler {
|
|
|
2822
2824
|
message: [coreResult.message, rendered, ...(previewActions ? [...previewActions].sort() : [])].filter(Boolean).join('\n'),
|
|
2823
2825
|
};
|
|
2824
2826
|
}
|
|
2825
|
-
async executeCore(ctx) {
|
|
2827
|
+
async executeCore(ctx, resolvedProviders) {
|
|
2826
2828
|
const explicitTarget = firstUsePositional(ctx.args);
|
|
2827
2829
|
if (ctx.args.includes('--workspace-signals')) {
|
|
2828
2830
|
const signalArgs = ctx.args.filter((a) => a !== '--workspace-signals');
|
|
@@ -2989,6 +2991,13 @@ export class UseHandler {
|
|
|
2989
2991
|
|| remainingArgs.includes('--yes')
|
|
2990
2992
|
|| remainingArgs.includes('-y')
|
|
2991
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
|
+
}
|
|
2992
3001
|
if (!config) {
|
|
2993
3002
|
if (_providersValue) {
|
|
2994
3003
|
// --providers shorthand: write config without wizard
|
|
@@ -3306,6 +3315,15 @@ export class UseHandler {
|
|
|
3306
3315
|
message: totalFailed > 0 ? `${totalFailed} project-local deploy(s) failed` : '',
|
|
3307
3316
|
};
|
|
3308
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
|
+
}
|
|
3309
3327
|
return {
|
|
3310
3328
|
exitCode: 1,
|
|
3311
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.`,
|
|
@@ -3316,7 +3334,8 @@ export class UseHandler {
|
|
|
3316
3334
|
if (isAddon || isExtension) {
|
|
3317
3335
|
const providerIdx = remainingArgs.findIndex(a => a === '--provider' || a === '--platform');
|
|
3318
3336
|
const explicitAddonProvider = providerIdx >= 0 && remainingArgs[providerIdx + 1] ? remainingArgs[providerIdx + 1] : null;
|
|
3319
|
-
const
|
|
3337
|
+
const providers = resolvedProviders ?? [...new Set(configuredGlobalProviders(remainingArgs, config)
|
|
3338
|
+
.map(provider => resolveBuiltInProviderForUse(provider).provider))];
|
|
3320
3339
|
const targetIdx = remainingArgs.findIndex(a => a === '--target');
|
|
3321
3340
|
const target = targetIdx >= 0 && remainingArgs[targetIdx + 1] ? remainingArgs[targetIdx + 1] : process.cwd();
|
|
3322
3341
|
const dryRunAddon = remainingArgs.includes('--dry-run');
|
|
@@ -3329,264 +3348,206 @@ export class UseHandler {
|
|
|
3329
3348
|
catch (error) {
|
|
3330
3349
|
return { exitCode: 1, message: `Error: ${error instanceof Error ? error.message : String(error)}` };
|
|
3331
3350
|
}
|
|
3332
|
-
if (addonScope === 'user' && !USER_SCOPE_PATHS[provider]) {
|
|
3333
|
-
return {
|
|
3334
|
-
exitCode: 1,
|
|
3335
|
-
message: `--scope user not supported for provider '${provider}' — see docs/customization/user-scope-deployment.md for the supported list`,
|
|
3336
|
-
};
|
|
3337
|
-
}
|
|
3338
|
-
const runner = createUseScriptRunner(frameworkRoot);
|
|
3339
|
-
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
3340
|
-
if (remainingArgs.includes('--allow-over-budget'))
|
|
3341
|
-
addonBaseArgs.push('--allow-over-budget');
|
|
3342
|
-
if (addonScope === 'user')
|
|
3343
|
-
addonBaseArgs.push('--scope', 'user');
|
|
3344
|
-
// An explicitly selected upstream addon must be self-contained in the
|
|
3345
|
-
// project. Unlike a full framework deploy, its standard skills cannot be
|
|
3346
|
-
// left index-only: the user asked to install this specific bundle and
|
|
3347
|
-
// its supporting scripts must travel with the skill directory.
|
|
3348
|
-
addonBaseArgs.push('--copy-all');
|
|
3349
|
-
addonBaseArgs.push(...modelDeployArgs);
|
|
3350
|
-
if (provider)
|
|
3351
|
-
addonBaseArgs.push('--provider', provider);
|
|
3352
|
-
if (target)
|
|
3353
|
-
addonBaseArgs.push('--target', target);
|
|
3354
|
-
// Forward --copy-all (#1219) so addon-only deploys also honor it.
|
|
3355
|
-
if ((remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills'))
|
|
3356
|
-
&& !addonBaseArgs.includes('--copy-all')) {
|
|
3357
|
-
addonBaseArgs.push('--copy-all');
|
|
3358
|
-
}
|
|
3359
|
-
if (dryRunAddon)
|
|
3360
|
-
addonBaseArgs.push('--dry-run');
|
|
3361
|
-
if (remainingArgs.includes('--force'))
|
|
3362
|
-
addonBaseArgs.push('--force');
|
|
3363
3351
|
const kind = isExtension ? 'extension' : 'addon';
|
|
3364
|
-
const
|
|
3365
|
-
?
|
|
3366
|
-
:
|
|
3367
|
-
|
|
3368
|
-
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
|
+
}
|
|
3369
3437
|
ui.blank();
|
|
3370
|
-
ui.header(` Deploying
|
|
3371
|
-
const
|
|
3372
|
-
|
|
3373
|
-
'--quiet', '--source', dependencySource,
|
|
3438
|
+
ui.header(` Deploying ${framework} ${kind}...`);
|
|
3439
|
+
const addonResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3440
|
+
'--quiet', '--source', addonSource,
|
|
3374
3441
|
...addonBaseArgs,
|
|
3375
3442
|
], { capture: true });
|
|
3376
|
-
if (
|
|
3377
|
-
return
|
|
3378
|
-
...dependencyResult,
|
|
3379
|
-
message: dependencyResult.message
|
|
3380
|
-
|| `Failed to deploy required addon '${dependency}'`,
|
|
3381
|
-
};
|
|
3443
|
+
if (addonResult.exitCode !== 0) {
|
|
3444
|
+
return addonResult;
|
|
3382
3445
|
}
|
|
3383
3446
|
if (!dryRunAddon) {
|
|
3384
3447
|
try {
|
|
3385
|
-
await reconcileDeployedSkillAssets(
|
|
3448
|
+
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3386
3449
|
}
|
|
3387
3450
|
catch (error) {
|
|
3388
3451
|
return {
|
|
3389
3452
|
exitCode: 1,
|
|
3390
|
-
message:
|
|
3453
|
+
message: `${kind} '${framework}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3391
3454
|
};
|
|
3392
3455
|
}
|
|
3393
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
|
|
3394
3486
|
try {
|
|
3395
3487
|
await registerSourceCliCommands({
|
|
3396
|
-
source:
|
|
3488
|
+
source: addonSource,
|
|
3397
3489
|
target,
|
|
3398
3490
|
provider,
|
|
3399
3491
|
dryRun: dryRunAddon,
|
|
3400
|
-
fallbackDescription: `${
|
|
3492
|
+
fallbackDescription: `${framework} addon commands`,
|
|
3401
3493
|
});
|
|
3402
3494
|
}
|
|
3403
3495
|
catch (error) {
|
|
3404
3496
|
return {
|
|
3405
3497
|
exitCode: 1,
|
|
3406
|
-
message: `Failed to register
|
|
3498
|
+
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3407
3499
|
};
|
|
3408
3500
|
}
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
}
|
|
3413
|
-
ui.blank();
|
|
3414
|
-
ui.header(` Deploying ${framework} ${kind}...`);
|
|
3415
|
-
const addonSource = isExtension
|
|
3416
|
-
? extensionPath(frameworkRoot, framework)
|
|
3417
|
-
: addonPath(frameworkRoot, framework);
|
|
3418
|
-
const addonResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3419
|
-
'--quiet', '--source', addonSource,
|
|
3420
|
-
...addonBaseArgs,
|
|
3421
|
-
], { capture: true });
|
|
3422
|
-
if (addonResult.exitCode !== 0) {
|
|
3423
|
-
return addonResult;
|
|
3424
|
-
}
|
|
3425
|
-
if (!dryRunAddon) {
|
|
3426
|
-
try {
|
|
3427
|
-
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3428
|
-
}
|
|
3429
|
-
catch (error) {
|
|
3430
|
-
return {
|
|
3431
|
-
exitCode: 1,
|
|
3432
|
-
message: `${kind} '${framework}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3433
|
-
};
|
|
3434
|
-
}
|
|
3435
|
-
}
|
|
3436
|
-
if (!dryRunAddon && provider === 'omp' && (detectScope(remainingArgs) === 'user' || remainingArgs.includes('--user'))) {
|
|
3437
|
-
try {
|
|
3438
|
-
await deployOmpUserSource({ frameworkRoot, source: addonSource, target, bundle: framework, copyAll: true });
|
|
3439
|
-
}
|
|
3440
|
-
catch (error) {
|
|
3441
|
-
return { exitCode: 1, message: `OMP user deployment failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3442
|
-
}
|
|
3443
|
-
}
|
|
3444
|
-
// Register only artifacts actually written by a confirmed deployment.
|
|
3445
|
-
if (!dryRunAddon) {
|
|
3446
|
-
try {
|
|
3447
|
-
const registry = getRegistry();
|
|
3448
|
-
const paths = getProviderPaths(provider);
|
|
3449
|
-
await registerDeployedExtensions(registry, {
|
|
3450
|
-
agentsPath: paths.agents,
|
|
3451
|
-
skillsPath: paths.skills,
|
|
3452
|
-
commandsPath: paths.commands,
|
|
3453
|
-
rulesPath: paths.rules,
|
|
3454
|
-
behaviorsPath: paths.behaviors,
|
|
3455
|
-
provider,
|
|
3456
|
-
cwd: target,
|
|
3457
|
-
});
|
|
3458
|
-
ui.success('Extension registration complete');
|
|
3459
|
-
}
|
|
3460
|
-
catch (error) {
|
|
3461
|
-
ui.warn(`Failed to register extensions: ${error instanceof Error ? error.message : String(error)}`);
|
|
3462
|
-
}
|
|
3463
|
-
}
|
|
3464
|
-
// Register CLI commands if addon declares them
|
|
3465
|
-
try {
|
|
3466
|
-
await registerSourceCliCommands({
|
|
3467
|
-
source: addonSource,
|
|
3468
|
-
target,
|
|
3469
|
-
provider,
|
|
3470
|
-
dryRun: dryRunAddon,
|
|
3471
|
-
fallbackDescription: `${framework} addon commands`,
|
|
3472
|
-
});
|
|
3473
|
-
}
|
|
3474
|
-
catch (error) {
|
|
3475
|
-
return {
|
|
3476
|
-
exitCode: 1,
|
|
3477
|
-
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3478
|
-
};
|
|
3479
|
-
}
|
|
3480
|
-
if (!dryRunAddon && (provider === 'openclaw' || (provider === 'grokbot' && addonScope === 'user'))) {
|
|
3481
|
-
try {
|
|
3482
|
-
await recordNativeAddonDeploy(addonSource, target, provider, framework);
|
|
3483
|
-
}
|
|
3484
|
-
catch (error) {
|
|
3485
|
-
return { exitCode: 1, message: `Addon user registry update failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
// Persist the same lifecycle record frameworks and project-local bundles
|
|
3489
|
-
// receive so status, refresh, doctor, and remove can account for this
|
|
3490
|
-
// upstream addon and every provider artifact it actually deployed.
|
|
3491
|
-
if (!dryRunAddon && config) {
|
|
3492
|
-
try {
|
|
3493
|
-
const manifestPath = path.join(addonSource, 'manifest.json');
|
|
3494
|
-
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
3495
|
-
// Provider rule aggregation may rename many source rules into one
|
|
3496
|
-
// managed index. Record this addon's contributed artifact counts,
|
|
3497
|
-
// matching framework registry semantics, rather than trying to
|
|
3498
|
-
// attribute shared aggregate filenames after deployment.
|
|
3499
|
-
const counts = await countBundleSourceArtifacts(addonSource);
|
|
3500
|
-
const updated = updateInstalled(config, framework, provider, counts, {
|
|
3501
|
-
version: manifest.version ?? (await getVersionInfo()).version,
|
|
3502
|
-
source: 'bundled',
|
|
3503
|
-
manifestHash: await hashManifest(manifestPath),
|
|
3504
|
-
asPrimary: Boolean(explicitAddonProvider),
|
|
3505
|
-
});
|
|
3506
|
-
await writeAiwgConfig(projectDir, updated);
|
|
3507
|
-
config = updated;
|
|
3508
|
-
}
|
|
3509
|
-
catch (error) {
|
|
3510
|
-
ui.warn(`Addon registry update failed for '${framework}': ${error instanceof Error ? error.message : String(error)}`);
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
// Profile picker for addons with memory topology and multiple templates
|
|
3514
|
-
try {
|
|
3515
|
-
const profileManifestPath = path.join(addonSource, 'manifest.json');
|
|
3516
|
-
const profileManifestContent = await fs.readFile(profileManifestPath, 'utf-8');
|
|
3517
|
-
const profileManifest = JSON.parse(profileManifestContent);
|
|
3518
|
-
const topology = profileManifest.memory?.topology;
|
|
3519
|
-
const templates = profileManifest.templates;
|
|
3520
|
-
if (topology && templates && templates.length > 1) {
|
|
3521
|
-
const profileIdx = remainingArgs.findIndex(a => a === '--profile');
|
|
3522
|
-
let selectedProfile;
|
|
3523
|
-
if (profileIdx >= 0 && remainingArgs[profileIdx + 1]) {
|
|
3524
|
-
// Explicit --profile flag
|
|
3525
|
-
selectedProfile = remainingArgs[profileIdx + 1];
|
|
3526
|
-
const templateFile = templates.find((t) => t.replace('.md', '') === selectedProfile || t === selectedProfile);
|
|
3527
|
-
if (!templateFile) {
|
|
3528
|
-
ui.warn(`Unknown profile "${selectedProfile}". Available: ${templates.map((t) => t.replace('.md', '')).join(', ')}`);
|
|
3529
|
-
selectedProfile = undefined;
|
|
3530
|
-
}
|
|
3501
|
+
if (!dryRunAddon && (provider === 'openclaw' || (provider === 'grokbot' && addonScope === 'user'))) {
|
|
3502
|
+
try {
|
|
3503
|
+
await recordNativeAddonDeploy(addonSource, target, provider, framework);
|
|
3531
3504
|
}
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
// The profile picker is annoying during `aiwg use all`.
|
|
3535
|
-
selectedProfile = 'generic';
|
|
3505
|
+
catch (error) {
|
|
3506
|
+
return { exitCode: 1, message: `Addon user registry update failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3536
3507
|
}
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
const
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
}
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
}
|
|
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;
|
|
3559
3529
|
}
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
const namespace = topology.namespace || `.aiwg/${framework}`;
|
|
3563
|
-
const configDir = path.join(target, namespace);
|
|
3564
|
-
await fs.mkdir(configDir, { recursive: true });
|
|
3565
|
-
const profileConfig = {
|
|
3566
|
-
profile: selectedProfile,
|
|
3567
|
-
pageTemplate: `templates/${selectedProfile}.md`,
|
|
3568
|
-
selectedAt: new Date().toISOString(),
|
|
3569
|
-
};
|
|
3570
|
-
await fs.writeFile(path.join(configDir, 'config.json'), JSON.stringify(profileConfig, null, 2) + '\n');
|
|
3571
|
-
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)}`);
|
|
3572
3532
|
}
|
|
3573
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
|
+
}
|
|
3574
3546
|
}
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
const wrapperValidation = await validateDeployedModelWrappers({
|
|
3580
|
-
provider: normalizeProviderDefinitionId(provider) ?? provider,
|
|
3581
|
-
target,
|
|
3582
|
-
frameworkRoot,
|
|
3583
|
-
modelDeployArgs,
|
|
3584
|
-
filtered: remainingArgs.includes('--filter') || remainingArgs.includes('--filter-role'),
|
|
3585
|
-
verbose: remainingArgs.includes('--verbose') || remainingArgs.includes('-v'),
|
|
3586
|
-
});
|
|
3587
|
-
if (wrapperValidation)
|
|
3588
|
-
return wrapperValidation;
|
|
3589
|
-
}
|
|
3547
|
+
await selectAddonProfile({
|
|
3548
|
+
addonSource, framework, target, args: remainingArgs,
|
|
3549
|
+
dryRunAddon, bulkIntent: _isBulkIntent, signal: ctx.signal,
|
|
3550
|
+
});
|
|
3590
3551
|
ui.blank();
|
|
3591
3552
|
ui.success(dryRunAddon
|
|
3592
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) {
|