@aiwg/cli 2026.10.9 → 2026.10.11
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 +275 -17
- 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/sessions.js +198 -15
- package/dist/src/cli/handlers/use-addon-profile.js +72 -0
- package/dist/src/cli/handlers/use.js +203 -234
- 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-context.js +337 -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 +114 -16
- 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 +275 -17
- package/dist/src/models/provider-policy.js +14 -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/policy/authorization.js +29 -1
- package/dist/src/process/aiwg-probe-command.d.mts +15 -0
- package/dist/src/process/aiwg-probe-command.mjs +37 -0
- 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/sessions/adapters/grokbot.js +7 -0
- package/dist/src/sessions/batch-import.js +34 -6
- package/dist/src/sessions/contracts.js +19 -0
- package/dist/src/sessions/coverage-preflight.js +7 -1
- package/dist/src/sessions/fortemi-export-mapping.js +33 -3
- package/dist/src/sessions/host-catalog.js +157 -0
- package/dist/src/sessions/image-blobs.js +141 -0
- package/dist/src/sessions/importer.js +23 -3
- package/dist/src/sessions/index.js +2 -0
- package/dist/src/sessions/refresh.js +25 -2
- package/dist/src/sessions/repository.js +164 -22
- package/dist/src/sessions/workspace-discovery.js +5 -2
- package/dist/src/smiths/context-pipeline/parallelism-section.js +19 -7
- package/package.json +15 -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/muse-adapter.mjs +10 -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-context.mjs +237 -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-invocation-ancestry.mjs +132 -0
- package/tools/ralph-external/lib/worker-invocation-processes.mjs +123 -0
- package/tools/ralph-external/lib/worker-isolation-status.mjs +48 -0
- package/tools/ralph-external/lib/worker-isolation.mjs +19 -73
- package/tools/ralph-external/lib/worker-launch-cli.mjs +49 -0
- package/tools/ralph-external/lib/worker-native-sandbox.mjs +83 -0
- package/tools/ralph-external/lib/worker-overflow.mjs +48 -13
- package/tools/ralph-external/lib/worker-retry-evidence.mjs +103 -0
- package/tools/ralph-external/lib/worker-termination.mjs +82 -0
- package/tools/ralph-external/session-launcher.mjs +124 -313
- 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 { appendGitignore } from '../../config/gitignore.js';
|
|
31
|
+
import { readAiwgConfig, writeAiwgConfig, updateInstalled, hashManifest, emptyConfig, getProjectDir, getConfigPath } from '../../config/aiwg-config.js';
|
|
32
|
+
import { AIWG_RUNTIME_PATTERNS, 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';
|
|
@@ -499,11 +501,19 @@ function getProviderKernelSkillsPath(provider) {
|
|
|
499
501
|
const PROVIDER_GENERATED_GITIGNORE_PATTERNS = {
|
|
500
502
|
codex: ['.codex/', '.agents/'],
|
|
501
503
|
};
|
|
502
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Patterns `aiwg use` ensures in the project's .gitignore on every deploy:
|
|
506
|
+
* the AIWG runtime subdirs doctor expects, plus any provider-generated dirs.
|
|
507
|
+
* Append-only via appendGitignore — operator content is never rewritten (#3635).
|
|
508
|
+
*/
|
|
509
|
+
export function gitignorePatternsForDeploy(provider) {
|
|
510
|
+
return [...AIWG_RUNTIME_PATTERNS, ...(PROVIDER_GENERATED_GITIGNORE_PATTERNS[provider] ?? [])];
|
|
511
|
+
}
|
|
512
|
+
export async function ensureProviderGeneratedDirsIgnored(projectRoot, provider, opts) {
|
|
503
513
|
if (opts.dryRun)
|
|
504
514
|
return;
|
|
505
|
-
const patterns =
|
|
506
|
-
if (
|
|
515
|
+
const patterns = gitignorePatternsForDeploy(provider);
|
|
516
|
+
if (patterns.length === 0)
|
|
507
517
|
return;
|
|
508
518
|
try {
|
|
509
519
|
const result = await appendGitignore(projectRoot, patterns);
|
|
@@ -2687,7 +2697,7 @@ export class UseHandler {
|
|
|
2687
2697
|
}
|
|
2688
2698
|
let coreResult;
|
|
2689
2699
|
try {
|
|
2690
|
-
coreResult = await this.executeCore({ ...ctx, args: coreArgs });
|
|
2700
|
+
coreResult = await this.executeCore({ ...ctx, args: coreArgs }, providers);
|
|
2691
2701
|
}
|
|
2692
2702
|
catch (error) {
|
|
2693
2703
|
coreResult = { exitCode: 1, message: error instanceof Error ? error.message : String(error) };
|
|
@@ -2822,7 +2832,7 @@ export class UseHandler {
|
|
|
2822
2832
|
message: [coreResult.message, rendered, ...(previewActions ? [...previewActions].sort() : [])].filter(Boolean).join('\n'),
|
|
2823
2833
|
};
|
|
2824
2834
|
}
|
|
2825
|
-
async executeCore(ctx) {
|
|
2835
|
+
async executeCore(ctx, resolvedProviders) {
|
|
2826
2836
|
const explicitTarget = firstUsePositional(ctx.args);
|
|
2827
2837
|
if (ctx.args.includes('--workspace-signals')) {
|
|
2828
2838
|
const signalArgs = ctx.args.filter((a) => a !== '--workspace-signals');
|
|
@@ -2989,6 +2999,13 @@ export class UseHandler {
|
|
|
2989
2999
|
|| remainingArgs.includes('--yes')
|
|
2990
3000
|
|| remainingArgs.includes('-y')
|
|
2991
3001
|
|| remainingArgs.includes('--non-interactive');
|
|
3002
|
+
// An auto-created config is removed again if the target turns out to be unknown,
|
|
3003
|
+
// so a mistyped `aiwg use <name>` leaves the project untouched.
|
|
3004
|
+
let autoCreatedConfig = null;
|
|
3005
|
+
if (!config && !_isDryRun) {
|
|
3006
|
+
const configPath = getConfigPath(projectDir);
|
|
3007
|
+
autoCreatedConfig = { path: configPath, controlDirExisted: existsSync(path.dirname(configPath)) };
|
|
3008
|
+
}
|
|
2992
3009
|
if (!config) {
|
|
2993
3010
|
if (_providersValue) {
|
|
2994
3011
|
// --providers shorthand: write config without wizard
|
|
@@ -3306,6 +3323,15 @@ export class UseHandler {
|
|
|
3306
3323
|
message: totalFailed > 0 ? `${totalFailed} project-local deploy(s) failed` : '',
|
|
3307
3324
|
};
|
|
3308
3325
|
}
|
|
3326
|
+
if (autoCreatedConfig) {
|
|
3327
|
+
rmSync(autoCreatedConfig.path, { force: true });
|
|
3328
|
+
if (!autoCreatedConfig.controlDirExisted) {
|
|
3329
|
+
try {
|
|
3330
|
+
rmdirSync(path.dirname(autoCreatedConfig.path));
|
|
3331
|
+
}
|
|
3332
|
+
catch { /* not empty or already gone */ }
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3309
3335
|
return {
|
|
3310
3336
|
exitCode: 1,
|
|
3311
3337
|
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 +3342,8 @@ export class UseHandler {
|
|
|
3316
3342
|
if (isAddon || isExtension) {
|
|
3317
3343
|
const providerIdx = remainingArgs.findIndex(a => a === '--provider' || a === '--platform');
|
|
3318
3344
|
const explicitAddonProvider = providerIdx >= 0 && remainingArgs[providerIdx + 1] ? remainingArgs[providerIdx + 1] : null;
|
|
3319
|
-
const
|
|
3345
|
+
const providers = resolvedProviders ?? [...new Set(configuredGlobalProviders(remainingArgs, config)
|
|
3346
|
+
.map(provider => resolveBuiltInProviderForUse(provider).provider))];
|
|
3320
3347
|
const targetIdx = remainingArgs.findIndex(a => a === '--target');
|
|
3321
3348
|
const target = targetIdx >= 0 && remainingArgs[targetIdx + 1] ? remainingArgs[targetIdx + 1] : process.cwd();
|
|
3322
3349
|
const dryRunAddon = remainingArgs.includes('--dry-run');
|
|
@@ -3329,264 +3356,206 @@ export class UseHandler {
|
|
|
3329
3356
|
catch (error) {
|
|
3330
3357
|
return { exitCode: 1, message: `Error: ${error instanceof Error ? error.message : String(error)}` };
|
|
3331
3358
|
}
|
|
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
3359
|
const kind = isExtension ? 'extension' : 'addon';
|
|
3364
|
-
const
|
|
3365
|
-
?
|
|
3366
|
-
:
|
|
3367
|
-
|
|
3368
|
-
for (const
|
|
3360
|
+
const addonSource = isExtension
|
|
3361
|
+
? extensionPath(frameworkRoot, framework)
|
|
3362
|
+
: addonPath(frameworkRoot, framework);
|
|
3363
|
+
// Deploy, reconcile, and record exactly the provider set verification checks.
|
|
3364
|
+
for (const provider of providers) {
|
|
3365
|
+
if (addonScope === 'user' && !USER_SCOPE_PATHS[provider]) {
|
|
3366
|
+
return {
|
|
3367
|
+
exitCode: 1,
|
|
3368
|
+
message: `--scope user not supported for provider '${provider}' — see docs/customization/user-scope-deployment.md for the supported list`,
|
|
3369
|
+
};
|
|
3370
|
+
}
|
|
3371
|
+
const runner = createUseScriptRunner(frameworkRoot);
|
|
3372
|
+
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
3373
|
+
if (remainingArgs.includes('--allow-over-budget'))
|
|
3374
|
+
addonBaseArgs.push('--allow-over-budget');
|
|
3375
|
+
if (addonScope === 'user')
|
|
3376
|
+
addonBaseArgs.push('--scope', 'user');
|
|
3377
|
+
// An explicitly selected upstream addon must be self-contained in the
|
|
3378
|
+
// project. Unlike a full framework deploy, its standard skills cannot be
|
|
3379
|
+
// left index-only: the user asked to install this specific bundle and
|
|
3380
|
+
// its supporting scripts must travel with the skill directory.
|
|
3381
|
+
addonBaseArgs.push('--copy-all');
|
|
3382
|
+
addonBaseArgs.push(...modelDeployArgs);
|
|
3383
|
+
if (provider)
|
|
3384
|
+
addonBaseArgs.push('--provider', provider);
|
|
3385
|
+
if (target)
|
|
3386
|
+
addonBaseArgs.push('--target', target);
|
|
3387
|
+
// Forward --copy-all (#1219) so addon-only deploys also honor it.
|
|
3388
|
+
if ((remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills'))
|
|
3389
|
+
&& !addonBaseArgs.includes('--copy-all')) {
|
|
3390
|
+
addonBaseArgs.push('--copy-all');
|
|
3391
|
+
}
|
|
3392
|
+
if (dryRunAddon)
|
|
3393
|
+
addonBaseArgs.push('--dry-run');
|
|
3394
|
+
if (remainingArgs.includes('--force'))
|
|
3395
|
+
addonBaseArgs.push('--force');
|
|
3396
|
+
const activationOrder = isAddon
|
|
3397
|
+
? await resolveRequiredAddonActivationOrder(frameworkRoot, framework)
|
|
3398
|
+
: [framework];
|
|
3399
|
+
const requiredAddons = activationOrder.slice(0, -1);
|
|
3400
|
+
for (const dependency of requiredAddons) {
|
|
3401
|
+
ui.blank();
|
|
3402
|
+
ui.header(` Deploying required ${dependency} addon...`);
|
|
3403
|
+
const dependencySource = addonPath(frameworkRoot, dependency);
|
|
3404
|
+
const dependencyResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3405
|
+
'--quiet', '--source', dependencySource,
|
|
3406
|
+
...addonBaseArgs,
|
|
3407
|
+
], { capture: true });
|
|
3408
|
+
if (dependencyResult.exitCode !== 0) {
|
|
3409
|
+
return {
|
|
3410
|
+
...dependencyResult,
|
|
3411
|
+
message: dependencyResult.message
|
|
3412
|
+
|| `Failed to deploy required addon '${dependency}'`,
|
|
3413
|
+
};
|
|
3414
|
+
}
|
|
3415
|
+
if (!dryRunAddon) {
|
|
3416
|
+
try {
|
|
3417
|
+
await reconcileDeployedSkillAssets(dependencySource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3418
|
+
}
|
|
3419
|
+
catch (error) {
|
|
3420
|
+
return {
|
|
3421
|
+
exitCode: 1,
|
|
3422
|
+
message: `Required addon '${dependency}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3423
|
+
};
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
try {
|
|
3427
|
+
await registerSourceCliCommands({
|
|
3428
|
+
source: dependencySource,
|
|
3429
|
+
target,
|
|
3430
|
+
provider,
|
|
3431
|
+
dryRun: dryRunAddon,
|
|
3432
|
+
fallbackDescription: `${dependency} addon commands`,
|
|
3433
|
+
});
|
|
3434
|
+
}
|
|
3435
|
+
catch (error) {
|
|
3436
|
+
return {
|
|
3437
|
+
exitCode: 1,
|
|
3438
|
+
message: `Failed to register required addon '${dependency}' CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
ui.success(dryRunAddon
|
|
3442
|
+
? `Required ${dependency} addon activation previewed`
|
|
3443
|
+
: `Required ${dependency} addon deployed`);
|
|
3444
|
+
}
|
|
3369
3445
|
ui.blank();
|
|
3370
|
-
ui.header(` Deploying
|
|
3371
|
-
const
|
|
3372
|
-
|
|
3373
|
-
'--quiet', '--source', dependencySource,
|
|
3446
|
+
ui.header(` Deploying ${framework} ${kind}...`);
|
|
3447
|
+
const addonResult = await runner.run('tools/agents/deploy-agents.mjs', [
|
|
3448
|
+
'--quiet', '--source', addonSource,
|
|
3374
3449
|
...addonBaseArgs,
|
|
3375
3450
|
], { capture: true });
|
|
3376
|
-
if (
|
|
3377
|
-
return
|
|
3378
|
-
...dependencyResult,
|
|
3379
|
-
message: dependencyResult.message
|
|
3380
|
-
|| `Failed to deploy required addon '${dependency}'`,
|
|
3381
|
-
};
|
|
3451
|
+
if (addonResult.exitCode !== 0) {
|
|
3452
|
+
return addonResult;
|
|
3382
3453
|
}
|
|
3383
3454
|
if (!dryRunAddon) {
|
|
3384
3455
|
try {
|
|
3385
|
-
await reconcileDeployedSkillAssets(
|
|
3456
|
+
await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false, force: remainingArgs.includes('--force') });
|
|
3386
3457
|
}
|
|
3387
3458
|
catch (error) {
|
|
3388
3459
|
return {
|
|
3389
3460
|
exitCode: 1,
|
|
3390
|
-
message:
|
|
3461
|
+
message: `${kind} '${framework}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3391
3462
|
};
|
|
3392
3463
|
}
|
|
3393
3464
|
}
|
|
3465
|
+
if (!dryRunAddon && provider === 'omp' && (detectScope(remainingArgs) === 'user' || remainingArgs.includes('--user'))) {
|
|
3466
|
+
try {
|
|
3467
|
+
await deployOmpUserSource({ frameworkRoot, source: addonSource, target, bundle: framework, copyAll: true });
|
|
3468
|
+
}
|
|
3469
|
+
catch (error) {
|
|
3470
|
+
return { exitCode: 1, message: `OMP user deployment failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
// Register only artifacts actually written by a confirmed deployment.
|
|
3474
|
+
if (!dryRunAddon) {
|
|
3475
|
+
try {
|
|
3476
|
+
const registry = getRegistry();
|
|
3477
|
+
const paths = getProviderPaths(provider);
|
|
3478
|
+
await registerDeployedExtensions(registry, {
|
|
3479
|
+
agentsPath: paths.agents,
|
|
3480
|
+
skillsPath: paths.skills,
|
|
3481
|
+
commandsPath: paths.commands,
|
|
3482
|
+
rulesPath: paths.rules,
|
|
3483
|
+
behaviorsPath: paths.behaviors,
|
|
3484
|
+
provider,
|
|
3485
|
+
cwd: target,
|
|
3486
|
+
});
|
|
3487
|
+
ui.success('Extension registration complete');
|
|
3488
|
+
}
|
|
3489
|
+
catch (error) {
|
|
3490
|
+
ui.warn(`Failed to register extensions: ${error instanceof Error ? error.message : String(error)}`);
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
// Register CLI commands if addon declares them
|
|
3394
3494
|
try {
|
|
3395
3495
|
await registerSourceCliCommands({
|
|
3396
|
-
source:
|
|
3496
|
+
source: addonSource,
|
|
3397
3497
|
target,
|
|
3398
3498
|
provider,
|
|
3399
3499
|
dryRun: dryRunAddon,
|
|
3400
|
-
fallbackDescription: `${
|
|
3500
|
+
fallbackDescription: `${framework} addon commands`,
|
|
3401
3501
|
});
|
|
3402
3502
|
}
|
|
3403
3503
|
catch (error) {
|
|
3404
3504
|
return {
|
|
3405
3505
|
exitCode: 1,
|
|
3406
|
-
message: `Failed to register
|
|
3407
|
-
};
|
|
3408
|
-
}
|
|
3409
|
-
ui.success(dryRunAddon
|
|
3410
|
-
? `Required ${dependency} addon activation previewed`
|
|
3411
|
-
: `Required ${dependency} addon deployed`);
|
|
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)}`,
|
|
3506
|
+
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
3433
3507
|
};
|
|
3434
3508
|
}
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
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
|
-
}
|
|
3509
|
+
if (!dryRunAddon && (provider === 'openclaw' || (provider === 'grokbot' && addonScope === 'user'))) {
|
|
3510
|
+
try {
|
|
3511
|
+
await recordNativeAddonDeploy(addonSource, target, provider, framework);
|
|
3531
3512
|
}
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
// The profile picker is annoying during `aiwg use all`.
|
|
3535
|
-
selectedProfile = 'generic';
|
|
3513
|
+
catch (error) {
|
|
3514
|
+
return { exitCode: 1, message: `Addon user registry update failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3536
3515
|
}
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
const
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
}
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
}
|
|
3516
|
+
}
|
|
3517
|
+
// Persist the same lifecycle record frameworks and project-local bundles
|
|
3518
|
+
// receive so status, refresh, doctor, and remove can account for this
|
|
3519
|
+
// upstream addon and every provider artifact it actually deployed.
|
|
3520
|
+
if (!dryRunAddon && config) {
|
|
3521
|
+
try {
|
|
3522
|
+
const manifestPath = path.join(addonSource, 'manifest.json');
|
|
3523
|
+
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
3524
|
+
// Provider rule aggregation may rename many source rules into one
|
|
3525
|
+
// managed index. Record this addon's contributed artifact counts,
|
|
3526
|
+
// matching framework registry semantics, rather than trying to
|
|
3527
|
+
// attribute shared aggregate filenames after deployment.
|
|
3528
|
+
const counts = await countBundleSourceArtifacts(addonSource);
|
|
3529
|
+
const updated = updateInstalled(config, framework, provider, counts, {
|
|
3530
|
+
version: manifest.version ?? (await getVersionInfo()).version,
|
|
3531
|
+
source: 'bundled',
|
|
3532
|
+
manifestHash: await hashManifest(manifestPath),
|
|
3533
|
+
asPrimary: Boolean(explicitAddonProvider),
|
|
3534
|
+
});
|
|
3535
|
+
await writeAiwgConfig(projectDir, updated);
|
|
3536
|
+
config = updated;
|
|
3559
3537
|
}
|
|
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`);
|
|
3538
|
+
catch (error) {
|
|
3539
|
+
ui.warn(`Addon registry update failed for '${framework}': ${error instanceof Error ? error.message : String(error)}`);
|
|
3572
3540
|
}
|
|
3573
3541
|
}
|
|
3542
|
+
if (framework === 'aiwg-utils' && !['pi', 'omp'].includes(provider) && !remainingArgs.includes('--dry-run')) {
|
|
3543
|
+
const wrapperValidation = await validateDeployedModelWrappers({
|
|
3544
|
+
provider: normalizeProviderDefinitionId(provider) ?? provider,
|
|
3545
|
+
target,
|
|
3546
|
+
frameworkRoot,
|
|
3547
|
+
modelDeployArgs,
|
|
3548
|
+
filtered: remainingArgs.includes('--filter') || remainingArgs.includes('--filter-role'),
|
|
3549
|
+
verbose: remainingArgs.includes('--verbose') || remainingArgs.includes('-v'),
|
|
3550
|
+
});
|
|
3551
|
+
if (wrapperValidation)
|
|
3552
|
+
return wrapperValidation;
|
|
3553
|
+
}
|
|
3574
3554
|
}
|
|
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
|
-
}
|
|
3555
|
+
await selectAddonProfile({
|
|
3556
|
+
addonSource, framework, target, args: remainingArgs,
|
|
3557
|
+
dryRunAddon, bulkIntent: _isBulkIntent, signal: ctx.signal,
|
|
3558
|
+
});
|
|
3590
3559
|
ui.blank();
|
|
3591
3560
|
ui.success(dryRunAddon
|
|
3592
3561
|
? `${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) {
|