@aiwg/cli 2026.8.17 → 2026.8.19
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/bin/aiwg.mjs +24 -2
- package/dist/src/a2a/agent-card.js +4 -1
- package/dist/src/a2a/client.js +148 -68
- package/dist/src/a2a/codecs.js +480 -0
- package/dist/src/a2a/events.js +226 -0
- package/dist/src/a2a/hitl-driver.js +8 -6
- package/dist/src/a2a/hitl.js +2 -1
- package/dist/src/a2a/http.js +85 -5
- package/dist/src/a2a/protocol.js +136 -0
- package/dist/src/a2a/types.js +4 -14
- package/dist/src/a2a/webhook.js +101 -4
- package/dist/src/artifacts/index-builder.js +63 -12
- package/dist/src/artifacts/index-files.js +26 -5
- package/dist/src/artifacts/query-engine.js +67 -67
- package/dist/src/artifacts/stats.js +6 -2
- package/dist/src/artifacts/types.js +1 -1
- package/dist/src/audit/operator-decision.js +15 -1
- package/dist/src/channel/manager.mjs +89 -17
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/installation.js +79 -0
- package/dist/src/cli/handlers/refresh.js +6 -2
- package/dist/src/cli/handlers/runtime-info.js +9 -1
- package/dist/src/cli/handlers/serve.js +107 -4
- package/dist/src/cli/handlers/session.js +12 -26
- package/dist/src/cli/handlers/use.js +19 -4
- package/dist/src/cli/handlers/utilities.js +4 -0
- package/dist/src/cli/handlers/version.js +4 -0
- package/dist/src/config/user-config-dir.mjs +29 -0
- package/dist/src/config/user-config.js +4 -22
- package/dist/src/extensions/commands/definitions.js +20 -1
- package/dist/src/features/catalog.js +2 -1
- package/dist/src/flow/graph-metadata.js +56 -0
- package/dist/src/installation/manager-command.mjs +31 -0
- package/dist/src/installation/manager.mjs +264 -0
- package/dist/src/serve/a2a-terminal-observer.js +28 -5
- package/dist/src/serve/dispatch-router.js +32 -4
- package/dist/src/serve/executor-registry.js +29 -0
- package/dist/src/serve/mission-conductor.js +15 -1
- package/dist/src/serve/stack-adapters.js +2 -1
- package/dist/src/serve/telemetry.js +5 -1
- package/dist/src/smiths/context-pipeline/claude-hook.js +8 -5
- package/dist/src/smiths/context-pipeline/line-endings.js +12 -0
- package/dist/src/smiths/context-pipeline/managed-hook.js +8 -5
- package/dist/src/smiths/context-pipeline/workspace-context.js +3 -1
- package/dist/src/update/checker.mjs +16 -15
- package/dist/src/update/notifier.mjs +8 -3
- package/dist/src/update/service.mjs +51 -5
- package/package.json +1 -1
- package/tools/agents/deploy-agents.mjs +28 -8
- package/tools/agents/providers/base.mjs +5 -3
|
@@ -14,6 +14,7 @@ import { buildNormalizedAiwgMd } from './finalization.js';
|
|
|
14
14
|
import { getProviderDefinition, listProviderDefinitions, } from '../../providers/provider-definitions.js';
|
|
15
15
|
import { readAiwgConfig } from '../../config/aiwg-config.js';
|
|
16
16
|
import { projectAiwgPath, projectControlPath, resolveProjectAiwgDir, } from '../../config/project-artifacts.js';
|
|
17
|
+
import { dominantLineEnding, withLineEnding } from './line-endings.js';
|
|
17
18
|
export const WORKSPACE_MANAGED_START = '<!-- AIWG:workspace-context:start -->';
|
|
18
19
|
export const WORKSPACE_MANAGED_END = '<!-- AIWG:workspace-context:end -->';
|
|
19
20
|
export const WORKSPACE_OPERATOR_START = '<!-- AIWG:workspace-operator:start -->';
|
|
@@ -90,7 +91,8 @@ function replaceBlock(content, start, end, block) {
|
|
|
90
91
|
return null;
|
|
91
92
|
if (startIndex < 0 || endIndex < startIndex)
|
|
92
93
|
throw new Error(`Malformed managed block: ${start} / ${end}`);
|
|
93
|
-
|
|
94
|
+
const renderedBlock = withLineEnding(block, dominantLineEnding(content));
|
|
95
|
+
return content.slice(0, startIndex) + renderedBlock + content.slice(endIndex + end.length);
|
|
94
96
|
}
|
|
95
97
|
function stripGeneratedBlocks(content) {
|
|
96
98
|
let stripped = content;
|
|
@@ -15,6 +15,7 @@ import https from 'https';
|
|
|
15
15
|
import { execSync } from 'child_process';
|
|
16
16
|
import { createInterface } from 'readline';
|
|
17
17
|
import { loadConfig, saveConfig, getChannel, getPackageRoot } from '../channel/manager.mjs';
|
|
18
|
+
import { updateInstallation } from './service.mjs';
|
|
18
19
|
|
|
19
20
|
const NPM_REGISTRY = 'https://registry.npmjs.org/aiwg';
|
|
20
21
|
|
|
@@ -212,13 +213,13 @@ async function checkStableUpdates(config) {
|
|
|
212
213
|
console.log('');
|
|
213
214
|
console.log('Updating aiwg...');
|
|
214
215
|
try {
|
|
215
|
-
|
|
216
|
+
await updateInstallation({ config, channel: 'stable' });
|
|
216
217
|
console.log('Update complete! Please restart your terminal.');
|
|
217
218
|
} catch (error) {
|
|
218
|
-
console.error('Update failed. Run manually:
|
|
219
|
+
console.error('Update failed. Run manually: aiwg update');
|
|
219
220
|
}
|
|
220
221
|
} else {
|
|
221
|
-
console.log('Update skipped. Run `
|
|
222
|
+
console.log('Update skipped. Run `aiwg update` when ready.');
|
|
222
223
|
}
|
|
223
224
|
console.log('');
|
|
224
225
|
}
|
|
@@ -251,13 +252,13 @@ async function checkNextUpdates(config) {
|
|
|
251
252
|
console.log('');
|
|
252
253
|
console.log('Updating aiwg@next...');
|
|
253
254
|
try {
|
|
254
|
-
|
|
255
|
+
await updateInstallation({ config, channel: 'next' });
|
|
255
256
|
console.log('Update complete! Please restart your terminal.');
|
|
256
257
|
} catch {
|
|
257
|
-
console.error('Update failed. Run manually:
|
|
258
|
+
console.error('Update failed. Run manually: aiwg update');
|
|
258
259
|
}
|
|
259
260
|
} else {
|
|
260
|
-
console.log('Update skipped. Run `
|
|
261
|
+
console.log('Update skipped. Run `aiwg update` when ready.');
|
|
261
262
|
}
|
|
262
263
|
console.log('');
|
|
263
264
|
}
|
|
@@ -290,13 +291,13 @@ async function checkNightlyUpdates(config) {
|
|
|
290
291
|
console.log('');
|
|
291
292
|
console.log('Updating aiwg@nightly...');
|
|
292
293
|
try {
|
|
293
|
-
|
|
294
|
+
await updateInstallation({ config, channel: 'nightly' });
|
|
294
295
|
console.log('Update complete! Please restart your terminal.');
|
|
295
296
|
} catch {
|
|
296
|
-
console.error('Update failed. Run manually:
|
|
297
|
+
console.error('Update failed. Run manually: aiwg update');
|
|
297
298
|
}
|
|
298
299
|
} else {
|
|
299
|
-
console.log('Update skipped. Run `
|
|
300
|
+
console.log('Update skipped. Run `aiwg update` when ready.');
|
|
300
301
|
}
|
|
301
302
|
console.log('');
|
|
302
303
|
}
|
|
@@ -348,13 +349,13 @@ export async function forceUpdateCheck() {
|
|
|
348
349
|
console.log('Checking for updates on next channel...');
|
|
349
350
|
const latestVersion = await fetchNpmDistTag('next');
|
|
350
351
|
if (!latestVersion) {
|
|
351
|
-
console.log('Could not check npm registry. Try:
|
|
352
|
+
console.log('Could not check npm registry. Try: aiwg update');
|
|
352
353
|
return;
|
|
353
354
|
}
|
|
354
355
|
if (currentVersion !== latestVersion) {
|
|
355
356
|
console.log(`Update available: ${currentVersion} → ${latestVersion}`);
|
|
356
357
|
console.log('');
|
|
357
|
-
console.log('Run:
|
|
358
|
+
console.log('Run: aiwg update');
|
|
358
359
|
} else {
|
|
359
360
|
console.log(`You are on the latest next release: ${currentVersion}`);
|
|
360
361
|
}
|
|
@@ -362,13 +363,13 @@ export async function forceUpdateCheck() {
|
|
|
362
363
|
console.log('Checking for updates on nightly channel...');
|
|
363
364
|
const latestVersion = await fetchNpmDistTag('nightly');
|
|
364
365
|
if (!latestVersion) {
|
|
365
|
-
console.log('Could not check npm registry. Try:
|
|
366
|
+
console.log('Could not check npm registry. Try: aiwg update');
|
|
366
367
|
return;
|
|
367
368
|
}
|
|
368
369
|
if (currentVersion !== latestVersion) {
|
|
369
370
|
console.log(`Update available: ${currentVersion} → ${latestVersion}`);
|
|
370
371
|
console.log('');
|
|
371
|
-
console.log('Run:
|
|
372
|
+
console.log('Run: aiwg update');
|
|
372
373
|
} else {
|
|
373
374
|
console.log(`You are on the latest nightly snapshot: ${currentVersion}`);
|
|
374
375
|
}
|
|
@@ -381,14 +382,14 @@ export async function forceUpdateCheck() {
|
|
|
381
382
|
const latestVersion = await fetchLatestNpmVersion();
|
|
382
383
|
|
|
383
384
|
if (!latestVersion) {
|
|
384
|
-
console.log('Could not check npm registry. Try:
|
|
385
|
+
console.log('Could not check npm registry. Try: aiwg update');
|
|
385
386
|
return;
|
|
386
387
|
}
|
|
387
388
|
|
|
388
389
|
if (isNewerVersion(currentVersion, latestVersion)) {
|
|
389
390
|
console.log(`Update available: ${currentVersion} → ${latestVersion}`);
|
|
390
391
|
console.log('');
|
|
391
|
-
console.log('Run:
|
|
392
|
+
console.log('Run: aiwg update');
|
|
392
393
|
} else {
|
|
393
394
|
console.log(`You are on the latest version: ${currentVersion}`);
|
|
394
395
|
}
|
|
@@ -27,12 +27,13 @@
|
|
|
27
27
|
|
|
28
28
|
import https from 'https';
|
|
29
29
|
import path from 'path';
|
|
30
|
-
import os from 'os';
|
|
31
30
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
32
31
|
import { spawn } from 'child_process';
|
|
33
32
|
import { fileURLToPath } from 'url';
|
|
33
|
+
import { resolveUserConfigDir } from '../config/user-config-dir.mjs';
|
|
34
|
+
import { loadInstallationIdentity } from '../installation/manager.mjs';
|
|
34
35
|
|
|
35
|
-
const CACHE_DIR =
|
|
36
|
+
const CACHE_DIR = resolveUserConfigDir();
|
|
36
37
|
const CACHE_FILE = path.join(CACHE_DIR, 'update-notifier.json');
|
|
37
38
|
|
|
38
39
|
/**
|
|
@@ -191,11 +192,13 @@ async function runCheck(packageRoot) {
|
|
|
191
192
|
*/
|
|
192
193
|
export function scheduleBackgroundCheck(packageRoot) {
|
|
193
194
|
if (isDisabled()) return;
|
|
195
|
+
const installation = loadInstallationIdentity({ actualRoot: packageRoot, createIfMissing: false });
|
|
196
|
+
if (installation?.checkOnStartup === false) return;
|
|
194
197
|
|
|
195
198
|
const cache = readCache();
|
|
196
199
|
if (cacheMatchesPackage(cache, packageRoot) && cache?.lastCheckAt) {
|
|
197
200
|
const age = Date.now() - new Date(cache.lastCheckAt).getTime();
|
|
198
|
-
if (age < CHECK_INTERVAL_MS) return; // recent enough — skip
|
|
201
|
+
if (age < (installation?.updateCheckInterval ?? CHECK_INTERVAL_MS)) return; // recent enough — skip
|
|
199
202
|
}
|
|
200
203
|
|
|
201
204
|
try {
|
|
@@ -225,6 +228,8 @@ export function scheduleBackgroundCheck(packageRoot) {
|
|
|
225
228
|
*/
|
|
226
229
|
export function maybePrintNotice(packageRoot) {
|
|
227
230
|
if (isDisabled()) return;
|
|
231
|
+
const installation = loadInstallationIdentity({ actualRoot: packageRoot, createIfMissing: false });
|
|
232
|
+
if (installation?.checkOnStartup === false) return;
|
|
228
233
|
const cache = readCache();
|
|
229
234
|
if (!cacheMatchesPackage(cache, packageRoot)) return;
|
|
230
235
|
if (!cache?.hasUpdate || !cache.current || !cache.latest) return;
|
|
@@ -10,6 +10,13 @@ import { execFileSync } from 'node:child_process';
|
|
|
10
10
|
import { existsSync, readFileSync } from 'node:fs';
|
|
11
11
|
import path from 'node:path';
|
|
12
12
|
import { getPackageRoot, loadConfig } from '../channel/manager.mjs';
|
|
13
|
+
import {
|
|
14
|
+
assertCanonicalInstallation,
|
|
15
|
+
createInstallationIdentity,
|
|
16
|
+
loadInstallationIdentity,
|
|
17
|
+
saveInstallationIdentity,
|
|
18
|
+
} from '../installation/manager.mjs';
|
|
19
|
+
import { resolveManagerCommand } from '../installation/manager-command.mjs';
|
|
13
20
|
|
|
14
21
|
const VALID_MODES = new Set(['npm', 'web', 'source']);
|
|
15
22
|
|
|
@@ -24,14 +31,42 @@ function readPackageName(packageRoot) {
|
|
|
24
31
|
export async function detectInstallMode(options = {}) {
|
|
25
32
|
const packageRoot = options.packageRoot ?? getPackageRoot();
|
|
26
33
|
const override = options.env?.AIWG_INSTALL_MODE ?? process.env.AIWG_INSTALL_MODE;
|
|
34
|
+
const config = options.config ?? await loadConfig(options);
|
|
35
|
+
let identity = options.identity ?? config.installation ?? null;
|
|
36
|
+
let identityPersistent = Boolean(config.installation) || options.identityPersistent === true;
|
|
37
|
+
if (!identity && options.config) {
|
|
38
|
+
const method = override ?? (readPackageName(packageRoot) === '@aiwg/cli'
|
|
39
|
+
? 'web'
|
|
40
|
+
: (config.devMode || config.channel === 'edge' || existsSync(path.join(packageRoot, '.git'))) ? 'source' : 'npm');
|
|
41
|
+
identity = createInstallationIdentity({
|
|
42
|
+
...options,
|
|
43
|
+
actualRoot: packageRoot,
|
|
44
|
+
method,
|
|
45
|
+
channel: config.channel,
|
|
46
|
+
runMode: config.devMode ? 'development' : undefined,
|
|
47
|
+
});
|
|
48
|
+
} else if (!identity) {
|
|
49
|
+
identity = loadInstallationIdentity({ ...options, actualRoot: packageRoot });
|
|
50
|
+
identityPersistent = Boolean(identity);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (override && !VALID_MODES.has(override)) {
|
|
54
|
+
throw new Error(`AIWG_INSTALL_MODE must be one of: ${[...VALID_MODES].join(', ')}`);
|
|
55
|
+
}
|
|
56
|
+
if (override && identity && override !== identity.method) {
|
|
57
|
+
throw new Error(`AIWG_INSTALL_MODE=${override} conflicts with the canonical installation method ${identity.method}. Use \`aiwg installation switch\` instead.`);
|
|
58
|
+
}
|
|
59
|
+
if (identity) {
|
|
60
|
+
const status = assertCanonicalInstallation({ ...options, actualRoot: packageRoot, identity });
|
|
61
|
+
return { mode: identity.method, packageRoot, packageName: readPackageName(packageRoot), identity, identityPersistent, installation: status };
|
|
62
|
+
}
|
|
63
|
+
|
|
27
64
|
if (override) {
|
|
28
65
|
if (!VALID_MODES.has(override)) {
|
|
29
66
|
throw new Error(`AIWG_INSTALL_MODE must be one of: ${[...VALID_MODES].join(', ')}`);
|
|
30
67
|
}
|
|
31
68
|
return { mode: override, packageRoot, packageName: readPackageName(packageRoot) };
|
|
32
69
|
}
|
|
33
|
-
|
|
34
|
-
const config = options.config ?? await loadConfig();
|
|
35
70
|
const packageName = readPackageName(packageRoot);
|
|
36
71
|
if (packageName === '@aiwg/cli') return { mode: 'web', packageRoot, packageName };
|
|
37
72
|
if (config.devMode || config.channel === 'edge' || existsSync(path.join(packageRoot, '.git'))) {
|
|
@@ -56,7 +91,7 @@ function npmTag(channel) {
|
|
|
56
91
|
export async function updateInstallation(options = {}) {
|
|
57
92
|
const config = options.config ?? await loadConfig();
|
|
58
93
|
const detected = await detectInstallMode({ ...options, config });
|
|
59
|
-
const channel = options.channel ?? config.channel ?? 'stable';
|
|
94
|
+
const channel = options.channel ?? detected.identity?.channel ?? config.channel ?? 'stable';
|
|
60
95
|
const dryRun = options.dryRun === true;
|
|
61
96
|
const offline = options.offline === true;
|
|
62
97
|
|
|
@@ -84,6 +119,9 @@ export async function updateInstallation(options = {}) {
|
|
|
84
119
|
return resolveWebRelease({ selector });
|
|
85
120
|
});
|
|
86
121
|
const release = await refreshWebResources(channel);
|
|
122
|
+
if (detected.identity && detected.identityPersistent && options.persistIdentity !== false) {
|
|
123
|
+
saveInstallationIdentity({ ...detected.identity, channel }, options);
|
|
124
|
+
}
|
|
87
125
|
return {
|
|
88
126
|
...detected,
|
|
89
127
|
channel,
|
|
@@ -106,16 +144,24 @@ export async function updateInstallation(options = {}) {
|
|
|
106
144
|
|
|
107
145
|
const tag = npmTag(channel);
|
|
108
146
|
const command = ['install', '--global', `aiwg@${tag}`];
|
|
147
|
+
const managerExecutable = detected.identity?.managerExecutable;
|
|
148
|
+
if (!managerExecutable) {
|
|
149
|
+
throw new Error('Canonical npm installation has no package-manager executable. Run `aiwg installation adopt --manager <absolute-path-to-npm>`.');
|
|
150
|
+
}
|
|
109
151
|
if (!dryRun) {
|
|
152
|
+
const invocation = resolveManagerCommand(managerExecutable, command, options);
|
|
110
153
|
const execute = options.execute ?? ((file, args) => execFileSync(file, args, { stdio: 'inherit' }));
|
|
111
|
-
execute(
|
|
154
|
+
execute(invocation.file, invocation.args);
|
|
155
|
+
if (detected.identity && detected.identityPersistent && options.persistIdentity !== false) {
|
|
156
|
+
saveInstallationIdentity({ ...detected.identity, channel }, options);
|
|
157
|
+
}
|
|
112
158
|
}
|
|
113
159
|
return {
|
|
114
160
|
...detected,
|
|
115
161
|
channel,
|
|
116
162
|
status: dryRun ? 'dry-run' : 'updated',
|
|
117
163
|
changed: !dryRun,
|
|
118
|
-
command:
|
|
164
|
+
command: `${managerExecutable} ${command.join(' ')}`,
|
|
119
165
|
message: dryRun
|
|
120
166
|
? `Would update the full AIWG npm distribution on the '${tag}' channel.`
|
|
121
167
|
: `Updated the full AIWG npm distribution on the '${tag}' channel.`,
|
package/package.json
CHANGED
|
@@ -340,7 +340,7 @@ function mirrorSkillsAsCommands(provider, target, srcRoot, opts) {
|
|
|
340
340
|
* @param {string|null} explicitSource the raw `--source` value (null when unset)
|
|
341
341
|
*/
|
|
342
342
|
function pruneStaleAiwgArtifacts(provider, target, srcRoot, opts, explicitSource) {
|
|
343
|
-
if (opts.skillsOnly) return; // skills run their own prune in the provider
|
|
343
|
+
if (opts.skillsOnly && !opts.kernelOnly) return; // skills run their own prune in the provider
|
|
344
344
|
|
|
345
345
|
const aiwgRoot = resolveAiwgRoot(srcRoot);
|
|
346
346
|
if (!aiwgRoot) return; // no AIWG tree → bundle/standalone deploy; never prune
|
|
@@ -355,6 +355,20 @@ function pruneStaleAiwgArtifacts(provider, target, srcRoot, opts, explicitSource
|
|
|
355
355
|
if (!underCode) return; // project-local bundle / external source → skip
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
+
if (opts.kernelOnly) {
|
|
359
|
+
for (const type of ['agents', 'commands', 'rules']) {
|
|
360
|
+
const relPath = provider.paths?.[type];
|
|
361
|
+
if (!relPath || relPath.endsWith('.md')) continue;
|
|
362
|
+
const destDir = path.isAbsolute(relPath) ? relPath : path.join(target, relPath);
|
|
363
|
+
pruneStaleAiwgFiles(destDir, new Set(), {
|
|
364
|
+
dryRun: opts.dryRun,
|
|
365
|
+
verbose: opts.verbose,
|
|
366
|
+
artifactExtensions: ['.md', '.mdc', '.toml'],
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
358
372
|
const typesThisRun = [];
|
|
359
373
|
if (!opts.commandsOnly && !opts.rulesOnly) typesThisRun.push('agents');
|
|
360
374
|
if (opts.deployCommands || opts.commandsOnly) typesThisRun.push('commands');
|
|
@@ -406,6 +420,7 @@ function parseArgs() {
|
|
|
406
420
|
commandsOnly: false,
|
|
407
421
|
skillsOnly: false,
|
|
408
422
|
rulesOnly: false,
|
|
423
|
+
kernelOnly: false,
|
|
409
424
|
filter: null, // Glob pattern for agent names
|
|
410
425
|
filterRole: null, // Filter by role: reasoning|coding|efficiency
|
|
411
426
|
save: false, // Save model config to project models.json
|
|
@@ -438,6 +453,7 @@ function parseArgs() {
|
|
|
438
453
|
else if (a === '--commands-only') cfg.commandsOnly = true;
|
|
439
454
|
else if (a === '--skills-only') cfg.skillsOnly = true;
|
|
440
455
|
else if (a === '--rules-only') cfg.rulesOnly = true;
|
|
456
|
+
else if (a === '--kernel-only') cfg.kernelOnly = true;
|
|
441
457
|
else if (a === '--deploy-behaviors') cfg.deployBehaviors = true;
|
|
442
458
|
else if (a === '--filter' && args[i + 1]) cfg.filter = args[++i];
|
|
443
459
|
else if (a === '--filter-role' && args[i + 1]) cfg.filterRole = args[++i];
|
|
@@ -474,6 +490,7 @@ Options:
|
|
|
474
490
|
--commands-only Deploy only commands (skip agents)
|
|
475
491
|
--skills-only Deploy only skills (skip agents)
|
|
476
492
|
--rules-only Deploy only rules (skip agents)
|
|
493
|
+
--kernel-only Deploy kernel skills only and prune managed bulk artifacts
|
|
477
494
|
--dry-run Show what would be deployed without writing
|
|
478
495
|
--force Overwrite existing files
|
|
479
496
|
--provider <name> Target provider (see below)
|
|
@@ -490,7 +507,9 @@ Options:
|
|
|
490
507
|
--create-agents-md Create/update AGENTS.md template
|
|
491
508
|
--skip-commands-migration Skip deleting the commands directory before skills deployment
|
|
492
509
|
--copy-all Copy ALL skills per-project (legacy mirror at <provider>/.aiwg/skills/).
|
|
493
|
-
|
|
510
|
+
For aiwg use all, this also restores the legacy full agent,
|
|
511
|
+
command, and expanded-rule copy. Default bulk deployment is
|
|
512
|
+
kernel-only + index-driven discovery for the rest (#1217).
|
|
494
513
|
Use this for sandboxed runtimes / air-gapped corpora where
|
|
495
514
|
$AIWG_ROOT isn't readable from the agent's working dir.
|
|
496
515
|
Alias: --copy-standard-skills — rc.29 era).
|
|
@@ -879,13 +898,14 @@ export async function main() {
|
|
|
879
898
|
modelsConfig,
|
|
880
899
|
asAgentsMd: cfg.asAgentsMd,
|
|
881
900
|
createAgentsMd: cfg.createAgentsMd,
|
|
882
|
-
deployCommands: cfg.deployCommands,
|
|
883
|
-
deploySkills: cfg.deploySkills,
|
|
884
|
-
deployRules: cfg.deployRules,
|
|
885
|
-
deployBehaviors: cfg.deployBehaviors,
|
|
901
|
+
deployCommands: cfg.kernelOnly ? false : cfg.deployCommands,
|
|
902
|
+
deploySkills: cfg.kernelOnly ? true : cfg.deploySkills,
|
|
903
|
+
deployRules: cfg.kernelOnly ? false : cfg.deployRules,
|
|
904
|
+
deployBehaviors: cfg.kernelOnly ? false : cfg.deployBehaviors,
|
|
886
905
|
commandsOnly: cfg.commandsOnly,
|
|
887
|
-
skillsOnly: cfg.skillsOnly,
|
|
906
|
+
skillsOnly: cfg.skillsOnly || cfg.kernelOnly,
|
|
888
907
|
rulesOnly: cfg.rulesOnly,
|
|
908
|
+
kernelOnly: cfg.kernelOnly,
|
|
889
909
|
filter: cfg.filter,
|
|
890
910
|
filterRole: cfg.filterRole,
|
|
891
911
|
save: cfg.save,
|
|
@@ -893,7 +913,7 @@ export async function main() {
|
|
|
893
913
|
verbose: cfg.verbose,
|
|
894
914
|
quiet: cfg.quiet,
|
|
895
915
|
asPlugin: cfg.asPlugin,
|
|
896
|
-
deployBehaviors: cfg.deployBehaviors,
|
|
916
|
+
deployBehaviors: cfg.kernelOnly ? false : cfg.deployBehaviors,
|
|
897
917
|
skipCommandsMigration: cfg.skipCommandsMigration,
|
|
898
918
|
// #1217 / #1219: --copy-all flag forces legacy per-project mirror
|
|
899
919
|
// for the standard tier. Default is no-copy + index-driven discovery.
|
|
@@ -1183,7 +1183,7 @@ export function computeAllKernelNames(srcRoot) {
|
|
|
1183
1183
|
* located — see `computeAllKernelNames`), pruning is skipped entirely so a
|
|
1184
1184
|
* project-local-bundle deploy without AIWG_ROOT never empties the kernel
|
|
1185
1185
|
* skills directory (#123).
|
|
1186
|
-
* @param {object} opts `{ dryRun, verbose }`
|
|
1186
|
+
* @param {object} opts `{ dryRun, verbose, artifactExtensions }`
|
|
1187
1187
|
* @returns {number} count of pruned entries
|
|
1188
1188
|
*/
|
|
1189
1189
|
export function pruneStaleAiwgSkills(kernelDestDir, desiredKernelNames, opts = {}) {
|
|
@@ -1348,7 +1348,8 @@ export function resolveAiwgRoot(srcRoot) {
|
|
|
1348
1348
|
* `pruneStaleAiwgSkills`.
|
|
1349
1349
|
*
|
|
1350
1350
|
* Removes a file from `destDir` only when ALL hold:
|
|
1351
|
-
* 1. It
|
|
1351
|
+
* 1. It has an allowed deployed-artifact extension (`.md` / `.mdc` by
|
|
1352
|
+
* default; callers may include `.toml`), is not `RULES-INDEX.md`,
|
|
1352
1353
|
* and not the sidecar manifest.
|
|
1353
1354
|
* 2. Its stem is NOT in `desiredStems` (the source no longer ships it).
|
|
1354
1355
|
* 3. It carries an AIWG ownership signal — either a `.aiwg-manifest.json`
|
|
@@ -1369,6 +1370,7 @@ export function resolveAiwgRoot(srcRoot) {
|
|
|
1369
1370
|
*/
|
|
1370
1371
|
export function pruneStaleAiwgFiles(destDir, desiredStems, opts = {}) {
|
|
1371
1372
|
const { dryRun = false, verbose = false } = opts;
|
|
1373
|
+
const artifactExtensions = opts.artifactExtensions || ['.md', '.mdc'];
|
|
1372
1374
|
const removed = [];
|
|
1373
1375
|
if (!destDir || !fs.existsSync(destDir)) return removed;
|
|
1374
1376
|
|
|
@@ -1391,7 +1393,7 @@ export function pruneStaleAiwgFiles(destDir, desiredStems, opts = {}) {
|
|
|
1391
1393
|
if (name === 'RULES-INDEX.md') continue;
|
|
1392
1394
|
if (name === 'RULES-ONDEMAND.md') continue; // generated on-demand index (#1673)
|
|
1393
1395
|
const lower = name.toLowerCase();
|
|
1394
|
-
if (!
|
|
1396
|
+
if (!artifactExtensions.some(extension => lower.endsWith(extension))) continue;
|
|
1395
1397
|
|
|
1396
1398
|
if (desired.has(artifactStem(name))) continue;
|
|
1397
1399
|
|