@aiwg/cli 2026.8.0 → 2026.8.1

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 (61) hide show
  1. package/README.md +33 -0
  2. package/agentic/code/providers/capability-matrix.yaml +511 -0
  3. package/agentic/code/providers/model-capabilities.v1.json +120 -0
  4. package/agentic/code/providers/model-catalog.v1.json +96 -0
  5. package/agentic/code/providers/model-policy-evaluations.v1.json +50 -0
  6. package/agentic/code/providers/premium-model-allowlist.v1.json +36 -0
  7. package/bin/aiwg.mjs +14 -10
  8. package/dist/src/api/index.d.ts +1 -0
  9. package/dist/src/api/index.js +1 -0
  10. package/dist/src/artifacts/cli.js +2 -0
  11. package/dist/src/artifacts/types.js +4 -0
  12. package/dist/src/auth/client.js +209 -0
  13. package/dist/src/auth/config.js +38 -0
  14. package/dist/src/auth/credential-store.js +141 -0
  15. package/dist/src/auth/resource-credentials.js +25 -0
  16. package/dist/src/auth/types.js +2 -0
  17. package/dist/src/channel/manager.mjs +5 -5
  18. package/dist/src/cli/handlers/auth.js +125 -0
  19. package/dist/src/cli/handlers/help.js +1 -0
  20. package/dist/src/cli/handlers/index.js +3 -1
  21. package/dist/src/cli/handlers/resource-versions.js +2 -0
  22. package/dist/src/cli/handlers/sessions.js +23 -5
  23. package/dist/src/cli/handlers/subcommands.js +10 -1
  24. package/dist/src/cli/handlers/use.js +342 -43
  25. package/dist/src/config/gitignore.js +1 -0
  26. package/dist/src/extensions/commands/definitions.js +19 -0
  27. package/dist/src/memory/canonical-context.js +342 -0
  28. package/dist/src/memory/context-pack.js +282 -0
  29. package/dist/src/memory/index.js +4 -0
  30. package/dist/src/memory/intake.js +118 -0
  31. package/dist/src/resources/resolver.js +1 -0
  32. package/dist/src/resources/web-release.d.ts +3 -1
  33. package/dist/src/resources/web-release.js +14 -6
  34. package/dist/src/serve/agentic-sandbox-fleet-client.js +213 -0
  35. package/dist/src/serve/fleet-mission-conductor.js +293 -0
  36. package/dist/src/sessions/index.js +1 -0
  37. package/dist/src/sessions/output-registration.js +338 -0
  38. package/dist/src/sessions/promotion.js +73 -2
  39. package/dist/src/sessions/repository.js +2 -1
  40. package/dist/src/update/notifier.mjs +13 -2
  41. package/package.json +8 -1
  42. package/tools/_resolve-impl.mjs +74 -0
  43. package/tools/agents/deploy-agents.mjs +962 -0
  44. package/tools/agents/providers/base.mjs +2954 -0
  45. package/tools/agents/providers/claude.mjs +711 -0
  46. package/tools/agents/providers/codex.mjs +699 -0
  47. package/tools/agents/providers/copilot.mjs +659 -0
  48. package/tools/agents/providers/cursor.mjs +714 -0
  49. package/tools/agents/providers/factory.mjs +1130 -0
  50. package/tools/agents/providers/hermes.mjs +663 -0
  51. package/tools/agents/providers/hook-capabilities.mjs +85 -0
  52. package/tools/agents/providers/model-role.mjs +56 -0
  53. package/tools/agents/providers/openclaw-translator.mjs +348 -0
  54. package/tools/agents/providers/openclaw.mjs +680 -0
  55. package/tools/agents/providers/opencode.mjs +675 -0
  56. package/tools/agents/providers/openhuman.mjs +292 -0
  57. package/tools/agents/providers/warp.mjs +413 -0
  58. package/tools/agents/providers/windsurf.mjs +748 -0
  59. package/tools/commands/deploy-prompts-codex.mjs +336 -0
  60. package/tools/plugin/package-plugins.mjs +1013 -0
  61. package/tools/skills/deploy-skills-codex.mjs +571 -0
