@aiwg/cli 2026.8.0 → 2026.8.2
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/README.md +33 -0
- package/agentic/code/providers/capability-matrix.yaml +511 -0
- package/agentic/code/providers/model-capabilities.v1.json +120 -0
- package/agentic/code/providers/model-catalog.v1.json +96 -0
- package/agentic/code/providers/model-policy-evaluations.v1.json +50 -0
- package/agentic/code/providers/premium-model-allowlist.v1.json +36 -0
- package/bin/aiwg.mjs +14 -10
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/artifacts/cli.js +2 -0
- package/dist/src/artifacts/types.js +4 -0
- package/dist/src/auth/client.js +209 -0
- package/dist/src/auth/config.js +38 -0
- package/dist/src/auth/credential-store.js +141 -0
- package/dist/src/auth/resource-credentials.js +25 -0
- package/dist/src/auth/types.js +2 -0
- package/dist/src/channel/manager.mjs +5 -5
- package/dist/src/cli/handlers/auth.js +125 -0
- package/dist/src/cli/handlers/help.js +1 -0
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/install.js +42 -4
- package/dist/src/cli/handlers/marketplace.js +375 -122
- package/dist/src/cli/handlers/resource-versions.js +2 -0
- package/dist/src/cli/handlers/sessions.js +23 -5
- package/dist/src/cli/handlers/subcommands.js +10 -1
- package/dist/src/cli/handlers/use.js +342 -43
- package/dist/src/config/gitignore.js +1 -0
- package/dist/src/extensions/commands/definitions.js +19 -0
- package/dist/src/marketplace/exchange.js +602 -0
- package/dist/src/marketplace/provenance-types.js +19 -0
- package/dist/src/marketplace/provenance.js +834 -0
- package/dist/src/memory/canonical-context.js +342 -0
- package/dist/src/memory/context-pack.js +282 -0
- package/dist/src/memory/index.js +4 -0
- package/dist/src/memory/intake.js +118 -0
- package/dist/src/packages/adapters/git.js +79 -29
- package/dist/src/packages/package-discovery.js +81 -0
- package/dist/src/packages/package-registry.js +2 -0
- package/dist/src/packages/registry.js +119 -20
- package/dist/src/resources/resolver.js +1 -0
- package/dist/src/resources/web-release.d.ts +3 -1
- package/dist/src/resources/web-release.js +14 -6
- package/dist/src/serve/agentic-sandbox-fleet-client.js +213 -0
- package/dist/src/serve/fleet-mission-conductor.js +293 -0
- package/dist/src/sessions/index.js +1 -0
- package/dist/src/sessions/output-registration.js +338 -0
- package/dist/src/sessions/promotion.js +73 -2
- package/dist/src/sessions/repository.js +2 -1
- package/dist/src/update/notifier.mjs +13 -2
- package/package.json +8 -1
- package/tools/_resolve-impl.mjs +74 -0
- package/tools/agents/deploy-agents.mjs +962 -0
- package/tools/agents/providers/base.mjs +2954 -0
- package/tools/agents/providers/claude.mjs +711 -0
- package/tools/agents/providers/codex.mjs +699 -0
- package/tools/agents/providers/copilot.mjs +659 -0
- package/tools/agents/providers/cursor.mjs +714 -0
- package/tools/agents/providers/factory.mjs +1130 -0
- package/tools/agents/providers/hermes.mjs +663 -0
- package/tools/agents/providers/hook-capabilities.mjs +85 -0
- package/tools/agents/providers/model-role.mjs +56 -0
- package/tools/agents/providers/openclaw-translator.mjs +348 -0
- package/tools/agents/providers/openclaw.mjs +680 -0
- package/tools/agents/providers/opencode.mjs +675 -0
- package/tools/agents/providers/openhuman.mjs +292 -0
- package/tools/agents/providers/warp.mjs +413 -0
- package/tools/agents/providers/windsurf.mjs +748 -0
- package/tools/commands/deploy-prompts-codex.mjs +336 -0
- package/tools/plugin/package-plugins.mjs +1013 -0
- package/tools/skills/deploy-skills-codex.mjs +571 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenHuman provider (tinyhumansai/openhuman) — Tier-1 deployment.
|
|
3
|
+
*
|
|
4
|
+
* OpenHuman is an OSS personal-AI runtime (Rust core + React/Tauri shell).
|
|
5
|
+
* This module wires AIWG into OpenHuman's user-global app roots:
|
|
6
|
+
*
|
|
7
|
+
* - agents -> no markdown persona deploy; OpenHuman native custom agents
|
|
8
|
+
* are TOML-only under ~/.openhuman/agents (Tier-2, #1559)
|
|
9
|
+
* - skills -> kernel: ~/.openhuman/skills/ (native user-scope scan root;
|
|
10
|
+
* visible in the OpenHuman Skills UI)
|
|
11
|
+
* standard: AIWG index/discovery only
|
|
12
|
+
* - commands -> no native command directory; command-skills deploy as skills
|
|
13
|
+
* - rules -> full bodies under ~/.openhuman/.aiwg/rules/ for `aiwg show`
|
|
14
|
+
*
|
|
15
|
+
* Decisions: ADR `.aiwg/architecture/adr-openhuman-agent-target.md`.
|
|
16
|
+
* Epic #1552 · this module: #1555.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import path from 'path';
|
|
20
|
+
import os from 'os';
|
|
21
|
+
import {
|
|
22
|
+
ensureDir,
|
|
23
|
+
deployFiles,
|
|
24
|
+
deploySkillsWithKernelRouting,
|
|
25
|
+
createAgentsMdFromTemplate,
|
|
26
|
+
getAddonAgentFiles,
|
|
27
|
+
getAddonCommandFiles,
|
|
28
|
+
getAddonSkillDirs,
|
|
29
|
+
getAddonRuleFiles,
|
|
30
|
+
collectFrameworkArtifacts,
|
|
31
|
+
normalizeDeploymentMode,
|
|
32
|
+
cleanupOldRuleFiles,
|
|
33
|
+
filterCommandsAgainstSkills,
|
|
34
|
+
resolveAiwgRoot,
|
|
35
|
+
} from './base.mjs';
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Provider Configuration
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
export const name = 'openhuman';
|
|
42
|
+
export const aliases = [];
|
|
43
|
+
|
|
44
|
+
export const paths = {
|
|
45
|
+
// OpenHuman's native custom-agent surface is TOML-only under
|
|
46
|
+
// ~/.openhuman/agents. Markdown personas are not a project-level OpenHuman
|
|
47
|
+
// install target.
|
|
48
|
+
agents: '',
|
|
49
|
+
// OpenHuman has no native command surface. Empty path => no discrete command
|
|
50
|
+
// files; command-skills are reachable only through the kernel skill copy or
|
|
51
|
+
// AIWG index/discovery.
|
|
52
|
+
commands: '',
|
|
53
|
+
// Standard (non-kernel) skills are not copied by default. `--copy-all`
|
|
54
|
+
// explicitly opts into this user-scoped mirror for offline/discovery use.
|
|
55
|
+
skills: path.join(os.homedir(), '.openhuman', '.aiwg', 'skills'),
|
|
56
|
+
// Full rule bodies for `aiwg show rule`.
|
|
57
|
+
rules: path.join(os.homedir(), '.openhuman', '.aiwg', 'rules'),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// OpenHuman's native user-scope scan root for kernel skills.
|
|
61
|
+
export const kernelSkillsPath = path.join(os.homedir(), '.openhuman', 'skills');
|
|
62
|
+
|
|
63
|
+
export const support = {
|
|
64
|
+
agents: 'none', // Native TOML harness agents are emitted by the CLI
|
|
65
|
+
commands: 'none',
|
|
66
|
+
skills: 'native', // .openhuman/skills/ natively scanned
|
|
67
|
+
rules: 'indexed', // `aiwg show rule`
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const capabilities = {
|
|
71
|
+
skills: true,
|
|
72
|
+
rules: true,
|
|
73
|
+
aggregatedOutput: false,
|
|
74
|
+
yamlFormat: false,
|
|
75
|
+
homeDirectoryDeploy: true,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// Model Mapping
|
|
80
|
+
// ============================================================================
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* OpenHuman uses its own model namespace (neocortex-*, router hints
|
|
84
|
+
* reasoning/coding/agentic/local). AIWG `sonnet/opus/haiku` do not map cleanly.
|
|
85
|
+
* Markdown personas are not deployed for OpenHuman; native harness agents
|
|
86
|
+
* inherit the parent model (ModelSpec::Inherit) when `[model]` is omitted.
|
|
87
|
+
* See ADR adr-openhuman-agent-target.
|
|
88
|
+
*/
|
|
89
|
+
export function mapModel(originalModel) {
|
|
90
|
+
return originalModel;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// Content Transformation
|
|
95
|
+
// ============================================================================
|
|
96
|
+
|
|
97
|
+
/** Markdown personas are not a supported OpenHuman install target. */
|
|
98
|
+
export function transformAgent(srcPath, content) {
|
|
99
|
+
return content;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function transformCommand(srcPath, content) {
|
|
103
|
+
return content;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function transformSkillFrontmatter(content) {
|
|
107
|
+
if (!content.startsWith('---\n')) return content;
|
|
108
|
+
const end = content.indexOf('\n---', 4);
|
|
109
|
+
if (end < 0) return content;
|
|
110
|
+
|
|
111
|
+
let fm = content.slice(4, end);
|
|
112
|
+
const body = content.slice(end);
|
|
113
|
+
|
|
114
|
+
// OpenHuman currently classifies any SKILL.md with non-empty `platforms` as
|
|
115
|
+
// Hermes format. AIWG deploys directly into OpenHuman's user-global scan root,
|
|
116
|
+
// so the platform hint is not needed in the deployed copy and would mislabel
|
|
117
|
+
// the UI badge.
|
|
118
|
+
fm = fm
|
|
119
|
+
.replace(/^platforms:\s*\[[^\]]*\]\n?/m, '')
|
|
120
|
+
.replace(/^platforms:\s*\n(?:[ \t]+-[ \t]+\S[^\n]*\n?)*/m, '');
|
|
121
|
+
|
|
122
|
+
return `---\n${fm.trimEnd()}\n${body}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ============================================================================
|
|
126
|
+
// Deployment
|
|
127
|
+
// ============================================================================
|
|
128
|
+
|
|
129
|
+
export function deployAgents(agentFiles, targetDir, opts) {
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function deployCommands(commandFiles, targetDir, opts) {
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Kernel-vs-standard skill routing (#1212/#1216):
|
|
139
|
+
* - kernel → ~/.openhuman/skills/ (native UI scan root)
|
|
140
|
+
* - standard → not copied by default (AIWG index/discovery)
|
|
141
|
+
* → ~/.openhuman/.aiwg/skills/ with explicit --copy-all
|
|
142
|
+
*/
|
|
143
|
+
export function deploySkills(skillDirs, targetDir, opts) {
|
|
144
|
+
const standardDestDir = path.isAbsolute(paths.skills)
|
|
145
|
+
? paths.skills
|
|
146
|
+
: path.join(targetDir, paths.skills);
|
|
147
|
+
const kernelDestDir = path.isAbsolute(kernelSkillsPath)
|
|
148
|
+
? kernelSkillsPath
|
|
149
|
+
: path.join(targetDir, kernelSkillsPath);
|
|
150
|
+
return deploySkillsWithKernelRouting(skillDirs, standardDestDir, kernelDestDir, {
|
|
151
|
+
...opts,
|
|
152
|
+
copyStandardSkills: opts.copyStandardSkills === true,
|
|
153
|
+
transformSkillMd: transformSkillFrontmatter,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function deployRules(ruleFiles, targetDir, opts) {
|
|
158
|
+
const destDir = path.isAbsolute(paths.rules)
|
|
159
|
+
? paths.rules
|
|
160
|
+
: path.join(targetDir, paths.rules);
|
|
161
|
+
ensureDir(destDir, opts.dryRun);
|
|
162
|
+
cleanupOldRuleFiles(destDir, opts);
|
|
163
|
+
return deployFiles(ruleFiles, destDir, opts, transformAgent);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function createAgentsMd(target, srcRoot, dryRun) {
|
|
167
|
+
const aiwgRoot = resolveAiwgRoot(srcRoot) || srcRoot;
|
|
168
|
+
createAgentsMdFromTemplate(target, aiwgRoot, 'openhuman/AGENTS.md.aiwg-template', dryRun);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export async function postDeploy(targetDir, opts) {
|
|
172
|
+
if (
|
|
173
|
+
opts.createAgentsMd ||
|
|
174
|
+
(!opts.commandsOnly && !opts.skillsOnly && !opts.rulesOnly)
|
|
175
|
+
) {
|
|
176
|
+
createAgentsMd(targetDir, opts.srcRoot, opts.dryRun);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function getFileExtension() {
|
|
181
|
+
return '.md';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// Main Deploy Function
|
|
186
|
+
// ============================================================================
|
|
187
|
+
|
|
188
|
+
export async function deploy(opts) {
|
|
189
|
+
const {
|
|
190
|
+
srcRoot,
|
|
191
|
+
target,
|
|
192
|
+
mode,
|
|
193
|
+
deployCommands: shouldDeployCommands,
|
|
194
|
+
deploySkills: shouldDeploySkills,
|
|
195
|
+
deployRules: shouldDeployRules,
|
|
196
|
+
commandsOnly,
|
|
197
|
+
skillsOnly,
|
|
198
|
+
rulesOnly,
|
|
199
|
+
} = opts;
|
|
200
|
+
|
|
201
|
+
console.log(`\n=== OpenHuman Provider ===`);
|
|
202
|
+
console.log(`Target: ${target}`);
|
|
203
|
+
console.log(`Mode: ${mode}`);
|
|
204
|
+
|
|
205
|
+
const agentFiles = [];
|
|
206
|
+
const commandFiles = [];
|
|
207
|
+
const ruleFiles = [];
|
|
208
|
+
const skillDirs = [];
|
|
209
|
+
const normalizedMode = normalizeDeploymentMode(mode);
|
|
210
|
+
|
|
211
|
+
// Addon artifacts (dynamically discovered)
|
|
212
|
+
if (['general', 'sdlc', 'both', 'all'].includes(normalizedMode)) {
|
|
213
|
+
agentFiles.push(...getAddonAgentFiles(srcRoot));
|
|
214
|
+
if (shouldDeployCommands || commandsOnly) commandFiles.push(...getAddonCommandFiles(srcRoot));
|
|
215
|
+
if (shouldDeployRules || rulesOnly) ruleFiles.push(...getAddonRuleFiles(srcRoot));
|
|
216
|
+
if (shouldDeploySkills || skillsOnly) skillDirs.push(...getAddonSkillDirs(srcRoot));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Framework artifacts
|
|
220
|
+
const fw = collectFrameworkArtifacts(srcRoot, normalizedMode, {
|
|
221
|
+
includeAgents: true,
|
|
222
|
+
includeCommands: shouldDeployCommands || commandsOnly,
|
|
223
|
+
includeSkills: shouldDeploySkills || skillsOnly,
|
|
224
|
+
includeRules: shouldDeployRules || rulesOnly,
|
|
225
|
+
recursiveCommands: true,
|
|
226
|
+
consolidatedSdlcRules: true,
|
|
227
|
+
});
|
|
228
|
+
agentFiles.push(...fw.agents);
|
|
229
|
+
commandFiles.push(...fw.commands);
|
|
230
|
+
skillDirs.push(...fw.skills);
|
|
231
|
+
ruleFiles.push(...fw.rules);
|
|
232
|
+
|
|
233
|
+
if (!commandsOnly && !skillsOnly && !rulesOnly) {
|
|
234
|
+
console.log(`\nSkipping markdown agents: OpenHuman native agents are TOML-only under ~/.openhuman/agents.`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Commands take a back seat to skills where they collide.
|
|
238
|
+
const filteredCommands = (shouldDeploySkills || skillsOnly)
|
|
239
|
+
? filterCommandsAgainstSkills(commandFiles, skillDirs)
|
|
240
|
+
: commandFiles;
|
|
241
|
+
|
|
242
|
+
// No native command directory. Command-skills reach OpenHuman only when they
|
|
243
|
+
// are kernel skills copied to ~/.openhuman/skills; otherwise AIWG discovery
|
|
244
|
+
// finds them on demand.
|
|
245
|
+
if ((shouldDeployCommands || commandsOnly) && paths.commands) {
|
|
246
|
+
console.log(`\nDeploying ${filteredCommands.length} commands...`);
|
|
247
|
+
deployCommands(filteredCommands, target, opts);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (shouldDeploySkills || skillsOnly) {
|
|
251
|
+
console.log(
|
|
252
|
+
`\nDeploying ${skillDirs.length} skills (kernel → ~/.openhuman/skills, standard → ${
|
|
253
|
+
opts.copyStandardSkills ? '~/.openhuman/.aiwg/skills via --copy-all' : 'index/discovery'
|
|
254
|
+
})...`,
|
|
255
|
+
);
|
|
256
|
+
deploySkills(skillDirs, target, opts);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (shouldDeployRules || rulesOnly) {
|
|
260
|
+
console.log(`\nDeploying ${ruleFiles.length} rules for AIWG discovery...`);
|
|
261
|
+
deployRules(ruleFiles, target, opts);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
await postDeploy(target, opts);
|
|
265
|
+
|
|
266
|
+
console.log('\n=== OpenHuman deployment complete ===\n');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ============================================================================
|
|
270
|
+
// Default Export
|
|
271
|
+
// ============================================================================
|
|
272
|
+
|
|
273
|
+
export default {
|
|
274
|
+
name,
|
|
275
|
+
aliases,
|
|
276
|
+
paths,
|
|
277
|
+
kernelSkillsPath,
|
|
278
|
+
support,
|
|
279
|
+
capabilities,
|
|
280
|
+
transformAgent,
|
|
281
|
+
transformCommand,
|
|
282
|
+
mapModel,
|
|
283
|
+
deployAgents,
|
|
284
|
+
deployCommands,
|
|
285
|
+
deploySkills,
|
|
286
|
+
deployRules,
|
|
287
|
+
createAgentsMd,
|
|
288
|
+
transformSkillFrontmatter,
|
|
289
|
+
postDeploy,
|
|
290
|
+
getFileExtension,
|
|
291
|
+
deploy,
|
|
292
|
+
};
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warp Terminal Provider
|
|
3
|
+
*
|
|
4
|
+
* Supports both aggregated (WARP.md) and discrete file deployment.
|
|
5
|
+
* Aggregates agents and commands into WARP.md via external script,
|
|
6
|
+
* while also deploying discrete files for all 4 artifact types.
|
|
7
|
+
*
|
|
8
|
+
* Deployment paths:
|
|
9
|
+
* - Agents: WARP.md (aggregated only — Warp does not discover .warp/agents/)
|
|
10
|
+
* - Commands: WARP.md (aggregated only — Warp does not discover .warp/commands/)
|
|
11
|
+
* - Skills: .warp/skills/ (discrete — natively discovered by Warp)
|
|
12
|
+
* - Skills: .agents/skills/ (cross-agent compatibility path)
|
|
13
|
+
* - Rules: WARP.md (aggregated only — Warp does not discover .warp/rules/)
|
|
14
|
+
*
|
|
15
|
+
* Special features:
|
|
16
|
+
* - Aggregated WARP.md for agents, commands, and rules
|
|
17
|
+
* - Discrete .warp/skills/ for natively discovered skills
|
|
18
|
+
* - Section preservation (user vs AIWG managed sections in WARP.md)
|
|
19
|
+
* - Backup creation with timestamp
|
|
20
|
+
* - CLAUDE.md symlink support
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import realFs from 'fs';
|
|
24
|
+
import { createRequire } from 'module';
|
|
25
|
+
const _require = createRequire(import.meta.url);
|
|
26
|
+
let fs;
|
|
27
|
+
try { const gfs = _require('graceful-fs'); gfs.gracefulify(realFs); fs = realFs; } catch { fs = realFs; }
|
|
28
|
+
import path from 'path';
|
|
29
|
+
import { spawn } from 'child_process';
|
|
30
|
+
import { classifyModelRole, modelForRole } from './model-role.mjs';
|
|
31
|
+
import {
|
|
32
|
+
ensureDir,
|
|
33
|
+
listMdFiles,
|
|
34
|
+
listSkillDirs,
|
|
35
|
+
deploySkillDir,
|
|
36
|
+
deploySkillsWithKernelRouting,
|
|
37
|
+
isKernelSkill,
|
|
38
|
+
pruneStaleAiwgSkills,
|
|
39
|
+
computeAllKernelNames,
|
|
40
|
+
initializeFrameworkWorkspace,
|
|
41
|
+
getAddonAgentFiles,
|
|
42
|
+
getAddonCommandFiles,
|
|
43
|
+
getAddonSkillDirs,
|
|
44
|
+
getAddonRuleFiles,
|
|
45
|
+
normalizeDeploymentMode,
|
|
46
|
+
collectFrameworkArtifacts
|
|
47
|
+
} from './base.mjs';
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Provider Configuration
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
export const name = 'warp';
|
|
54
|
+
export const aliases = [];
|
|
55
|
+
|
|
56
|
+
export const paths = {
|
|
57
|
+
agents: '.warp/agents/',
|
|
58
|
+
commands: '.warp/commands/',
|
|
59
|
+
// Skills sequestered under .warp/.aiwg/skills/ — index-driven discovery (#1212).
|
|
60
|
+
skills: '.warp/.aiwg/skills/',
|
|
61
|
+
crossAgentSkills: '.agents/skills/', // Cross-agent compatibility path (#771)
|
|
62
|
+
rules: '.warp/rules/',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Kernel skills (always-loaded) deploy to the platform-native dir.
|
|
66
|
+
export const kernelSkillsPath = '.warp/skills/';
|
|
67
|
+
|
|
68
|
+
export const support = {
|
|
69
|
+
agents: 'aggregated', // WARP.md primary; files mirrored for portability
|
|
70
|
+
commands: 'conventional', // .warp/commands/ mirror for slash-command parity
|
|
71
|
+
skills: 'native', // .warp/skills/ — natively discovered by Warp
|
|
72
|
+
rules: 'aggregated' // WARP.md primary; rule files mirrored for portability
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const capabilities = {
|
|
76
|
+
skills: true,
|
|
77
|
+
rules: true,
|
|
78
|
+
aggregatedOutput: true, // All content in single WARP.md file
|
|
79
|
+
yamlFormat: false
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// ============================================================================
|
|
83
|
+
// Model Handling
|
|
84
|
+
// ============================================================================
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Replace model in frontmatter based on role classification
|
|
88
|
+
* opus -> reasoning, sonnet -> coding, haiku -> efficiency
|
|
89
|
+
*/
|
|
90
|
+
export function replaceModelFrontmatter(content, models) {
|
|
91
|
+
const fmStart = content.indexOf('---');
|
|
92
|
+
if (fmStart !== 0) return content;
|
|
93
|
+
const fmEnd = content.indexOf('\n---', 3);
|
|
94
|
+
if (fmEnd === -1) return content;
|
|
95
|
+
|
|
96
|
+
const header = content.slice(0, fmEnd + 4);
|
|
97
|
+
const body = content.slice(fmEnd + 4);
|
|
98
|
+
|
|
99
|
+
const modelMatch = header.match(/^model:\s*([^\n]+)$/m);
|
|
100
|
+
let newModel = null;
|
|
101
|
+
|
|
102
|
+
if (modelMatch) {
|
|
103
|
+
const orig = modelMatch[1].trim();
|
|
104
|
+
const role = classifyModelRole(orig);
|
|
105
|
+
|
|
106
|
+
if (role === 'reasoning') newModel = models.reasoning;
|
|
107
|
+
else if (role === 'efficiency') newModel = models.efficiency;
|
|
108
|
+
else if (role === 'coding') newModel = models.coding;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!newModel) return content;
|
|
112
|
+
const updatedHeader = header.replace(/^model:\s*[^\n]+$/m, `model: ${newModel}`);
|
|
113
|
+
return updatedHeader + body;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Map model shorthand to Warp format
|
|
118
|
+
*/
|
|
119
|
+
export function mapModel(shorthand, modelCfg, modelsConfig) {
|
|
120
|
+
// If overrides specified, use them
|
|
121
|
+
if (modelCfg.reasoningModel || modelCfg.codingModel || modelCfg.efficiencyModel) {
|
|
122
|
+
return modelForRole(shorthand, {
|
|
123
|
+
reasoning: modelCfg.reasoningModel || 'opus',
|
|
124
|
+
coding: modelCfg.codingModel || 'sonnet',
|
|
125
|
+
efficiency: modelCfg.efficiencyModel || 'haiku',
|
|
126
|
+
}, { defaultRole: 'coding' }) ?? shorthand;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return shorthand || 'sonnet';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Content Transformation
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Transform agent content for Warp
|
|
138
|
+
*/
|
|
139
|
+
export function transformAgent(srcPath, content, opts) {
|
|
140
|
+
const { reasoningModel, codingModel, efficiencyModel } = opts;
|
|
141
|
+
|
|
142
|
+
// Only transform if model overrides specified
|
|
143
|
+
if (reasoningModel || codingModel || efficiencyModel) {
|
|
144
|
+
const models = {
|
|
145
|
+
reasoning: reasoningModel || 'opus',
|
|
146
|
+
coding: codingModel || 'sonnet',
|
|
147
|
+
efficiency: efficiencyModel || 'haiku'
|
|
148
|
+
};
|
|
149
|
+
return replaceModelFrontmatter(content, models);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return content;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Transform command content for Warp
|
|
157
|
+
*/
|
|
158
|
+
export function transformCommand(srcPath, content, opts) {
|
|
159
|
+
return transformAgent(srcPath, content, opts);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ============================================================================
|
|
163
|
+
// Deployment Functions
|
|
164
|
+
// ============================================================================
|
|
165
|
+
|
|
166
|
+
// Warp does not discover .warp/agents/, .warp/commands/, or .warp/rules/.
|
|
167
|
+
// Agents, commands, and rules are delivered exclusively via aggregated WARP.md.
|
|
168
|
+
// Only skills (.warp/skills/) are natively discovered.
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Deploy skills to .warp/skills/ (primary) and .agents/skills/ (cross-agent compatibility).
|
|
172
|
+
* The .agents/skills/ path is an interop convention for projects using multiple AI coding tools.
|
|
173
|
+
*/
|
|
174
|
+
export function deploySkills(skillDirs, targetDir, opts) {
|
|
175
|
+
// Primary: kernel-vs-standard routing (#1212/#1216)
|
|
176
|
+
// - kernel skills → .warp/skills/ (platform-native, always-loaded)
|
|
177
|
+
// - standard → .warp/.aiwg/skills/ (index-discoverable)
|
|
178
|
+
const standardDestDir = path.join(targetDir, paths.skills);
|
|
179
|
+
const kernelDestDir = path.join(targetDir, kernelSkillsPath);
|
|
180
|
+
deploySkillsWithKernelRouting(skillDirs, standardDestDir, kernelDestDir, opts);
|
|
181
|
+
|
|
182
|
+
// Cross-agent compatibility: .agents/skills/
|
|
183
|
+
const crossAgentDir = path.join(targetDir, paths.crossAgentSkills);
|
|
184
|
+
ensureDir(crossAgentDir, opts.dryRun);
|
|
185
|
+
if (!opts.dryRun) {
|
|
186
|
+
console.log(`Deploying cross-agent skills to ${path.relative(process.cwd(), crossAgentDir)}...`);
|
|
187
|
+
} else {
|
|
188
|
+
console.log(`[dry-run] Would deploy cross-agent skills to .agents/skills/`);
|
|
189
|
+
}
|
|
190
|
+
for (const skillDir of skillDirs) {
|
|
191
|
+
deploySkillDir(skillDir, crossAgentDir, opts);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Deploy via external setup-warp.mjs script
|
|
197
|
+
* This generates the aggregated WARP.md file
|
|
198
|
+
*/
|
|
199
|
+
export async function deployWarp(targetDir, srcRoot, opts) {
|
|
200
|
+
const scriptPath = path.join(srcRoot, 'tools', 'warp', 'setup-warp.mjs');
|
|
201
|
+
|
|
202
|
+
if (!fs.existsSync(scriptPath)) {
|
|
203
|
+
console.warn(`Warp setup script not found at ${scriptPath}`);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
console.log('\nGenerating aggregated WARP.md...');
|
|
208
|
+
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
const args = ['--target', targetDir, '--source', srcRoot];
|
|
211
|
+
if (opts.dryRun) args.push('--dry-run');
|
|
212
|
+
if (opts.force) args.push('--force');
|
|
213
|
+
if (opts.mode) args.push('--mode', opts.mode);
|
|
214
|
+
|
|
215
|
+
const child = spawn('node', [scriptPath, ...args], {
|
|
216
|
+
stdio: 'inherit',
|
|
217
|
+
cwd: srcRoot
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
child.on('close', (code) => {
|
|
221
|
+
if (code === 0) resolve();
|
|
222
|
+
else reject(new Error(`setup-warp.mjs exited with code ${code}`));
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
child.on('error', reject);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ============================================================================
|
|
230
|
+
// AGENTS.md (not used for Warp - content goes in WARP.md)
|
|
231
|
+
// ============================================================================
|
|
232
|
+
|
|
233
|
+
export function createAgentsMd(target, srcRoot, dryRun) {
|
|
234
|
+
console.log('Warp uses WARP.md instead of AGENTS.md');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ============================================================================
|
|
238
|
+
// Post-Deployment
|
|
239
|
+
// ============================================================================
|
|
240
|
+
|
|
241
|
+
export async function postDeploy(targetDir, opts) {
|
|
242
|
+
initializeFrameworkWorkspace(targetDir, opts.mode, opts.dryRun, opts.srcRoot);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// File Extension
|
|
247
|
+
// ============================================================================
|
|
248
|
+
|
|
249
|
+
export function getFileExtension(type) {
|
|
250
|
+
return '.md';
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ============================================================================
|
|
254
|
+
// Main Deploy Function
|
|
255
|
+
// ============================================================================
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Main deployment function for Warp provider
|
|
259
|
+
* Deploys discrete files for all artifact types, then generates aggregated WARP.md
|
|
260
|
+
*/
|
|
261
|
+
export async function deploy(opts) {
|
|
262
|
+
const {
|
|
263
|
+
srcRoot,
|
|
264
|
+
target,
|
|
265
|
+
mode,
|
|
266
|
+
deployCommands: shouldDeployCommands,
|
|
267
|
+
deploySkills: shouldDeploySkills,
|
|
268
|
+
deployRules: shouldDeployRules,
|
|
269
|
+
commandsOnly,
|
|
270
|
+
skillsOnly,
|
|
271
|
+
rulesOnly,
|
|
272
|
+
dryRun
|
|
273
|
+
} = opts;
|
|
274
|
+
|
|
275
|
+
console.log(`\n=== Warp Terminal Provider ===`);
|
|
276
|
+
console.log(`Target: ${target}`);
|
|
277
|
+
console.log(`Mode: ${mode}`);
|
|
278
|
+
|
|
279
|
+
// Collect source files based on mode
|
|
280
|
+
const agentFiles = [];
|
|
281
|
+
const commandFiles = [];
|
|
282
|
+
const skillDirs = [];
|
|
283
|
+
const ruleFiles = [];
|
|
284
|
+
|
|
285
|
+
// Check for addon-style directory structure (direct agents/, commands/, skills/ subdirs)
|
|
286
|
+
// This handles deployment when --source points to an addon directory
|
|
287
|
+
const isAddonSource = fs.existsSync(path.join(srcRoot, 'agents')) ||
|
|
288
|
+
fs.existsSync(path.join(srcRoot, 'commands')) ||
|
|
289
|
+
fs.existsSync(path.join(srcRoot, 'skills'));
|
|
290
|
+
|
|
291
|
+
if (isAddonSource) {
|
|
292
|
+
// Deploy from addon-style directory structure
|
|
293
|
+
const addonAgentsDir = path.join(srcRoot, 'agents');
|
|
294
|
+
if (fs.existsSync(addonAgentsDir)) {
|
|
295
|
+
agentFiles.push(...listMdFiles(addonAgentsDir));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (shouldDeployCommands || commandsOnly) {
|
|
299
|
+
const addonCommandsDir = path.join(srcRoot, 'commands');
|
|
300
|
+
if (fs.existsSync(addonCommandsDir)) {
|
|
301
|
+
commandFiles.push(...listMdFiles(addonCommandsDir));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (shouldDeploySkills || skillsOnly) {
|
|
306
|
+
const addonSkillsDir = path.join(srcRoot, 'skills');
|
|
307
|
+
if (fs.existsSync(addonSkillsDir)) {
|
|
308
|
+
skillDirs.push(...listSkillDirs(addonSkillsDir));
|
|
309
|
+
|
|
310
|
+
// Holistic post-deploy cleanup of stale AIWG-managed kernel
|
|
311
|
+
// skills (renamed/removed sources). Uses the global kernel set
|
|
312
|
+
// (computeAllKernelNames walks all source frameworks/addons),
|
|
313
|
+
// not just this-call's skillDirs, because aiwg use invokes
|
|
314
|
+
// deploy-agents.mjs multiple times.
|
|
315
|
+
{
|
|
316
|
+
const _kernelDestDir = path.isAbsolute(kernelSkillsPath)
|
|
317
|
+
? kernelSkillsPath
|
|
318
|
+
: path.join(target, kernelSkillsPath);
|
|
319
|
+
pruneStaleAiwgSkills(_kernelDestDir, computeAllKernelNames(srcRoot), opts);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (shouldDeployRules || rulesOnly) {
|
|
325
|
+
const addonRulesDir = path.join(srcRoot, 'rules');
|
|
326
|
+
if (fs.existsSync(addonRulesDir)) {
|
|
327
|
+
ruleFiles.push(...listMdFiles(addonRulesDir));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const normalizedMode = normalizeDeploymentMode(mode);
|
|
333
|
+
|
|
334
|
+
// All addons (dynamically discovered)
|
|
335
|
+
if (normalizedMode === 'general' || normalizedMode === 'sdlc' || normalizedMode === 'both' || normalizedMode === 'all') {
|
|
336
|
+
agentFiles.push(...getAddonAgentFiles(srcRoot));
|
|
337
|
+
|
|
338
|
+
if (shouldDeployCommands || commandsOnly) {
|
|
339
|
+
commandFiles.push(...getAddonCommandFiles(srcRoot));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (shouldDeploySkills || skillsOnly) {
|
|
343
|
+
skillDirs.push(...getAddonSkillDirs(srcRoot));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (shouldDeployRules || rulesOnly) {
|
|
347
|
+
ruleFiles.push(...getAddonRuleFiles(srcRoot));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const frameworkArtifacts = collectFrameworkArtifacts(srcRoot, normalizedMode, {
|
|
352
|
+
includeAgents: true,
|
|
353
|
+
includeCommands: shouldDeployCommands || commandsOnly,
|
|
354
|
+
includeSkills: shouldDeploySkills || skillsOnly,
|
|
355
|
+
includeRules: shouldDeployRules || rulesOnly,
|
|
356
|
+
recursiveCommands: true,
|
|
357
|
+
consolidatedSdlcRules: true
|
|
358
|
+
});
|
|
359
|
+
agentFiles.push(...frameworkArtifacts.agents);
|
|
360
|
+
commandFiles.push(...frameworkArtifacts.commands);
|
|
361
|
+
skillDirs.push(...frameworkArtifacts.skills);
|
|
362
|
+
ruleFiles.push(...frameworkArtifacts.rules);
|
|
363
|
+
|
|
364
|
+
// Warp only discovers .warp/skills/ natively.
|
|
365
|
+
// Agents, commands, and rules are delivered via aggregated WARP.md only.
|
|
366
|
+
console.log('\n--- Deploying discrete files (skills only) ---');
|
|
367
|
+
|
|
368
|
+
if (shouldDeploySkills || skillsOnly) {
|
|
369
|
+
console.log(`\nDeploying ${skillDirs.length} skills to .warp/skills/...`);
|
|
370
|
+
deploySkills(skillDirs, target, opts);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (!commandsOnly && !skillsOnly && !rulesOnly) {
|
|
374
|
+
console.log(`\nSkipping discrete agent deployment (Warp uses WARP.md)`);
|
|
375
|
+
}
|
|
376
|
+
if (shouldDeployCommands || commandsOnly) {
|
|
377
|
+
console.log(`\nSkipping discrete command deployment (Warp uses WARP.md)`);
|
|
378
|
+
}
|
|
379
|
+
if (shouldDeployRules || rulesOnly) {
|
|
380
|
+
console.log(`\nSkipping discrete rule deployment (Warp uses WARP.md)`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Generate aggregated WARP.md (existing behavior)
|
|
384
|
+
console.log('\n--- Generating aggregated output ---');
|
|
385
|
+
await deployWarp(target, srcRoot, opts);
|
|
386
|
+
|
|
387
|
+
// Post-deployment
|
|
388
|
+
await postDeploy(target, opts);
|
|
389
|
+
|
|
390
|
+
console.log('\n=== Warp deployment complete ===\n');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// ============================================================================
|
|
394
|
+
// Default Export
|
|
395
|
+
// ============================================================================
|
|
396
|
+
|
|
397
|
+
export default {
|
|
398
|
+
name,
|
|
399
|
+
aliases,
|
|
400
|
+
paths,
|
|
401
|
+
kernelSkillsPath,
|
|
402
|
+
support,
|
|
403
|
+
capabilities,
|
|
404
|
+
transformAgent,
|
|
405
|
+
transformCommand,
|
|
406
|
+
mapModel,
|
|
407
|
+
deploySkills,
|
|
408
|
+
deployWarp,
|
|
409
|
+
createAgentsMd,
|
|
410
|
+
postDeploy,
|
|
411
|
+
getFileExtension,
|
|
412
|
+
deploy
|
|
413
|
+
};
|