@aiwg/cli 2026.8.17 → 2026.8.18

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.
Files changed (37) hide show
  1. package/bin/aiwg.mjs +24 -2
  2. package/dist/src/a2a/agent-card.js +4 -1
  3. package/dist/src/a2a/client.js +148 -68
  4. package/dist/src/a2a/codecs.js +480 -0
  5. package/dist/src/a2a/events.js +226 -0
  6. package/dist/src/a2a/hitl-driver.js +8 -6
  7. package/dist/src/a2a/hitl.js +2 -1
  8. package/dist/src/a2a/http.js +85 -5
  9. package/dist/src/a2a/protocol.js +136 -0
  10. package/dist/src/a2a/types.js +4 -14
  11. package/dist/src/a2a/webhook.js +101 -4
  12. package/dist/src/audit/operator-decision.js +15 -1
  13. package/dist/src/channel/manager.mjs +89 -17
  14. package/dist/src/cli/handlers/index.js +3 -1
  15. package/dist/src/cli/handlers/installation.js +79 -0
  16. package/dist/src/cli/handlers/refresh.js +4 -2
  17. package/dist/src/cli/handlers/runtime-info.js +9 -1
  18. package/dist/src/cli/handlers/serve.js +107 -4
  19. package/dist/src/cli/handlers/session.js +12 -26
  20. package/dist/src/cli/handlers/utilities.js +4 -0
  21. package/dist/src/cli/handlers/version.js +4 -0
  22. package/dist/src/config/user-config-dir.mjs +29 -0
  23. package/dist/src/config/user-config.js +4 -22
  24. package/dist/src/extensions/commands/definitions.js +20 -1
  25. package/dist/src/features/catalog.js +2 -1
  26. package/dist/src/flow/graph-metadata.js +56 -0
  27. package/dist/src/installation/manager.mjs +243 -0
  28. package/dist/src/serve/a2a-terminal-observer.js +28 -5
  29. package/dist/src/serve/dispatch-router.js +32 -4
  30. package/dist/src/serve/executor-registry.js +29 -0
  31. package/dist/src/serve/mission-conductor.js +15 -1
  32. package/dist/src/serve/stack-adapters.js +2 -1
  33. package/dist/src/serve/telemetry.js +5 -1
  34. package/dist/src/update/checker.mjs +16 -15
  35. package/dist/src/update/notifier.mjs +8 -3
  36. package/dist/src/update/service.mjs +49 -5
  37. package/package.json +1 -1
@@ -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 = path.join(os.homedir(), '.aiwg');
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,12 @@ 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';
13
19
 
14
20
  const VALID_MODES = new Set(['npm', 'web', 'source']);
15
21
 