@@ -0,0 +1,141 @@
1
+ import { spawn } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ export const defaultCommandRunner = (command, args, stdin = "") => new Promise((resolve, reject) => {
6
+ const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
7
+ const stdout = [];
8
+ const stderr = [];
9
+ let outputBytes = 0;
10
+ const collect = (target, chunk) => {
11
+ outputBytes += chunk.length;
12
+ if (outputBytes > 1024 * 1024)
13
+ child.kill();
14
+ else
15
+ target.push(chunk);
16
+ };
17
+ child.stdout.on("data", (chunk) => collect(stdout, chunk));
18
+ child.stderr.on("data", (chunk) => collect(stderr, chunk));
19
+ child.once("error", reject);
20
+ child.once("close", (code) => resolve({
21
+ stdout: Buffer.concat(stdout).toString("utf8"),
22
+ stderr: Buffer.concat(stderr).toString("utf8"),
23
+ exitCode: code ?? 1,
24
+ }));
25
+ child.stdin.end(stdin);
26
+ });
27
+ function parseCredentials(raw) {
28
+ const value = JSON.parse(raw);
29
+ if (!value.accessToken?.startsWith("aiwg_at_") || !value.refreshToken?.startsWith("aiwg_rt_")
30
+ || value.tokenType !== "Bearer" || !Array.isArray(value.scope) || !value.expiresAt) {
31
+ throw new Error("stored AIWG credentials are invalid");
32
+ }
33
+ return value;
34
+ }
35
+ const SERVICE = "releases.aiwg.io";
36
+ const ACCOUNT = "aiwg-cli";
37
+ class NativeCredentialStore {
38
+ run;
39
+ constructor(run = defaultCommandRunner) {
40
+ this.run = run;
41
+ }
42
+ parse(raw) { return parseCredentials(raw.trim()); }
43
+ }
44
+ export class MacOsKeychainStore extends NativeCredentialStore {
45
+ metadata = { provider: "macos-keychain", location: `Keychain:${SERVICE}/${ACCOUNT}` };
46
+ async load() {
47
+ const result = await this.run("security", ["find-generic-password", "-a", ACCOUNT, "-s", SERVICE, "-w"]);
48
+ return result.exitCode === 44 ? null : result.exitCode === 0 ? this.parse(result.stdout) : Promise.reject(new Error("macOS Keychain read failed"));
49
+ }
50
+ async save(credentials) {
51
+ const result = await this.run("security", ["add-generic-password", "-U", "-a", ACCOUNT, "-s", SERVICE, "-w"], JSON.stringify(credentials));
52
+ if (result.exitCode !== 0)
53
+ throw new Error("macOS Keychain write failed");
54
+ }
55
+ async delete() { await this.run("security", ["delete-generic-password", "-a", ACCOUNT, "-s", SERVICE]); }
56
+ }
57
+ export class LinuxSecretServiceStore extends NativeCredentialStore {
58
+ metadata = { provider: "linux-secret-service", location: `SecretService:${SERVICE}/${ACCOUNT}` };
59
+ async load() {
60
+ const result = await this.run("secret-tool", ["lookup", "service", SERVICE, "account", ACCOUNT]);
61
+ return result.exitCode === 1 ? null : result.exitCode === 0 ? this.parse(result.stdout) : Promise.reject(new Error("Linux Secret Service read failed"));
62
+ }
63
+ async save(credentials) {
64
+ const result = await this.run("secret-tool", ["store", `--label=AIWG ${SERVICE}`, "service", SERVICE, "account", ACCOUNT], JSON.stringify(credentials));
65
+ if (result.exitCode !== 0)
66
+ throw new Error("Linux Secret Service write failed");
67
+ }
68
+ async delete() { await this.run("secret-tool", ["clear", "service", SERVICE, "account", ACCOUNT]); }
69
+ }
70
+ const WINDOWS_READ = "$v=New-Object Windows.Security.Credentials.PasswordVault;try{$c=$v.Retrieve('releases.aiwg.io','aiwg-cli');$c.RetrievePassword();[Console]::Out.Write($c.Password)}catch{exit 1}";
71
+ const WINDOWS_WRITE = "$s=[Console]::In.ReadToEnd();$v=New-Object Windows.Security.Credentials.PasswordVault;$v.Add((New-Object Windows.Security.Credentials.PasswordCredential('releases.aiwg.io','aiwg-cli',$s)))";
72
+ const WINDOWS_DELETE = "$v=New-Object Windows.Security.Credentials.PasswordVault;try{$c=$v.Retrieve('releases.aiwg.io','aiwg-cli');$v.Remove($c)}catch{}";
73
+ export class WindowsCredentialManagerStore extends NativeCredentialStore {
74
+ metadata = { provider: "windows-credential-manager", location: `CredentialManager:${SERVICE}/${ACCOUNT}` };
75
+ execute(script, stdin = "") { return this.run("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], stdin); }
76
+ async load() { const result = await this.execute(WINDOWS_READ); return result.exitCode === 1 ? null : result.exitCode === 0 ? this.parse(result.stdout) : Promise.reject(new Error("Windows Credential Manager read failed")); }
77
+ async save(credentials) { if ((await this.execute(WINDOWS_WRITE, JSON.stringify(credentials))).exitCode !== 0)
78
+ throw new Error("Windows Credential Manager write failed"); }
79
+ async delete() { await this.execute(WINDOWS_DELETE); }
80
+ }
81
+ export class FileCredentialStore {
82
+ pathname;
83
+ explicitlyAllowed;
84
+ metadata;
85
+ constructor(pathname, explicitlyAllowed) {
86
+ this.pathname = pathname;
87
+ this.explicitlyAllowed = explicitlyAllowed;
88
+ this.pathname = path.resolve(pathname);
89
+ this.metadata = { provider: "file", location: this.pathname };
90
+ }
91
+ assertAllowed() { if (!this.explicitlyAllowed)
92
+ throw new Error("credential file fallback requires --allow-file-store or AIWG_AUTH_ALLOW_FILE_STORE=1"); }
93
+ async load() {
94
+ this.assertAllowed();
95
+ try {
96
+ const stat = await fs.lstat(this.pathname);
97
+ if (!stat.isFile() || stat.isSymbolicLink() || (stat.mode & 0o077) !== 0)
98
+ throw new Error("credential file must be a non-symlink mode-0600 regular file");
99
+ return parseCredentials(await fs.readFile(this.pathname, "utf8"));
100
+ }
101
+ catch (error) {
102
+ if (error.code === "ENOENT")
103
+ return null;
104
+ throw error;
105
+ }
106
+ }
107
+ async save(credentials) {
108
+ this.assertAllowed();
109
+ await fs.mkdir(path.dirname(this.pathname), { recursive: true, mode: 0o700 });
110
+ const temporary = `${this.pathname}.${process.pid}.tmp`;
111
+ await fs.writeFile(temporary, `${JSON.stringify(credentials)}\n`, { mode: 0o600, flag: "wx" });
112
+ await fs.rename(temporary, this.pathname);
113
+ await fs.chmod(this.pathname, 0o600);
114
+ }
115
+ async delete() { this.assertAllowed(); await fs.unlink(this.pathname).catch((error) => { if (error.code !== "ENOENT")
116
+ throw error; }); }
117
+ }
118
+ export class MemoryCredentialStore {
119
+ metadata = { provider: "memory", location: "injected-memory-store" };
120
+ value = null;
121
+ async load() { return this.value ? structuredClone(this.value) : null; }
122
+ async save(value) { this.value = structuredClone(value); }
123
+ async delete() { this.value = null; }
124
+ }
125
+ export function defaultCredentialFile() {
126
+ const root = process.env.XDG_CONFIG_HOME || (process.platform === "win32" ? process.env.APPDATA : undefined) || path.join(os.homedir(), ".config");
127
+ return path.join(root, "aiwg", "credentials", "resource-auth.json");
128
+ }
129
+ export function createCredentialStore(options = {}) {
130
+ if (options.useFile)
131
+ return new FileCredentialStore(options.pathname || defaultCredentialFile(), options.allowFile === true);
132
+ const platform = options.platform || process.platform;
133
+ if (platform === "darwin")
134
+ return new MacOsKeychainStore(options.runner);
135
+ if (platform === "win32")
136
+ return new WindowsCredentialManagerStore(options.runner);
137
+ if (platform === "linux")
138
+ return new LinuxSecretServiceStore(options.runner);
139
+ throw new Error("no native credential store is available; explicitly opt in to the mode-0600 file fallback");
140
+ }
141
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1,25 @@
1
+ import { explicitResourceToken } from "./config.js";
2
+ import { createCredentialStore } from "./credential-store.js";
3
+ /**
4
+ * Resolve credentials for protected release downloads. Explicit compatibility
5
+ * inputs take precedence over interactive-login credentials.
6
+ */
7
+ export function createResourceCredentialProvider(env = process.env, store) {
8
+ return async () => {
9
+ const explicit = explicitResourceToken(env);
10
+ if (explicit)
11
+ return explicit;
12
+ const selected = store ?? createCredentialStore();
13
+ try {
14
+ return (await selected.load())?.accessToken ?? null;
15
+ }
16
+ catch (error) {
17
+ // A workstation without the platform keychain helper must retain access
18
+ // to public releases. Invalid/corrupt stored credentials still fail loud.
19
+ if (error.code === "ENOENT")
20
+ return null;
21
+ throw error;
22
+ }
23
+ };
24
+ }
25
+ //# sourceMappingURL=resource-credentials.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -99,10 +99,10 @@ const DEFAULT_CONFIG = {
99
99
  * Get the package root directory.
100
100
  *
101
101
  * Walks up from this file's directory looking for the nearest package.json
102
- * that names "aiwg". This works whether this module runs from its source
103
- * location (`src/channel/manager.mjs`) or from its compiled-build copy
104
- * (`dist/src/channel/manager.mjs`), both of which have package.json at
105
- * the repo root.
102
+ * that names either the full `aiwg` distribution or the lightweight
103
+ * `@aiwg/cli` distribution. This works whether this module runs from its
104
+ * source location (`src/channel/manager.mjs`) or from its compiled-build copy
105
+ * (`dist/src/channel/manager.mjs`).
106
106
  *
107
107
  * The walk is bounded to 10 levels as a safety cap.
108
108
  *
@@ -115,7 +115,7 @@ export function getPackageRoot() {
115
115
  if (existsSync(pkg)) {
116
116
  try {
117
117
  const content = JSON.parse(readFileSync(pkg, 'utf8'));
118
- if (content.name === 'aiwg') return dir;
118
+ if (content.name === 'aiwg' || content.name === '@aiwg/cli') return dir;
119
119
  } catch {
120
120
  // keep walking
121
121
  }
@@ -0,0 +1,125 @@
1
+ import { AuthClient, defaultBrowserOpener } from "../../auth/client.js";
2
+ import { authConfigFromEnvironment } from "../../auth/config.js";
3
+ import { createCredentialStore } from "../../auth/credential-store.js";
4
+ function usage() {
5
+ return [
6
+ "Usage:",
7
+ " aiwg auth login [--device] [--device-label <label>] [--store native|file] [--allow-file-store]",
8
+ " aiwg auth status [--json] [--store native|file] [--allow-file-store]",
9
+ " aiwg auth logout [--all] [--store native|file] [--allow-file-store]",
10
+ "",
11
+ "Exit codes: 0 success; 2 invalid usage; 3 not authenticated; 4 authorization denied/expired; 5 credential store unavailable; 6 network/protocol failure.",
12
+ ].join("\n");
13
+ }
14
+ function value(args, flag) {
15
+ const index = args.indexOf(flag);
16
+ if (index < 0)
17
+ return undefined;
18
+ const result = args[index + 1];
19
+ if (!result || result.startsWith("--"))
20
+ throw new Error(`${flag} requires a value`);
21
+ return result;
22
+ }
23
+ function classify(error) {
24
+ const message = error instanceof Error ? error.message : String(error);
25
+ if (message === "not_authenticated")
26
+ return 3;
27
+ if (/access_denied|expired_token|authorization canceled/.test(message))
28
+ return 4;
29
+ if (/credential|Keychain|Secret Service|Credential Manager/.test(message))
30
+ return 5;
31
+ return 6;
32
+ }
33
+ export function createAuthHandler(dependencies = {}) {
34
+ return {
35
+ id: "auth",
36
+ name: "Authentication",
37
+ description: "Log in, inspect access, and log out of paid AIWG web resources",
38
+ category: "maintenance",
39
+ aliases: [],
40
+ async execute(ctx) {
41
+ if (!ctx.args.length || ["help", "--help", "-h"].includes(ctx.args[0])) {
42
+ console.log(usage());
43
+ return { exitCode: 0 };
44
+ }
45
+ const [subcommand, ...args] = ctx.args;
46
+ if (!["login", "status", "logout"].includes(subcommand))
47
+ return { exitCode: 2, message: usage() };
48
+ try {
49
+ const storeMode = value(args, "--store") || "native";
50
+ if (!["native", "file"].includes(storeMode))
51
+ return { exitCode: 2, message: "--store must be native or file" };
52
+ const allowFile = args.includes("--allow-file-store") || dependencies.env?.AIWG_AUTH_ALLOW_FILE_STORE === "1" || process.env.AIWG_AUTH_ALLOW_FILE_STORE === "1";
53
+ const store = dependencies.store || createCredentialStore({
54
+ platform: dependencies.platform,
55
+ useFile: storeMode === "file",
56
+ allowFile,
57
+ runner: dependencies.runner,
58
+ });
59
+ if (store.metadata.provider === "file")
60
+ console.error("Warning: using explicitly opted-in mode-0600 credential file fallback.");
61
+ const config = dependencies.config || authConfigFromEnvironment(dependencies.env);
62
+ const client = new AuthClient(config, store, dependencies.fetcher, dependencies.openBrowser, dependencies.now);
63
+ if (subcommand === "login") {
64
+ const deviceLabel = value(args, "--device-label");
65
+ if (args.includes("--device")) {
66
+ await client.loginDevice({
67
+ signal: ctx.signal,
68
+ deviceLabel,
69
+ onCode(info) {
70
+ console.log(`Open: ${String(info.verification_uri)}`);
71
+ console.log(`Code: ${String(info.user_code)}`);
72
+ },
73
+ });
74
+ }
75
+ else {
76
+ await client.loginBrowser({ signal: ctx.signal, deviceLabel });
77
+ }
78
+ console.log(`Authenticated. Credentials stored in ${store.metadata.location}.`);
79
+ return { exitCode: 0 };
80
+ }
81
+ if (subcommand === "status") {
82
+ const { profile, credentials } = await client.status(ctx.signal);
83
+ const output = {
84
+ authenticated: true,
85
+ subject: profile.sub,
86
+ account: profile.email || null,
87
+ organization: profile.organization_id || null,
88
+ scopes: profile.scope?.split(/\s+/).filter(Boolean) || credentials.scope,
89
+ plan: profile.plan || null,
90
+ accessReason: profile.access_reason || null,
91
+ accessValidUntil: profile.access_valid_until || credentials.expiresAt,
92
+ credentialStore: store.metadata,
93
+ };
94
+ if (args.includes("--json"))
95
+ console.log(JSON.stringify(output));
96
+ else {
97
+ console.log(`subject: ${output.subject}`);
98
+ console.log(`account: ${output.account || "(not supplied)"}`);
99
+ console.log(`organization: ${output.organization || "(none)"}`);
100
+ console.log(`scopes: ${output.scopes.join(" ")}`);
101
+ console.log(`plan: ${output.plan || "(none)"}`);
102
+ console.log(`access_reason: ${output.accessReason || "(unknown)"}`);
103
+ console.log(`access_valid_until: ${output.accessValidUntil}`);
104
+ console.log(`credential_location: ${store.metadata.location}`);
105
+ }
106
+ return { exitCode: 0 };
107
+ }
108
+ if (args.includes("--all")) {
109
+ const opener = dependencies.openBrowser || defaultBrowserOpener;
110
+ await opener(`${config.baseUrl}/account/security?revoke=all`);
111
+ }
112
+ await client.logout(ctx.signal);
113
+ console.log(args.includes("--all")
114
+ ? "Local credentials removed. Complete revoke-all in the opened account security page."
115
+ : "Logged out and removed local credentials.");
116
+ return { exitCode: 0 };
117
+ }
118
+ catch (error) {
119
+ return { exitCode: classify(error), message: error instanceof Error ? error.message : String(error) };
120
+ }
121
+ },
122
+ };
123
+ }
124
+ export const authHandler = createAuthHandler();
125
+ //# sourceMappingURL=auth.js.map
@@ -81,6 +81,7 @@ function displayHelp() {
81
81
  ['discover "<phrase>"', 'Find skills/agents/commands/rules by capability'],
82
82
  ['show <type> <name>', 'Stream the body of an indexed artifact'],
83
83
  ['versions <list|resolve|show>', 'Browse and resolve signed AIWG web resource releases'],
84
+ ['auth <login|status|logout>', 'Authenticate for paid AIWG web resources'],
84
85
  ['index <subcommand>', 'Manage the artifact index (build/query/discover/deps/stats)'],
85
86
  ['artifacts move --to <path>', 'Move/rename the project AIWG artifact root and reindex'],
86
87
  ]);
@@ -13,6 +13,7 @@ export { createScriptRunner, DefaultScriptRunner } from './script-runner.js';
13
13
  // Import all handlers
14
14
  import { helpHandler } from './help.js';
15
15
  import { versionHandler } from './version.js';
16
+ import { authHandler } from './auth.js';
16
17
  import { useHandler } from './use.js';
17
18
  import { statusHandler, wizardHandler, migrateWorkspaceHandler, rollbackWorkspaceHandler, workspaceHandlers, } from './workspace.js';
18
19
  import { prefillCardsHandler, contributeStartHandler, validateMetadataHandler, doctorHandler, updateHandler, utilityHandlers, } from './utilities.js';
@@ -61,7 +62,7 @@ import { jobHandler } from './job.js';
61
62
  // Re-export individual handlers
62
63
  export {
63
64
  // Maintenance
64
- helpHandler, versionHandler, doctorHandler, updateHandler, refreshHandler, regenerateHandler, workspaceContextHandler,
65
+ helpHandler, versionHandler, authHandler, doctorHandler, updateHandler, refreshHandler, regenerateHandler, workspaceContextHandler,
65
66
  // Framework management
66
67
  useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler,
67
68
  // Project
@@ -115,6 +116,7 @@ export const allHandlers = [
115
116
  // Maintenance (shown first in help)
116
117
  helpHandler,
117
118
  versionHandler,
119
+ authHandler,
118
120
  doctorHandler,
119
121
  updateHandler,
120
122
  refreshHandler,
@@ -3,6 +3,7 @@ import { loadResourceTrustRootFile, readVerifiedRegularFile, resolveWebRelease,
3
3
  import { getProjectDir } from "../../config/aiwg-config.js";
4
4
  import { cleanWebResourceCache } from "../../resources/cache-cleanup.js";
5
5
  import { writeWebResourceLock } from "../../resources/lockfile.js";
6
+ import { createResourceCredentialProvider } from "../../auth/resource-credentials.js";
6
7
  const MAX_RESOURCE_MANIFEST_BYTES = 4 * 1024 * 1024;
7
8
  const DEFAULT_CHANNELS = ["stable", "latest", "canary", "main"];
8
9
  function usage() {
@@ -82,6 +83,7 @@ function webReleaseOptionsFromEnvironment() {
82
83
  ? undefined
83
84
  : loadResourceTrustRootFile(path.resolve(trustRootFile));
84
85
  return {
86
+ credentialProvider: createResourceCredentialProvider(process.env),
85
87
  ...(baseUrl === undefined ? {} : { baseUrl }),
86
88
  ...(cacheRoot === undefined ? {} : { cacheRoot }),
87
89
  ...(publicKeyPem === undefined ? {} : { publicKeyPem }),
@@ -1,7 +1,22 @@
1
1
  import { existsSync, mkdirSync, realpathSync, statSync, } from 'node:fs';
2
2
  import { dirname, isAbsolute, resolve, } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
3
4
  import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SESSION_PROVIDER_IDS, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, } from '../../sessions/index.js';
4
5
  const JSON_CONTRACT_VERSION = '1.0.0';
6
+ async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
7
+ const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
8
+ if (!existsSync(modulePath)) {
9
+ throw new SessionContractError('UNSUPPORTED_OPERATION', 'line-memory promotion adapter is missing from the installed addon');
10
+ }
11
+ const loaded = await import(pathToFileURL(modulePath).href);
12
+ if (!loaded.LineMemoryPromotionDestination) {
13
+ throw new SessionContractError('UNSUPPORTED_OPERATION', 'line-memory addon does not export its promotion adapter');
14
+ }
15
+ return new loaded.LineMemoryPromotionDestination({
16
+ projectRoot,
17
+ consumer: 'line-memory',
18
+ });
19
+ }
5
20
  const EXIT = {
6
21
  ok: 0, usage: 2, unsupported: 3, unavailable: 4, contract: 5, storage: 6,
7
22
  locked: 7, coverage: 8,
@@ -406,11 +421,14 @@ async function executeCommand(ctx, args) {
406
421
  const candidateId = requiredPositional(args, 0, 'candidate-id');
407
422
  const version = boundedInteger(requiredPositional(args, 1, 'version'), 1, 1, Number.MAX_SAFE_INTEGER, 'version');
408
423
  const consumer = requiredValue(args, '--consumer');
409
- const destination = new FilesystemMemoryDestination({
410
- projectRoot: ctx.cwd,
411
- consumer,
412
- manifestPath: resolveMemoryConsumerManifest(ctx.cwd, consumer),
413
- });
424
+ const manifestPath = resolveMemoryConsumerManifest(ctx.cwd, consumer);
425
+ const destination = consumer === 'line-memory'
426
+ ? await createLineMemoryPromotionDestination(ctx.cwd, manifestPath)
427
+ : new FilesystemMemoryDestination({
428
+ projectRoot: ctx.cwd,
429
+ consumer,
430
+ manifestPath,
431
+ });
414
432
  const scopedPromotionStore = {
415
433
  getCandidate: (id, candidateVersion) => repository.getCandidate(id, candidateVersion, workspaceId),
416
434
  getPromotionReceipt: (id, candidateVersion, namedConsumer) => repository.getCandidate(id, candidateVersion, workspaceId)
@@ -1147,9 +1147,18 @@ export const packagePluginHandler = {
1147
1147
  message: "Error: plugin name is required.\n\nRun `aiwg package-plugin --help` for usage.",
1148
1148
  };
1149
1149
  }
1150
+ const positionalSource = positional && (positional.includes('/') || positional.includes('\\'))
1151
+ ? positional
1152
+ : undefined;
1150
1153
  const normalizedArgs = hasExplicitPlugin
1151
1154
  ? ctx.args
1152
- : ["--plugin", positional, ...ctx.args.slice(1)];
1155
+ : positionalSource
1156
+ ? [
1157
+ "--plugin", path.basename(path.resolve(ctx.cwd, positionalSource)),
1158
+ "--source", positionalSource,
1159
+ ...ctx.args.slice(1),
1160
+ ]
1161
+ : ["--plugin", positional, ...ctx.args.slice(1)];
1153
1162
  const frameworkRoot = await getFrameworkRoot();
1154
1163
  const runner = createScriptRunner(frameworkRoot);
1155
1164
  return runner.run("tools/plugin/package-plugins.mjs", normalizedArgs, {