@orderful/droid 0.52.1 → 0.54.0

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.
@@ -33,6 +33,7 @@
33
33
  "./src/tools/share/skills/share/SKILL.md",
34
34
  "./src/tools/status-update/skills/status-update/SKILL.md",
35
35
  "./src/tools/tech-design/skills/tech-design/SKILL.md",
36
+ "./src/tools/webform/skills/webform/SKILL.md",
36
37
  "./src/tools/wrapup/skills/wrapup/SKILL.md"
37
38
  ],
38
39
  "commands": [
@@ -52,6 +53,7 @@
52
53
  "./src/tools/share/commands/share.md",
53
54
  "./src/tools/status-update/commands/status-update.md",
54
55
  "./src/tools/tech-design/commands/tech-design.md",
56
+ "./src/tools/webform/commands/webform.md",
55
57
  "./src/tools/wrapup/commands/wrapup.md"
56
58
  ],
57
59
  "agents": [
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @orderful/droid
2
2
 
3
+ ## 0.54.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#329](https://github.com/Orderful/droid/pull/329) [`ee57191`](https://github.com/Orderful/droid/commit/ee57191e4c13e23703df561b3d56182fe6da62b7) Thanks [@theabuitendyk](https://github.com/theabuitendyk)! - Add webform tool
8
+
9
+ ### Patch Changes
10
+
11
+ - [#326](https://github.com/Orderful/droid/pull/326) [`d5b2cca`](https://github.com/Orderful/droid/commit/d5b2ccabe1486086ec3f5f1bbd9c36a64a3387f0) Thanks [@frytyler](https://github.com/frytyler)! - Add findings-only and partial plan support to propose-plan skill
12
+
13
+ ## 0.53.0
14
+
15
+ ### Minor Changes
16
+
17
+ - [#325](https://github.com/Orderful/droid/pull/325) [`241a9ac`](https://github.com/Orderful/droid/commit/241a9acbfb9864c634fe9f858e19b594d80e83f9) Thanks [@frytyler](https://github.com/frytyler)! - Export tools + pack functions from package entry point and add `droid copy-skills` command for agents integration
18
+
19
+ ### Patch Changes
20
+
21
+ - [#323](https://github.com/Orderful/droid/pull/323) [`f1459be`](https://github.com/Orderful/droid/commit/f1459beecb6aa72c5fcc6ee552308a3d39f52aad) Thanks [@frytyler](https://github.com/frytyler)! - Add `planSummary` field to propose-plan evidence schema
22
+
3
23
  ## 0.52.1
4
24
 
5
25
  ### Patch Changes
package/README.md CHANGED
@@ -116,6 +116,7 @@ Browse available tools, see what's installed, and manage everything from one pla
116
116
  | **tech-design** | Three-document approach for technical designs | beta |
117
117
  | **wrapup** | Session wrap-up that captures decisions to persistent docs | alpha |
118
118
  | **status-update** | Generate and post project status updates to Slack | beta |
119
+ | **webform** | Generate PrintView webform templates for EDI transaction types | beta |
119
120
 
120
121
  ### Comments
121
122
 
@@ -187,7 +188,26 @@ Post project status updates to Slack:
187
188
  /status-update # Generate and post status update
188
189
  ```
189
190
 
190
- Pulls context from codex projects and Jira, formats with phase checklists, posts to Slack (or prints to terminal). Requires one-time setup:
191
+ Pulls context from codex projects and Jira, formats with phase checklists, posts to Slack (or prints to terminal).
192
+
193
+ ### Webform
194
+
195
+ Generate PrintView webform templates from Orderful JSON schemas and sample transactions:
196
+
197
+ ```bash
198
+ /webform 850 ~/Downloads/sample-850.json # Generate from sample
199
+ /webform 812 ~/Downloads/812.edi # Generate from EDI file
200
+ /webform 997 # Start (will ask for sample)
201
+ ```
202
+
203
+ Proposes a visual layout for approval, then generates template code with reusable subsection items. Requires configuration:
204
+
205
+ ```bash
206
+ droid config --set tools.webform.schema_repo="~/Projects/orderful-workspace"
207
+ droid config --set tools.webform.ui_repo="~/Projects/o2-app-ui"
208
+ ```
209
+
210
+ Requires one-time setup:
191
211
 
192
212
  ```bash
193
213
  droid auth slack # Set up Slack OAuth (per user)
package/dist/bin/droid.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/bin/droid.ts
4
4
  import { program } from "commander";
5
- import chalk13 from "chalk";
5
+ import chalk14 from "chalk";
6
6
 
7
7
  // src/commands/setup.ts
8
8
  import inquirer from "inquirer";
@@ -1410,6 +1410,39 @@ function findSkillPath(skillName) {
1410
1410
  }
1411
1411
  return null;
1412
1412
  }
1413
+ function getSkillPath(skillName) {
1414
+ const result = findSkillPath(skillName);
1415
+ return result?.skillDir ?? null;
1416
+ }
1417
+ function copySkillsToDir(skillNames, dest) {
1418
+ if (!existsSync7(dest)) {
1419
+ mkdirSync5(dest, { recursive: true });
1420
+ }
1421
+ const results = [];
1422
+ for (const name of skillNames) {
1423
+ const skillDir = getSkillPath(name);
1424
+ if (!skillDir) {
1425
+ results.push({
1426
+ name,
1427
+ success: false,
1428
+ error: `Skill '${name}' not found in bundled tools`
1429
+ });
1430
+ continue;
1431
+ }
1432
+ const targetDir = join8(dest, name);
1433
+ try {
1434
+ copyDirectoryRecursive(skillDir, targetDir, () => true);
1435
+ results.push({ name, success: true, dest: targetDir });
1436
+ } catch (err) {
1437
+ results.push({
1438
+ name,
1439
+ success: false,
1440
+ error: `Failed to copy: ${err}`
1441
+ });
1442
+ }
1443
+ }
1444
+ return results;
1445
+ }
1413
1446
  function getBundledSkills() {
1414
1447
  if (!existsSync7(BUNDLED_SKILLS_DIR)) {
1415
1448
  return [];
@@ -6101,6 +6134,52 @@ async function slackPostCommand(options) {
6101
6134
  }
6102
6135
  }
6103
6136
 
6137
+ // src/commands/copy-skills.ts
6138
+ import chalk13 from "chalk";
6139
+ import { readFileSync as readFileSync13 } from "fs";
6140
+ function copySkillsCommand(options) {
6141
+ const { dest, manifest, names } = options;
6142
+ let skillNames;
6143
+ if (manifest) {
6144
+ try {
6145
+ const content = readFileSync13(manifest, "utf-8");
6146
+ skillNames = JSON.parse(content);
6147
+ if (!Array.isArray(skillNames)) {
6148
+ console.error(
6149
+ chalk13.red("Manifest must be a JSON array of skill names")
6150
+ );
6151
+ process.exit(1);
6152
+ }
6153
+ } catch (err) {
6154
+ console.error(chalk13.red(`Failed to read manifest: ${err}`));
6155
+ process.exit(1);
6156
+ }
6157
+ } else if (names?.length) {
6158
+ skillNames = names;
6159
+ } else {
6160
+ console.error(
6161
+ chalk13.red("Provide either --manifest <file> or --names <names...>")
6162
+ );
6163
+ process.exit(1);
6164
+ }
6165
+ if (skillNames.length === 0) {
6166
+ console.log(chalk13.yellow("No skills to copy."));
6167
+ return;
6168
+ }
6169
+ const results = copySkillsToDir(skillNames, dest);
6170
+ for (const result of results) {
6171
+ if (result.success) {
6172
+ console.log(chalk13.green(` \u2713 ${result.name} \u2192 ${result.dest}`));
6173
+ } else {
6174
+ console.error(chalk13.red(` \u2717 ${result.name}: ${result.error}`));
6175
+ }
6176
+ }
6177
+ const failed = results.filter((r) => !r.success);
6178
+ if (failed.length > 0) {
6179
+ process.exit(1);
6180
+ }
6181
+ }
6182
+
6104
6183
  // src/bin/droid.ts
6105
6184
  var version = getVersion();
6106
6185
  program.name("droid").description("Droid, teaching your AI new tricks").version(version);
@@ -6121,6 +6200,7 @@ program.command("update").description("Update droid and installed tools").option
6121
6200
  program.command("tui").description("Launch interactive TUI dashboard").action(tuiCommand);
6122
6201
  program.command("pack").description("Create zip packs for distribution").argument("[audience]", "Target audience (e.g., engineering, customer-support)").option("-l, --list", "List available audiences and tool counts").option("-t, --tool <name>", "Pack a single tool by name").option("-o, --output <dir>", "Output directory (default: cwd)").action(packCommand);
6123
6202
  program.command("exec <tool> <script>").description("Execute a tool script").argument("[args...]", "Arguments to pass to the script").allowUnknownOption().action(execCommand);
6203
+ program.command("copy-skills").description("Copy bundled skills to a destination directory").requiredOption("-d, --dest <dir>", "Destination directory").option("-m, --manifest <file>", "JSON file with array of skill names").option("-n, --names <names...>", "Skill names to copy").action(copySkillsCommand);
6124
6204
  var integrations = program.command("integrations").description("Manage external service integrations");
6125
6205
  var integrationsSetup = integrations.command("setup").description("Set up an integration");
6126
6206
  integrationsSetup.command("slack").description("Set up Slack integration").action(integrationsSetupSlackCommand);
@@ -6132,8 +6212,8 @@ if (configExists()) {
6132
6212
  const config = loadConfig();
6133
6213
  const newPlatforms = syncNewPlatforms(config);
6134
6214
  if (newPlatforms.length > 0) {
6135
- console.log(chalk13.green(`\u2713 Detected new platform(s): ${newPlatforms.join(", ")}`));
6136
- console.log(chalk13.gray(" Synced installed tools to new platform(s)\n"));
6215
+ console.log(chalk14.green(`\u2713 Detected new platform(s): ${newPlatforms.join(", ")}`));
6216
+ console.log(chalk14.gray(" Synced installed tools to new platform(s)\n"));
6137
6217
  saveConfig(config);
6138
6218
  }
6139
6219
  }
@@ -0,0 +1,15 @@
1
+ interface CopySkillsOptions {
2
+ dest: string;
3
+ manifest?: string;
4
+ names?: string[];
5
+ }
6
+ /**
7
+ * Copy bundled skills to a destination directory.
8
+ *
9
+ * Usage:
10
+ * droid copy-skills -d dist/assets/skills -m droid-skills.json
11
+ * droid copy-skills -d dist/assets/skills -n propose-plan edi-schema
12
+ */
13
+ export declare function copySkillsCommand(options: CopySkillsOptions): void;
14
+ export {};
15
+ //# sourceMappingURL=copy-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-skills.d.ts","sourceRoot":"","sources":["../../src/commands/copy-skills.ts"],"names":[],"mappings":"AAIA,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAgDlE"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from './lib/types';
2
2
  export * from './lib/config';
3
3
  export * from './lib/skills';
4
+ export * from './lib/tools';
5
+ export * from './lib/pack';
4
6
  export * from './lib/version';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -602,6 +602,9 @@ async function checkForUpdates() {
602
602
  // src/lib/tools.ts
603
603
  var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
604
604
  var BUNDLED_TOOLS_DIR = join5(__dirname2, "../tools");
605
+ function getBundledToolsDir() {
606
+ return BUNDLED_TOOLS_DIR;
607
+ }
605
608
  function loadToolManifest(toolDir) {
606
609
  const manifestPath = join5(toolDir, "TOOL.yaml");
607
610
  if (!existsSync4(manifestPath)) {
@@ -645,6 +648,58 @@ function isToolInstalled(toolName) {
645
648
  const requiredSkills = tool.includes.skills.filter((s) => s.required).map((s) => s.name);
646
649
  return requiredSkills.some((skillName) => skillName in installedTools);
647
650
  }
651
+ function getInstalledToolVersion(toolName) {
652
+ const config = loadConfig();
653
+ const installedTools = getPlatformTools(config);
654
+ const tool = getBundledTools().find((t) => t.name === toolName);
655
+ if (!tool) return null;
656
+ const requiredSkills = tool.includes.skills.filter((s) => s.required).map((s) => s.name);
657
+ for (const skillName of requiredSkills) {
658
+ if (installedTools[skillName]) {
659
+ return installedTools[skillName].version;
660
+ }
661
+ }
662
+ return null;
663
+ }
664
+ function getToolUpdateStatus(toolName) {
665
+ const installedVersion = getInstalledToolVersion(toolName);
666
+ const tool = getBundledTools().find((t) => t.name === toolName);
667
+ const bundledVersion = tool?.version || null;
668
+ if (!installedVersion || !bundledVersion) {
669
+ return {
670
+ name: toolName,
671
+ hasUpdate: false,
672
+ installedVersion,
673
+ bundledVersion
674
+ };
675
+ }
676
+ const hasUpdate = compareSemver(bundledVersion, installedVersion) > 0;
677
+ return {
678
+ name: toolName,
679
+ hasUpdate,
680
+ installedVersion,
681
+ bundledVersion
682
+ };
683
+ }
684
+ function getToolsWithUpdates() {
685
+ const config = loadConfig();
686
+ const installedTools = getPlatformTools(config);
687
+ const bundledTools = getBundledTools();
688
+ const toolsWithUpdates = [];
689
+ for (const tool of bundledTools) {
690
+ const requiredSkills = tool.includes.skills.filter((s) => s.required).map((s) => s.name);
691
+ const isInstalled = requiredSkills.some(
692
+ (skillName) => skillName in installedTools
693
+ );
694
+ if (isInstalled) {
695
+ const updateStatus = getToolUpdateStatus(tool.name);
696
+ if (updateStatus.hasUpdate) {
697
+ toolsWithUpdates.push(updateStatus);
698
+ }
699
+ }
700
+ }
701
+ return toolsWithUpdates;
702
+ }
648
703
 
649
704
  // src/lib/agents.ts
650
705
  var __dirname3 = dirname4(fileURLToPath3(import.meta.url));
@@ -1316,6 +1371,39 @@ function findSkillPath(skillName) {
1316
1371
  }
1317
1372
  return null;
1318
1373
  }
1374
+ function getSkillPath(skillName) {
1375
+ const result = findSkillPath(skillName);
1376
+ return result?.skillDir ?? null;
1377
+ }
1378
+ function copySkillsToDir(skillNames, dest) {
1379
+ if (!existsSync7(dest)) {
1380
+ mkdirSync5(dest, { recursive: true });
1381
+ }
1382
+ const results = [];
1383
+ for (const name of skillNames) {
1384
+ const skillDir = getSkillPath(name);
1385
+ if (!skillDir) {
1386
+ results.push({
1387
+ name,
1388
+ success: false,
1389
+ error: `Skill '${name}' not found in bundled tools`
1390
+ });
1391
+ continue;
1392
+ }
1393
+ const targetDir = join8(dest, name);
1394
+ try {
1395
+ copyDirectoryRecursive(skillDir, targetDir, () => true);
1396
+ results.push({ name, success: true, dest: targetDir });
1397
+ } catch (err) {
1398
+ results.push({
1399
+ name,
1400
+ success: false,
1401
+ error: `Failed to copy: ${err}`
1402
+ });
1403
+ }
1404
+ }
1405
+ return results;
1406
+ }
1319
1407
  function getBundledSkills() {
1320
1408
  if (!existsSync7(BUNDLED_SKILLS_DIR)) {
1321
1409
  return [];
@@ -1822,6 +1910,239 @@ function uninstallCommand(commandName, skillName) {
1822
1910
  }
1823
1911
  return { success: false, message: `Command not installed: ${commandName}` };
1824
1912
  }
1913
+
1914
+ // src/lib/pack.ts
1915
+ import { existsSync as existsSync8, readdirSync as readdirSync7, readFileSync as readFileSync7, createWriteStream } from "fs";
1916
+ import { join as join9 } from "path";
1917
+ import archiver from "archiver";
1918
+ function getToolsForAudience(audience) {
1919
+ const allTools = getBundledTools();
1920
+ return allTools.filter((tool) => {
1921
+ if (!tool.audience || tool.audience.length === 0) {
1922
+ return false;
1923
+ }
1924
+ return tool.audience.includes(audience) || tool.audience.includes("all" /* All */);
1925
+ });
1926
+ }
1927
+ function getAudienceInfo() {
1928
+ const allTools = getBundledTools();
1929
+ const audiences = Object.values(ToolAudience).filter(
1930
+ (a) => a !== "all" /* All */
1931
+ );
1932
+ return audiences.map((audience) => {
1933
+ const tools = allTools.filter(
1934
+ (tool) => tool.audience && (tool.audience.includes(audience) || tool.audience.includes("all" /* All */))
1935
+ );
1936
+ return {
1937
+ audience,
1938
+ toolCount: tools.length,
1939
+ toolNames: tools.map((t) => t.name)
1940
+ };
1941
+ }).filter((info) => info.toolCount > 0);
1942
+ }
1943
+ function collectToolArtifacts(tool) {
1944
+ const artifacts = [];
1945
+ const toolDir = join9(getBundledToolsDir(), tool.name);
1946
+ for (const skill of tool.includes.skills) {
1947
+ const skillDir = join9(toolDir, "skills", skill.name);
1948
+ if (!existsSync8(skillDir)) continue;
1949
+ const skillMd = join9(skillDir, "SKILL.md");
1950
+ if (existsSync8(skillMd)) {
1951
+ artifacts.push({
1952
+ sourcePath: skillMd,
1953
+ zipPath: `skills/${skill.name}/SKILL.md`
1954
+ });
1955
+ }
1956
+ const refsDir = join9(skillDir, "references");
1957
+ if (existsSync8(refsDir)) {
1958
+ const refFiles = readdirSync7(refsDir).filter((f) => !f.startsWith("."));
1959
+ for (const file of refFiles) {
1960
+ artifacts.push({
1961
+ sourcePath: join9(refsDir, file),
1962
+ zipPath: `skills/${skill.name}/references/${file}`
1963
+ });
1964
+ }
1965
+ }
1966
+ }
1967
+ const commandsDir = join9(toolDir, "commands");
1968
+ if (existsSync8(commandsDir)) {
1969
+ const commandFiles = readdirSync7(commandsDir).filter(
1970
+ (f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
1971
+ );
1972
+ for (const file of commandFiles) {
1973
+ artifacts.push({
1974
+ sourcePath: join9(commandsDir, file),
1975
+ zipPath: `commands/${file}`
1976
+ });
1977
+ }
1978
+ }
1979
+ const agentsDir = join9(toolDir, "agents");
1980
+ if (existsSync8(agentsDir)) {
1981
+ const agentFiles = readdirSync7(agentsDir).filter(
1982
+ (f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
1983
+ );
1984
+ for (const file of agentFiles) {
1985
+ artifacts.push({
1986
+ sourcePath: join9(agentsDir, file),
1987
+ zipPath: `agents/${file}`
1988
+ });
1989
+ }
1990
+ }
1991
+ return artifacts;
1992
+ }
1993
+ function generateClaudeMd(tools) {
1994
+ const skillNames = [];
1995
+ for (const tool of tools) {
1996
+ for (const skill of tool.includes.skills) {
1997
+ skillNames.push(skill.name);
1998
+ }
1999
+ }
2000
+ const lines = [
2001
+ "# Droid Skills",
2002
+ "",
2003
+ "Skills installed from a Droid pack. Each skill teaches your AI new capabilities.",
2004
+ ""
2005
+ ];
2006
+ for (const name of skillNames) {
2007
+ lines.push(`- [${name}](skills/${name}/SKILL.md)`);
2008
+ }
2009
+ lines.push("");
2010
+ return lines.join("\n");
2011
+ }
2012
+ function generateReadme(label, tools) {
2013
+ const lines = [
2014
+ `# Droid Pack: ${label}`,
2015
+ "",
2016
+ "This pack contains AI skills, commands, and agents for Claude Desktop.",
2017
+ "",
2018
+ "## Installation",
2019
+ "",
2020
+ "1. Unzip this archive",
2021
+ "2. Copy the contents into your `~/.claude/` directory:",
2022
+ "",
2023
+ "```bash",
2024
+ "# From the directory where you unzipped:",
2025
+ "cp -r skills/ ~/.claude/skills/",
2026
+ "cp -r commands/ ~/.claude/commands/",
2027
+ "cp -r agents/ ~/.claude/agents/",
2028
+ "```",
2029
+ "",
2030
+ "3. Append the contents of `CLAUDE.md` to your `~/.claude/CLAUDE.md`:",
2031
+ "",
2032
+ "```bash",
2033
+ "cat CLAUDE.md >> ~/.claude/CLAUDE.md",
2034
+ "```",
2035
+ "",
2036
+ "## Included Tools",
2037
+ ""
2038
+ ];
2039
+ for (const tool of tools) {
2040
+ lines.push(`- **${tool.name}** (v${tool.version}) \u2014 ${tool.description}`);
2041
+ }
2042
+ lines.push("");
2043
+ return lines.join("\n");
2044
+ }
2045
+ function checkDependencies(tools) {
2046
+ const warnings = [];
2047
+ const toolNames = new Set(tools.map((t) => t.name));
2048
+ for (const tool of tools) {
2049
+ if (!tool.dependencies) continue;
2050
+ for (const dep of tool.dependencies) {
2051
+ if (!toolNames.has(dep)) {
2052
+ warnings.push(
2053
+ `Tool '${tool.name}' depends on '${dep}' which is not included in this pack`
2054
+ );
2055
+ }
2056
+ }
2057
+ }
2058
+ return warnings;
2059
+ }
2060
+ async function buildToolPack(options) {
2061
+ const { toolName, outputDir } = options;
2062
+ const allTools = getBundledTools();
2063
+ const tool = allTools.find((t) => t.name === toolName);
2064
+ if (!tool) {
2065
+ return {
2066
+ success: false,
2067
+ message: `Tool '${toolName}' not found`
2068
+ };
2069
+ }
2070
+ const tools = [tool];
2071
+ const warnings = checkDependencies(tools);
2072
+ const filename = `droid-${toolName}.zip`;
2073
+ const outputPath = join9(outputDir, filename);
2074
+ return new Promise((resolve) => {
2075
+ const output = createWriteStream(outputPath);
2076
+ const archive = archiver("zip", { zlib: { level: 9 } });
2077
+ output.on("close", () => {
2078
+ resolve({
2079
+ success: true,
2080
+ message: `Pack created: ${filename}`,
2081
+ outputPath,
2082
+ toolCount: 1,
2083
+ warnings: warnings.length > 0 ? warnings : void 0
2084
+ });
2085
+ });
2086
+ archive.on("error", (err) => {
2087
+ resolve({
2088
+ success: false,
2089
+ message: `Failed to create pack: ${err.message}`
2090
+ });
2091
+ });
2092
+ archive.pipe(output);
2093
+ const artifacts = collectToolArtifacts(tool);
2094
+ for (const artifact of artifacts) {
2095
+ const content = readFileSync7(artifact.sourcePath, "utf-8");
2096
+ archive.append(content, { name: artifact.zipPath });
2097
+ }
2098
+ archive.append(generateClaudeMd(tools), { name: "CLAUDE.md" });
2099
+ archive.append(generateReadme(toolName, tools), { name: "README.md" });
2100
+ archive.finalize();
2101
+ });
2102
+ }
2103
+ async function buildPack(options) {
2104
+ const { audience, outputDir } = options;
2105
+ const tools = getToolsForAudience(audience);
2106
+ if (tools.length === 0) {
2107
+ return {
2108
+ success: false,
2109
+ message: `No tools found for audience '${audience}'`
2110
+ };
2111
+ }
2112
+ const warnings = checkDependencies(tools);
2113
+ const filename = `droid-${audience}-pack.zip`;
2114
+ const outputPath = join9(outputDir, filename);
2115
+ return new Promise((resolve) => {
2116
+ const output = createWriteStream(outputPath);
2117
+ const archive = archiver("zip", { zlib: { level: 9 } });
2118
+ output.on("close", () => {
2119
+ resolve({
2120
+ success: true,
2121
+ message: `Pack created: ${filename}`,
2122
+ outputPath,
2123
+ toolCount: tools.length,
2124
+ warnings: warnings.length > 0 ? warnings : void 0
2125
+ });
2126
+ });
2127
+ archive.on("error", (err) => {
2128
+ resolve({
2129
+ success: false,
2130
+ message: `Failed to create pack: ${err.message}`
2131
+ });
2132
+ });
2133
+ archive.pipe(output);
2134
+ for (const tool of tools) {
2135
+ const artifacts = collectToolArtifacts(tool);
2136
+ for (const artifact of artifacts) {
2137
+ const content = readFileSync7(artifact.sourcePath, "utf-8");
2138
+ archive.append(content, { name: artifact.zipPath });
2139
+ }
2140
+ }
2141
+ archive.append(generateClaudeMd(tools), { name: "CLAUDE.md" });
2142
+ archive.append(generateReadme(audience, tools), { name: "README.md" });
2143
+ archive.finalize();
2144
+ });
2145
+ }
1825
2146
  export {
1826
2147
  AIToolValue as AITool,
1827
2148
  BuiltInOutput,
@@ -1830,20 +2151,27 @@ export {
1830
2151
  SkillStatus,
1831
2152
  ToolAudience,
1832
2153
  addRepo,
2154
+ buildPack,
2155
+ buildToolPack,
1833
2156
  checkForUpdates,
1834
2157
  compareSemver,
1835
2158
  configExists,
2159
+ copySkillsToDir,
1836
2160
  ensureConfigDir,
1837
2161
  findSkillPath,
1838
2162
  getAITag,
2163
+ getAudienceInfo,
1839
2164
  getAutoUpdateConfig,
1840
2165
  getBundledSkills,
1841
2166
  getBundledSkillsDir,
2167
+ getBundledTools,
2168
+ getBundledToolsDir,
1842
2169
  getCommandsInstallPath,
1843
2170
  getConfigDir,
1844
2171
  getConfigPath,
1845
2172
  getConfigValue,
1846
2173
  getInstalledSkill,
2174
+ getInstalledToolVersion,
1847
2175
  getPlatformConfigPath,
1848
2176
  getPlatformTools,
1849
2177
  getPlatformToolsFor,
@@ -1851,20 +2179,26 @@ export {
1851
2179
  getRepoPath,
1852
2180
  getRepos,
1853
2181
  getSkillOverridesPath,
2182
+ getSkillPath,
1854
2183
  getSkillStatusDisplay,
1855
2184
  getSkillUpdateStatus,
1856
2185
  getSkillsInstallPath,
1857
2186
  getSkillsWithUpdates,
1858
2187
  getToolSettings,
2188
+ getToolUpdateStatus,
2189
+ getToolsForAudience,
2190
+ getToolsWithUpdates,
1859
2191
  getUpdateInfo,
1860
2192
  getVersion,
1861
2193
  installCommand,
1862
2194
  installSkill,
1863
2195
  isCommandInstalled,
1864
2196
  isSkillInstalled,
2197
+ isToolInstalled,
1865
2198
  loadConfig,
1866
2199
  loadSkillManifest,
1867
2200
  loadSkillOverrides,
2201
+ loadToolManifest,
1868
2202
  removeRepo,
1869
2203
  runUpdate,
1870
2204
  saveConfig,
@@ -34,6 +34,29 @@ export declare function findSkillPath(skillName: string): {
34
34
  toolDir: string;
35
35
  skillDir: string;
36
36
  } | null;
37
+ /**
38
+ * Resolve the absolute path to a bundled skill directory by name.
39
+ * Returns null if the skill is not found.
40
+ *
41
+ * This is the stable public API for consumers who need to locate skill
42
+ * assets (e.g., for copying into a build output). It encapsulates droid's
43
+ * internal `tools/{tool}/skills/{name}/` directory structure.
44
+ */
45
+ export declare function getSkillPath(skillName: string): string | null;
46
+ /**
47
+ * Copy bundled skills to a destination directory.
48
+ * Each skill is copied as `{dest}/{skillName}/` with SKILL.md, references/, etc.
49
+ *
50
+ * @param skillNames - Array of skill names to copy
51
+ * @param dest - Target directory (created if it doesn't exist)
52
+ * @returns Results per skill: success/failure with paths
53
+ */
54
+ export declare function copySkillsToDir(skillNames: string[], dest: string): Array<{
55
+ name: string;
56
+ success: boolean;
57
+ dest?: string;
58
+ error?: string;
59
+ }>;
37
60
  /**
38
61
  * Get all bundled skills from all tools
39
62
  */
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,cAAc,EAGpB,MAAM,SAAS,CAAC;AAyBjB;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAExE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAEvE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,MAAM,EAAE,GACxB,IAAI,CA8CN;AAwBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA2BxE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAwB9C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,EAAE,MAAM,GACX,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqC1E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,EAAE,CA4BlD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAI1E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG;IACvD,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAkBA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,KAAK,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAqBD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CA+BA;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI;IACjC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAiCA;AAmCD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CA0RA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CA0FA;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAUlE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAuBT;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA4DvC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgDvC"}