@@ -24,14 +30,42 @@ function readPackageName(packageRoot) {
24
30
  export async function detectInstallMode(options = {}) {
25
31
  const packageRoot = options.packageRoot ?? getPackageRoot();
26
32
  const override = options.env?.AIWG_INSTALL_MODE ?? process.env.AIWG_INSTALL_MODE;
33
+ const config = options.config ?? await loadConfig(options);
34
+ let identity = options.identity ?? config.installation ?? null;
35
+ let identityPersistent = Boolean(config.installation) || options.identityPersistent === true;
36
+ if (!identity && options.config) {
37
+ const method = override ?? (readPackageName(packageRoot) === '@aiwg/cli'
38
+ ? 'web'
39
+ : (config.devMode || config.channel === 'edge' || existsSync(path.join(packageRoot, '.git'))) ? 'source' : 'npm');
40
+ identity = createInstallationIdentity({
41
+ ...options,
42
+ actualRoot: packageRoot,
43
+ method,
44
+ channel: config.channel,
45
+ runMode: config.devMode ? 'development' : undefined,
46
+ });
47
+ } else if (!identity) {
48
+ identity = loadInstallationIdentity({ ...options, actualRoot: packageRoot });
49
+ identityPersistent = Boolean(identity);
50
+ }
51
+
52
+ if (override && !VALID_MODES.has(override)) {
53
+ throw new Error(`AIWG_INSTALL_MODE must be one of: ${[...VALID_MODES].join(', ')}`);
54
+ }
55
+ if (override && identity && override !== identity.method) {
56
+ throw new Error(`AIWG_INSTALL_MODE=${override} conflicts with the canonical installation method ${identity.method}. Use \`aiwg installation switch\` instead.`);
57
+ }
58
+ if (identity) {
59
+ const status = assertCanonicalInstallation({ ...options, actualRoot: packageRoot, identity });
60
+ return { mode: identity.method, packageRoot, packageName: readPackageName(packageRoot), identity, identityPersistent, installation: status };
61
+ }
62
+
27
63
  if (override) {
28
64
  if (!VALID_MODES.has(override)) {
29
65
  throw new Error(`AIWG_INSTALL_MODE must be one of: ${[...VALID_MODES].join(', ')}`);
30
66
  }
31
67
  return { mode: override, packageRoot, packageName: readPackageName(packageRoot) };
32
68
  }
33
-
34
- const config = options.config ?? await loadConfig();
35
69
  const packageName = readPackageName(packageRoot);
36
70
  if (packageName === '@aiwg/cli') return { mode: 'web', packageRoot, packageName };
37
71
  if (config.devMode || config.channel === 'edge' || existsSync(path.join(packageRoot, '.git'))) {
@@ -56,7 +90,7 @@ function npmTag(channel) {
56
90
  export async function updateInstallation(options = {}) {
57
91
  const config = options.config ?? await loadConfig();
58
92
  const detected = await detectInstallMode({ ...options, config });
59
- const channel = options.channel ?? config.channel ?? 'stable';
93
+ const channel = options.channel ?? detected.identity?.channel ?? config.channel ?? 'stable';
60
94
  const dryRun = options.dryRun === true;
61
95
  const offline = options.offline === true;
62
96
 
@@ -84,6 +118,9 @@ export async function updateInstallation(options = {}) {
84
118
  return resolveWebRelease({ selector });
85
119
  });
86
120
  const release = await refreshWebResources(channel);
121
+ if (detected.identity && detected.identityPersistent && options.persistIdentity !== false) {
122
+ saveInstallationIdentity({ ...detected.identity, channel }, options);
123
+ }
87
124
  return {
88
125
  ...detected,
89
126
  channel,
@@ -106,16 +143,23 @@ export async function updateInstallation(options = {}) {
106
143
 
107
144
  const tag = npmTag(channel);
108
145
  const command = ['install', '--global', `aiwg@${tag}`];
146
+ const managerExecutable = detected.identity?.managerExecutable;
147
+ if (!managerExecutable) {
148
+ throw new Error('Canonical npm installation has no package-manager executable. Run `aiwg installation adopt --manager <absolute-path-to-npm>`.');
149
+ }
109
150
  if (!dryRun) {
110
151
  const execute = options.execute ?? ((file, args) => execFileSync(file, args, { stdio: 'inherit' }));
111
- execute('npm', command);
152
+ execute(managerExecutable, command);
153
+ if (detected.identity && detected.identityPersistent && options.persistIdentity !== false) {
154
+ saveInstallationIdentity({ ...detected.identity, channel }, options);
155
+ }
112
156
  }
113
157
  return {
114
158
  ...detected,
115
159
  channel,
116
160
  status: dryRun ? 'dry-run' : 'updated',
117
161
  changed: !dryRun,
118
- command: `npm ${command.join(' ')}`,
162
+ command: `${managerExecutable} ${command.join(' ')}`,
119
163
  message: dryRun
120
164
  ? `Would update the full AIWG npm distribution on the '${tag}' channel.`
121
165
  : `Updated the full AIWG npm distribution on the '${tag}' channel.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwg/cli",
3
- "version": "2026.8.17",
3
+ "version": "2026.8.18",
4
4
  "description": "Lightweight AIWG CLI for signed, versioned web-backed resources.",
5
5
  "type": "module",
6
6
  "license": "MIT",