@orderful/droid 0.48.0 → 0.51.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -1
- package/CHANGELOG.md +34 -0
- package/bun.lock +137 -3
- package/dist/bin/droid.js +355 -90
- package/dist/commands/pack.d.ts +5 -0
- package/dist/commands/pack.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/lib/pack.d.ts +31 -0
- package/dist/lib/pack.d.ts.map +1 -0
- package/dist/lib/types.d.ts +17 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/tools/brain/.claude-plugin/plugin.json +1 -1
- package/dist/tools/brain/TOOL.yaml +3 -1
- package/dist/tools/brain/skills/brain/SKILL.md +4 -0
- package/dist/tools/brain/skills/brain/references/workflows.md +21 -7
- package/dist/tools/coach/TOOL.yaml +4 -0
- package/dist/tools/code-review/.claude-plugin/plugin.json +3 -2
- package/dist/tools/code-review/TOOL.yaml +4 -1
- package/dist/tools/code-review/agents/codex-context-researcher.md +99 -0
- package/dist/tools/code-review/skills/code-review/SKILL.md +20 -1
- package/dist/tools/codex/.claude-plugin/plugin.json +1 -1
- package/dist/tools/codex/TOOL.yaml +3 -1
- package/dist/tools/codex/skills/codex/SKILL.md +5 -1
- package/dist/tools/codex/skills/codex/scripts/normalize-frontmatter.d.ts +61 -0
- package/dist/tools/codex/skills/codex/scripts/normalize-frontmatter.d.ts.map +1 -0
- package/dist/tools/codex/skills/codex/scripts/normalize-frontmatter.ts +402 -0
- package/dist/tools/comments/TOOL.yaml +2 -0
- package/dist/tools/droid/.claude-plugin/plugin.json +1 -1
- package/dist/tools/droid/TOOL.yaml +3 -1
- package/dist/tools/droid/skills/droid/SKILL.md +48 -2
- package/dist/tools/droid/skills/droid/references/new-tool-workflow.md +234 -0
- package/dist/tools/edi-schema/TOOL.yaml +2 -0
- package/dist/tools/excalidraw/TOOL.yaml +2 -0
- package/dist/tools/meeting/TOOL.yaml +2 -0
- package/dist/tools/pii/TOOL.yaml +2 -0
- package/dist/tools/plan/.claude-plugin/plugin.json +1 -1
- package/dist/tools/plan/TOOL.yaml +5 -1
- package/dist/tools/plan/commands/plan.md +3 -2
- package/dist/tools/plan/skills/plan/SKILL.md +31 -10
- package/dist/tools/plan/skills/plan/references/workflows.md +44 -14
- package/dist/tools/project/.claude-plugin/plugin.json +1 -1
- package/dist/tools/project/TOOL.yaml +7 -1
- package/dist/tools/project/skills/project/SKILL.md +32 -1
- package/dist/tools/project/skills/project/references/loading.md +1 -0
- package/dist/tools/project/skills/project/references/pulling.md +57 -0
- package/dist/tools/project/skills/project/references/pushing.md +79 -0
- package/dist/tools/release/TOOL.yaml +2 -0
- package/dist/tools/share/TOOL.yaml +2 -0
- package/dist/tools/status-update/TOOL.yaml +4 -0
- package/dist/tools/tech-design/TOOL.yaml +2 -0
- package/dist/tools/wrapup/TOOL.yaml +2 -0
- package/package.json +3 -1
- package/scripts/build.ts +3 -2
- package/src/bin/droid.ts +9 -0
- package/src/commands/pack.ts +77 -0
- package/src/lib/pack.test.ts +85 -0
- package/src/lib/pack.ts +293 -0
- package/src/lib/types.ts +19 -0
- package/src/tools/brain/.claude-plugin/plugin.json +1 -1
- package/src/tools/brain/TOOL.yaml +3 -1
- package/src/tools/brain/skills/brain/SKILL.md +4 -0
- package/src/tools/brain/skills/brain/references/workflows.md +21 -7
- package/src/tools/coach/TOOL.yaml +4 -0
- package/src/tools/code-review/.claude-plugin/plugin.json +3 -2
- package/src/tools/code-review/TOOL.yaml +4 -1
- package/src/tools/code-review/agents/codex-context-researcher.md +99 -0
- package/src/tools/code-review/skills/code-review/SKILL.md +20 -1
- package/src/tools/codex/.claude-plugin/plugin.json +1 -1
- package/src/tools/codex/TOOL.yaml +3 -1
- package/src/tools/codex/skills/codex/SKILL.md +5 -1
- package/src/tools/codex/skills/codex/scripts/normalize-frontmatter.test.ts +331 -0
- package/src/tools/codex/skills/codex/scripts/normalize-frontmatter.ts +402 -0
- package/src/tools/comments/TOOL.yaml +2 -0
- package/src/tools/droid/.claude-plugin/plugin.json +1 -1
- package/src/tools/droid/TOOL.yaml +3 -1
- package/src/tools/droid/skills/droid/SKILL.md +48 -2
- package/src/tools/droid/skills/droid/references/new-tool-workflow.md +234 -0
- package/src/tools/edi-schema/TOOL.yaml +2 -0
- package/src/tools/excalidraw/TOOL.yaml +2 -0
- package/src/tools/meeting/TOOL.yaml +2 -0
- package/src/tools/pii/TOOL.yaml +2 -0
- package/src/tools/plan/.claude-plugin/plugin.json +1 -1
- package/src/tools/plan/TOOL.yaml +5 -1
- package/src/tools/plan/commands/plan.md +3 -2
- package/src/tools/plan/skills/plan/SKILL.md +31 -10
- package/src/tools/plan/skills/plan/references/workflows.md +44 -14
- package/src/tools/project/.claude-plugin/plugin.json +1 -1
- package/src/tools/project/TOOL.yaml +7 -1
- package/src/tools/project/skills/project/SKILL.md +32 -1
- package/src/tools/project/skills/project/references/loading.md +1 -0
- package/src/tools/project/skills/project/references/pulling.md +57 -0
- package/src/tools/project/skills/project/references/pushing.md +79 -0
- package/src/tools/release/TOOL.yaml +2 -0
- package/src/tools/share/TOOL.yaml +2 -0
- package/src/tools/status-update/TOOL.yaml +4 -0
- package/src/tools/tech-design/TOOL.yaml +2 -0
- package/src/tools/wrapup/TOOL.yaml +2 -0
- package/dist/tools/codex/skills/codex/scripts/git-scripts.test.ts +0 -364
- package/dist/tools/pii/skills/pii/scripts/presidio.test.ts +0 -444
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
|
|
5
|
+
import chalk13 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/commands/setup.ts
|
|
8
8
|
import inquirer from "inquirer";
|
|
@@ -37,6 +37,16 @@ function setPlatformTools(config, tools) {
|
|
|
37
37
|
}
|
|
38
38
|
config.platforms[config.platform].tools = tools;
|
|
39
39
|
}
|
|
40
|
+
var ToolAudience = /* @__PURE__ */ ((ToolAudience2) => {
|
|
41
|
+
ToolAudience2["All"] = "all";
|
|
42
|
+
ToolAudience2["Engineering"] = "engineering";
|
|
43
|
+
ToolAudience2["Product"] = "product";
|
|
44
|
+
ToolAudience2["Design"] = "design";
|
|
45
|
+
ToolAudience2["IntegrationDevelopers"] = "integration-developers";
|
|
46
|
+
ToolAudience2["CustomerSupport"] = "customer-support";
|
|
47
|
+
ToolAudience2["NetworkOperations"] = "network-operations";
|
|
48
|
+
return ToolAudience2;
|
|
49
|
+
})(ToolAudience || {});
|
|
40
50
|
|
|
41
51
|
// src/lib/config.ts
|
|
42
52
|
var CONFIG_DIR = join(homedir(), ".droid");
|
|
@@ -5158,32 +5168,286 @@ async function execCommand(tool, script, args) {
|
|
|
5158
5168
|
});
|
|
5159
5169
|
}
|
|
5160
5170
|
|
|
5161
|
-
// src/commands/
|
|
5171
|
+
// src/commands/pack.ts
|
|
5162
5172
|
import chalk10 from "chalk";
|
|
5173
|
+
|
|
5174
|
+
// src/lib/pack.ts
|
|
5175
|
+
import { existsSync as existsSync12, readdirSync as readdirSync7, readFileSync as readFileSync11, createWriteStream } from "fs";
|
|
5176
|
+
import { join as join14 } from "path";
|
|
5177
|
+
import archiver from "archiver";
|
|
5178
|
+
function getToolsForAudience(audience) {
|
|
5179
|
+
const allTools = getBundledTools();
|
|
5180
|
+
return allTools.filter((tool) => {
|
|
5181
|
+
if (!tool.audience || tool.audience.length === 0) {
|
|
5182
|
+
return false;
|
|
5183
|
+
}
|
|
5184
|
+
return tool.audience.includes(audience) || tool.audience.includes("all" /* All */);
|
|
5185
|
+
});
|
|
5186
|
+
}
|
|
5187
|
+
function getAudienceInfo() {
|
|
5188
|
+
const allTools = getBundledTools();
|
|
5189
|
+
const audiences = Object.values(ToolAudience).filter(
|
|
5190
|
+
(a) => a !== "all" /* All */
|
|
5191
|
+
);
|
|
5192
|
+
return audiences.map((audience) => {
|
|
5193
|
+
const tools = allTools.filter(
|
|
5194
|
+
(tool) => tool.audience && (tool.audience.includes(audience) || tool.audience.includes("all" /* All */))
|
|
5195
|
+
);
|
|
5196
|
+
return {
|
|
5197
|
+
audience,
|
|
5198
|
+
toolCount: tools.length,
|
|
5199
|
+
toolNames: tools.map((t) => t.name)
|
|
5200
|
+
};
|
|
5201
|
+
}).filter((info) => info.toolCount > 0);
|
|
5202
|
+
}
|
|
5203
|
+
function collectToolArtifacts(tool) {
|
|
5204
|
+
const artifacts = [];
|
|
5205
|
+
const toolDir = join14(getBundledToolsDir(), tool.name);
|
|
5206
|
+
for (const skill of tool.includes.skills) {
|
|
5207
|
+
const skillDir = join14(toolDir, "skills", skill.name);
|
|
5208
|
+
if (!existsSync12(skillDir)) continue;
|
|
5209
|
+
const skillMd = join14(skillDir, "SKILL.md");
|
|
5210
|
+
if (existsSync12(skillMd)) {
|
|
5211
|
+
artifacts.push({
|
|
5212
|
+
sourcePath: skillMd,
|
|
5213
|
+
zipPath: `skills/${skill.name}/SKILL.md`
|
|
5214
|
+
});
|
|
5215
|
+
}
|
|
5216
|
+
const refsDir = join14(skillDir, "references");
|
|
5217
|
+
if (existsSync12(refsDir)) {
|
|
5218
|
+
const refFiles = readdirSync7(refsDir).filter((f) => f.endsWith(".md"));
|
|
5219
|
+
for (const file of refFiles) {
|
|
5220
|
+
artifacts.push({
|
|
5221
|
+
sourcePath: join14(refsDir, file),
|
|
5222
|
+
zipPath: `skills/${skill.name}/references/${file}`
|
|
5223
|
+
});
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
const commandsDir = join14(toolDir, "commands");
|
|
5228
|
+
if (existsSync12(commandsDir)) {
|
|
5229
|
+
const commandFiles = readdirSync7(commandsDir).filter(
|
|
5230
|
+
(f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
|
|
5231
|
+
);
|
|
5232
|
+
for (const file of commandFiles) {
|
|
5233
|
+
artifacts.push({
|
|
5234
|
+
sourcePath: join14(commandsDir, file),
|
|
5235
|
+
zipPath: `commands/${file}`
|
|
5236
|
+
});
|
|
5237
|
+
}
|
|
5238
|
+
}
|
|
5239
|
+
const agentsDir = join14(toolDir, "agents");
|
|
5240
|
+
if (existsSync12(agentsDir)) {
|
|
5241
|
+
const agentFiles = readdirSync7(agentsDir).filter(
|
|
5242
|
+
(f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
|
|
5243
|
+
);
|
|
5244
|
+
for (const file of agentFiles) {
|
|
5245
|
+
artifacts.push({
|
|
5246
|
+
sourcePath: join14(agentsDir, file),
|
|
5247
|
+
zipPath: `agents/${file}`
|
|
5248
|
+
});
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
return artifacts;
|
|
5252
|
+
}
|
|
5253
|
+
function generateClaudeMd(tools) {
|
|
5254
|
+
const skillNames = [];
|
|
5255
|
+
for (const tool of tools) {
|
|
5256
|
+
for (const skill of tool.includes.skills) {
|
|
5257
|
+
skillNames.push(skill.name);
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5260
|
+
const lines = [
|
|
5261
|
+
"# Droid Skills",
|
|
5262
|
+
"",
|
|
5263
|
+
"Skills installed from a Droid pack. Each skill teaches your AI new capabilities.",
|
|
5264
|
+
""
|
|
5265
|
+
];
|
|
5266
|
+
for (const name of skillNames) {
|
|
5267
|
+
lines.push(`- [${name}](skills/${name}/SKILL.md)`);
|
|
5268
|
+
}
|
|
5269
|
+
lines.push("");
|
|
5270
|
+
return lines.join("\n");
|
|
5271
|
+
}
|
|
5272
|
+
function generateReadme(audience, tools) {
|
|
5273
|
+
const lines = [
|
|
5274
|
+
`# Droid Pack: ${audience}`,
|
|
5275
|
+
"",
|
|
5276
|
+
"This pack contains AI skills, commands, and agents for Claude Desktop.",
|
|
5277
|
+
"",
|
|
5278
|
+
"## Installation",
|
|
5279
|
+
"",
|
|
5280
|
+
"1. Unzip this archive",
|
|
5281
|
+
"2. Copy the contents into your `~/.claude/` directory:",
|
|
5282
|
+
"",
|
|
5283
|
+
"```bash",
|
|
5284
|
+
"# From the directory where you unzipped:",
|
|
5285
|
+
"cp -r skills/ ~/.claude/skills/",
|
|
5286
|
+
"cp -r commands/ ~/.claude/commands/",
|
|
5287
|
+
"cp -r agents/ ~/.claude/agents/",
|
|
5288
|
+
"```",
|
|
5289
|
+
"",
|
|
5290
|
+
"3. Append the contents of `CLAUDE.md` to your `~/.claude/CLAUDE.md`:",
|
|
5291
|
+
"",
|
|
5292
|
+
"```bash",
|
|
5293
|
+
"cat CLAUDE.md >> ~/.claude/CLAUDE.md",
|
|
5294
|
+
"```",
|
|
5295
|
+
"",
|
|
5296
|
+
"## Included Tools",
|
|
5297
|
+
""
|
|
5298
|
+
];
|
|
5299
|
+
for (const tool of tools) {
|
|
5300
|
+
lines.push(`- **${tool.name}** (v${tool.version}) \u2014 ${tool.description}`);
|
|
5301
|
+
}
|
|
5302
|
+
lines.push("");
|
|
5303
|
+
return lines.join("\n");
|
|
5304
|
+
}
|
|
5305
|
+
function checkDependencies(tools) {
|
|
5306
|
+
const warnings = [];
|
|
5307
|
+
const toolNames = new Set(tools.map((t) => t.name));
|
|
5308
|
+
for (const tool of tools) {
|
|
5309
|
+
if (!tool.dependencies) continue;
|
|
5310
|
+
for (const dep of tool.dependencies) {
|
|
5311
|
+
if (!toolNames.has(dep)) {
|
|
5312
|
+
warnings.push(
|
|
5313
|
+
`Tool '${tool.name}' depends on '${dep}' which is not included in this pack`
|
|
5314
|
+
);
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
}
|
|
5318
|
+
return warnings;
|
|
5319
|
+
}
|
|
5320
|
+
async function buildPack(options) {
|
|
5321
|
+
const { audience, outputDir } = options;
|
|
5322
|
+
const tools = getToolsForAudience(audience);
|
|
5323
|
+
if (tools.length === 0) {
|
|
5324
|
+
return {
|
|
5325
|
+
success: false,
|
|
5326
|
+
message: `No tools found for audience '${audience}'`
|
|
5327
|
+
};
|
|
5328
|
+
}
|
|
5329
|
+
const warnings = checkDependencies(tools);
|
|
5330
|
+
const filename = `droid-${audience}-pack.zip`;
|
|
5331
|
+
const outputPath = join14(outputDir, filename);
|
|
5332
|
+
return new Promise((resolve) => {
|
|
5333
|
+
const output = createWriteStream(outputPath);
|
|
5334
|
+
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
5335
|
+
output.on("close", () => {
|
|
5336
|
+
resolve({
|
|
5337
|
+
success: true,
|
|
5338
|
+
message: `Pack created: ${filename}`,
|
|
5339
|
+
outputPath,
|
|
5340
|
+
toolCount: tools.length,
|
|
5341
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
5342
|
+
});
|
|
5343
|
+
});
|
|
5344
|
+
archive.on("error", (err) => {
|
|
5345
|
+
resolve({
|
|
5346
|
+
success: false,
|
|
5347
|
+
message: `Failed to create pack: ${err.message}`
|
|
5348
|
+
});
|
|
5349
|
+
});
|
|
5350
|
+
archive.pipe(output);
|
|
5351
|
+
for (const tool of tools) {
|
|
5352
|
+
const artifacts = collectToolArtifacts(tool);
|
|
5353
|
+
for (const artifact of artifacts) {
|
|
5354
|
+
const content = readFileSync11(artifact.sourcePath, "utf-8");
|
|
5355
|
+
archive.append(content, { name: artifact.zipPath });
|
|
5356
|
+
}
|
|
5357
|
+
}
|
|
5358
|
+
archive.append(generateClaudeMd(tools), { name: "CLAUDE.md" });
|
|
5359
|
+
archive.append(generateReadme(audience, tools), { name: "README.md" });
|
|
5360
|
+
archive.finalize();
|
|
5361
|
+
});
|
|
5362
|
+
}
|
|
5363
|
+
|
|
5364
|
+
// src/commands/pack.ts
|
|
5365
|
+
function isValidAudience(value) {
|
|
5366
|
+
return Object.values(ToolAudience).includes(value);
|
|
5367
|
+
}
|
|
5368
|
+
async function packCommand(audience, options) {
|
|
5369
|
+
if (options.list) {
|
|
5370
|
+
const infos = getAudienceInfo();
|
|
5371
|
+
if (infos.length === 0) {
|
|
5372
|
+
console.log(chalk10.yellow("No tools with audience metadata found."));
|
|
5373
|
+
return;
|
|
5374
|
+
}
|
|
5375
|
+
console.log(chalk10.bold("\nAvailable audiences:\n"));
|
|
5376
|
+
for (const info of infos) {
|
|
5377
|
+
console.log(
|
|
5378
|
+
` ${chalk10.cyan(info.audience.padEnd(24))} ${chalk10.gray(`${info.toolCount} tools`)} ${chalk10.gray(info.toolNames.join(", "))}`
|
|
5379
|
+
);
|
|
5380
|
+
}
|
|
5381
|
+
console.log("");
|
|
5382
|
+
return;
|
|
5383
|
+
}
|
|
5384
|
+
if (!audience) {
|
|
5385
|
+
console.error(chalk10.red("\nError: audience argument required"));
|
|
5386
|
+
console.log(chalk10.gray("Usage: droid pack <audience>"));
|
|
5387
|
+
console.log(chalk10.gray(" droid pack --list"));
|
|
5388
|
+
process.exit(1);
|
|
5389
|
+
}
|
|
5390
|
+
if (!isValidAudience(audience)) {
|
|
5391
|
+
console.error(chalk10.red(`
|
|
5392
|
+
Error: unknown audience '${audience}'`));
|
|
5393
|
+
console.log(chalk10.gray("\nValid audiences:"));
|
|
5394
|
+
for (const a of Object.values(ToolAudience)) {
|
|
5395
|
+
if (a !== "all" /* All */) {
|
|
5396
|
+
console.log(chalk10.gray(` - ${a}`));
|
|
5397
|
+
}
|
|
5398
|
+
}
|
|
5399
|
+
process.exit(1);
|
|
5400
|
+
}
|
|
5401
|
+
const outputDir = options.output || process.cwd();
|
|
5402
|
+
console.log(
|
|
5403
|
+
chalk10.bold(`
|
|
5404
|
+
Packing tools for ${chalk10.cyan(audience)}...`)
|
|
5405
|
+
);
|
|
5406
|
+
const result = await buildPack({ audience, outputDir });
|
|
5407
|
+
if (!result.success) {
|
|
5408
|
+
console.error(chalk10.red(`
|
|
5409
|
+
${result.message}`));
|
|
5410
|
+
process.exit(1);
|
|
5411
|
+
}
|
|
5412
|
+
console.log(chalk10.green(`
|
|
5413
|
+
${result.message}`));
|
|
5414
|
+
console.log(chalk10.gray(` ${result.toolCount} tools included`));
|
|
5415
|
+
console.log(chalk10.gray(` Output: ${result.outputPath}`));
|
|
5416
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
5417
|
+
console.log(chalk10.yellow("\nWarnings:"));
|
|
5418
|
+
for (const warning of result.warnings) {
|
|
5419
|
+
console.log(chalk10.yellow(` - ${warning}`));
|
|
5420
|
+
}
|
|
5421
|
+
}
|
|
5422
|
+
console.log("");
|
|
5423
|
+
}
|
|
5424
|
+
|
|
5425
|
+
// src/commands/repos.ts
|
|
5426
|
+
import chalk11 from "chalk";
|
|
5163
5427
|
import inquirer4 from "inquirer";
|
|
5164
5428
|
async function reposListCommand(options) {
|
|
5165
5429
|
const repos2 = getRepos();
|
|
5166
5430
|
if (repos2.length === 0) {
|
|
5167
|
-
console.log(
|
|
5168
|
-
console.log(
|
|
5169
|
-
console.log(
|
|
5431
|
+
console.log(chalk11.yellow("No repos configured."));
|
|
5432
|
+
console.log(chalk11.gray("\nAdd a repo with:"));
|
|
5433
|
+
console.log(chalk11.gray(" droid repos add <name>"));
|
|
5170
5434
|
return;
|
|
5171
5435
|
}
|
|
5172
5436
|
if (options?.json) {
|
|
5173
5437
|
console.log(JSON.stringify(repos2, null, 2));
|
|
5174
5438
|
return;
|
|
5175
5439
|
}
|
|
5176
|
-
console.log(
|
|
5440
|
+
console.log(chalk11.bold("\n\u{1F4E6} Registered Repos\n"));
|
|
5177
5441
|
for (const repo of repos2) {
|
|
5178
5442
|
const expandedPath = getRepoPath(repo.name);
|
|
5179
|
-
console.log(
|
|
5180
|
-
console.log(
|
|
5443
|
+
console.log(chalk11.cyan(`${repo.name}`));
|
|
5444
|
+
console.log(chalk11.gray(` Path: ${expandedPath}`));
|
|
5181
5445
|
if (repo.description) {
|
|
5182
|
-
console.log(
|
|
5446
|
+
console.log(chalk11.gray(` ${repo.description}`));
|
|
5183
5447
|
}
|
|
5184
5448
|
if (repo.release_branch) {
|
|
5185
5449
|
const prod = repo.production_branch || "master";
|
|
5186
|
-
console.log(
|
|
5450
|
+
console.log(chalk11.gray(` Release: ${repo.release_branch} \u2192 ${prod}`));
|
|
5187
5451
|
}
|
|
5188
5452
|
console.log();
|
|
5189
5453
|
}
|
|
@@ -5246,7 +5510,7 @@ async function reposAddCommand(name, path, description) {
|
|
|
5246
5510
|
productionBranch = prodAnswers.production_branch || "master";
|
|
5247
5511
|
}
|
|
5248
5512
|
if (!repoName || !repoPath) {
|
|
5249
|
-
console.error(
|
|
5513
|
+
console.error(chalk11.red("Name and path are required"));
|
|
5250
5514
|
return;
|
|
5251
5515
|
}
|
|
5252
5516
|
const repo = {
|
|
@@ -5258,11 +5522,11 @@ async function reposAddCommand(name, path, description) {
|
|
|
5258
5522
|
};
|
|
5259
5523
|
addRepo(repo);
|
|
5260
5524
|
const expandedPath = getRepoPath(repoName);
|
|
5261
|
-
console.log(
|
|
5525
|
+
console.log(chalk11.green(`
|
|
5262
5526
|
\u2713 Added repo: ${repoName}`));
|
|
5263
|
-
console.log(
|
|
5527
|
+
console.log(chalk11.gray(` Path: ${expandedPath}`));
|
|
5264
5528
|
if (repoDescription) {
|
|
5265
|
-
console.log(
|
|
5529
|
+
console.log(chalk11.gray(` ${repoDescription}`));
|
|
5266
5530
|
}
|
|
5267
5531
|
}
|
|
5268
5532
|
async function reposRemoveCommand(name) {
|
|
@@ -5270,7 +5534,7 @@ async function reposRemoveCommand(name) {
|
|
|
5270
5534
|
if (!repoName) {
|
|
5271
5535
|
const repos2 = getRepos();
|
|
5272
5536
|
if (repos2.length === 0) {
|
|
5273
|
-
console.log(
|
|
5537
|
+
console.log(chalk11.yellow("No repos configured."));
|
|
5274
5538
|
return;
|
|
5275
5539
|
}
|
|
5276
5540
|
const answers2 = await inquirer4.prompt([
|
|
@@ -5284,7 +5548,7 @@ async function reposRemoveCommand(name) {
|
|
|
5284
5548
|
repoName = answers2.name;
|
|
5285
5549
|
}
|
|
5286
5550
|
if (!repoName) {
|
|
5287
|
-
console.error(
|
|
5551
|
+
console.error(chalk11.red("Repo name is required"));
|
|
5288
5552
|
return;
|
|
5289
5553
|
}
|
|
5290
5554
|
const answers = await inquirer4.prompt([
|
|
@@ -5296,22 +5560,22 @@ async function reposRemoveCommand(name) {
|
|
|
5296
5560
|
}
|
|
5297
5561
|
]);
|
|
5298
5562
|
if (!answers.confirm) {
|
|
5299
|
-
console.log(
|
|
5563
|
+
console.log(chalk11.gray("Cancelled"));
|
|
5300
5564
|
return;
|
|
5301
5565
|
}
|
|
5302
5566
|
const existed = removeRepo(repoName);
|
|
5303
5567
|
if (existed) {
|
|
5304
|
-
console.log(
|
|
5568
|
+
console.log(chalk11.green(`
|
|
5305
5569
|
\u2713 Removed repo: ${repoName}`));
|
|
5306
5570
|
} else {
|
|
5307
|
-
console.log(
|
|
5571
|
+
console.log(chalk11.yellow(`
|
|
5308
5572
|
Repo '${repoName}' not found`));
|
|
5309
5573
|
}
|
|
5310
5574
|
}
|
|
5311
5575
|
async function reposGetCommand(name) {
|
|
5312
5576
|
const repo = getRepo(name);
|
|
5313
5577
|
if (!repo) {
|
|
5314
|
-
console.error(
|
|
5578
|
+
console.error(chalk11.red(`Repo '${name}' not found`));
|
|
5315
5579
|
process.exit(1);
|
|
5316
5580
|
}
|
|
5317
5581
|
console.log(JSON.stringify(repo, null, 2));
|
|
@@ -5319,11 +5583,11 @@ async function reposGetCommand(name) {
|
|
|
5319
5583
|
|
|
5320
5584
|
// src/commands/integrations.ts
|
|
5321
5585
|
import inquirer5 from "inquirer";
|
|
5322
|
-
import
|
|
5586
|
+
import chalk12 from "chalk";
|
|
5323
5587
|
import { execSync as execSync6 } from "child_process";
|
|
5324
5588
|
import { createServer } from "https";
|
|
5325
|
-
import { readFileSync as
|
|
5326
|
-
import { join as
|
|
5589
|
+
import { readFileSync as readFileSync12, mkdirSync as mkdirSync7, appendFileSync as appendFileSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
5590
|
+
import { join as join15 } from "path";
|
|
5327
5591
|
|
|
5328
5592
|
// src/integrations/slack/index.ts
|
|
5329
5593
|
import { WebClient } from "@slack/web-api";
|
|
@@ -5445,13 +5709,13 @@ var SUCCESS_HTML = `<!DOCTYPE html>
|
|
|
5445
5709
|
</div>
|
|
5446
5710
|
</body>
|
|
5447
5711
|
</html>`;
|
|
5448
|
-
var CERT_DIR =
|
|
5449
|
-
var CERT_KEY_PATH =
|
|
5450
|
-
var CERT_PATH =
|
|
5712
|
+
var CERT_DIR = join15(process.env.HOME || "", ".droid", "certs");
|
|
5713
|
+
var CERT_KEY_PATH = join15(CERT_DIR, "localhost-key.pem");
|
|
5714
|
+
var CERT_PATH = join15(CERT_DIR, "localhost.pem");
|
|
5451
5715
|
function getOrCreateCert() {
|
|
5452
5716
|
try {
|
|
5453
|
-
const key =
|
|
5454
|
-
const cert =
|
|
5717
|
+
const key = readFileSync12(CERT_KEY_PATH, "utf-8");
|
|
5718
|
+
const cert = readFileSync12(CERT_PATH, "utf-8");
|
|
5455
5719
|
if (key && cert) return { key, cert };
|
|
5456
5720
|
} catch {
|
|
5457
5721
|
}
|
|
@@ -5461,8 +5725,8 @@ function getOrCreateCert() {
|
|
|
5461
5725
|
{ stdio: "ignore" }
|
|
5462
5726
|
);
|
|
5463
5727
|
return {
|
|
5464
|
-
key:
|
|
5465
|
-
cert:
|
|
5728
|
+
key: readFileSync12(CERT_KEY_PATH, "utf-8"),
|
|
5729
|
+
cert: readFileSync12(CERT_PATH, "utf-8")
|
|
5466
5730
|
};
|
|
5467
5731
|
}
|
|
5468
5732
|
function trustCertInKeychain() {
|
|
@@ -5524,7 +5788,7 @@ function writeTokenToShellRc(key, value) {
|
|
|
5524
5788
|
const exportLine = buildExportLine(key, value, isFish);
|
|
5525
5789
|
const fullPath = expandHome(rcPath);
|
|
5526
5790
|
try {
|
|
5527
|
-
const existing =
|
|
5791
|
+
const existing = readFileSync12(fullPath, "utf-8");
|
|
5528
5792
|
if (existing.includes(`${key}=`) || existing.includes(`${key} "`)) {
|
|
5529
5793
|
const lines = existing.split("\n");
|
|
5530
5794
|
const pattern = isFish ? new RegExp(`^set\\s+-gx\\s+${key}\\s+`) : new RegExp(`^export\\s+${key}=`);
|
|
@@ -5554,9 +5818,9 @@ ${exportLine}
|
|
|
5554
5818
|
}
|
|
5555
5819
|
}
|
|
5556
5820
|
async function integrationsSetupSlackCommand() {
|
|
5557
|
-
console.log(
|
|
5821
|
+
console.log(chalk12.bold("\nSlack Integration Setup\n"));
|
|
5558
5822
|
if (hasSlackToken()) {
|
|
5559
|
-
console.log(
|
|
5823
|
+
console.log(chalk12.green(" SLACK_USER_TOKEN is already set in your environment\n"));
|
|
5560
5824
|
const { reauth } = await inquirer5.prompt([
|
|
5561
5825
|
{
|
|
5562
5826
|
type: "confirm",
|
|
@@ -5574,23 +5838,23 @@ async function integrationsSetupSlackCommand() {
|
|
|
5574
5838
|
const clientSecret = process.env.SLACK_CLIENT_SECRET;
|
|
5575
5839
|
if (!clientId || !clientSecret) {
|
|
5576
5840
|
const { rcPath: rcPath2 } = getShellInfo();
|
|
5577
|
-
console.log(
|
|
5578
|
-
console.log(
|
|
5579
|
-
console.log(
|
|
5841
|
+
console.log(chalk12.yellow(" Missing Slack app credentials.\n"));
|
|
5842
|
+
console.log(chalk12.gray(' Get Client ID and Client Secret from 1Password ("Droid Slack App")'));
|
|
5843
|
+
console.log(chalk12.gray(` and add to your ${rcPath2}:
|
|
5580
5844
|
`));
|
|
5581
|
-
console.log(
|
|
5582
|
-
console.log(
|
|
5583
|
-
console.log(
|
|
5584
|
-
console.log(
|
|
5845
|
+
console.log(chalk12.white(' export SLACK_CLIENT_ID="your-client-id"'));
|
|
5846
|
+
console.log(chalk12.white(' export SLACK_CLIENT_SECRET="your-client-secret"\n'));
|
|
5847
|
+
console.log(chalk12.gray(" Then reload and run this again:\n"));
|
|
5848
|
+
console.log(chalk12.white(` source ${rcPath2} && droid integrations setup slack
|
|
5585
5849
|
`));
|
|
5586
5850
|
return;
|
|
5587
5851
|
}
|
|
5588
|
-
console.log(
|
|
5852
|
+
console.log(chalk12.gray(" Checking credentials...") + chalk12.green(" SLACK_CLIENT_ID found"));
|
|
5589
5853
|
const authorizeUrl = `https://slack.com/oauth/v2/authorize?client_id=${clientId}&user_scope=${SLACK_SCOPES}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`;
|
|
5590
5854
|
getOrCreateCert();
|
|
5591
5855
|
const certTrusted = getConfigValue("integrations.slack.cert_trusted");
|
|
5592
5856
|
if (!certTrusted) {
|
|
5593
|
-
console.log(
|
|
5857
|
+
console.log(chalk12.gray(" The OAuth callback uses a local HTTPS certificate."));
|
|
5594
5858
|
const { trust } = await inquirer5.prompt([
|
|
5595
5859
|
{
|
|
5596
5860
|
type: "confirm",
|
|
@@ -5600,45 +5864,45 @@ async function integrationsSetupSlackCommand() {
|
|
|
5600
5864
|
}
|
|
5601
5865
|
]);
|
|
5602
5866
|
if (trust) {
|
|
5603
|
-
console.log(
|
|
5867
|
+
console.log(chalk12.gray(" Adding certificate to Keychain (you may be prompted for your password)..."));
|
|
5604
5868
|
if (trustCertInKeychain()) {
|
|
5605
|
-
console.log(
|
|
5869
|
+
console.log(chalk12.green(" Certificate trusted."));
|
|
5606
5870
|
setConfigValue("integrations.slack.cert_trusted", true);
|
|
5607
5871
|
} else {
|
|
5608
|
-
console.log(
|
|
5872
|
+
console.log(chalk12.yellow(" Could not trust certificate \u2014 you may see a browser warning."));
|
|
5609
5873
|
}
|
|
5610
5874
|
}
|
|
5611
5875
|
console.log("");
|
|
5612
5876
|
}
|
|
5613
|
-
console.log(
|
|
5877
|
+
console.log(chalk12.gray(" Opening browser for Slack authorisation..."));
|
|
5614
5878
|
const callbackPromise = waitForCallback();
|
|
5615
5879
|
try {
|
|
5616
5880
|
execSync6(`open "${authorizeUrl}"`, { stdio: "ignore" });
|
|
5617
5881
|
} catch {
|
|
5618
|
-
console.log(
|
|
5619
|
-
console.log(
|
|
5882
|
+
console.log(chalk12.gray("\n Could not open browser. Open this URL manually:\n"));
|
|
5883
|
+
console.log(chalk12.cyan(` ${authorizeUrl}
|
|
5620
5884
|
`));
|
|
5621
5885
|
}
|
|
5622
|
-
console.log(
|
|
5886
|
+
console.log(chalk12.gray(" Waiting for callback..."));
|
|
5623
5887
|
let code;
|
|
5624
5888
|
try {
|
|
5625
5889
|
code = await callbackPromise;
|
|
5626
5890
|
} catch (error) {
|
|
5627
|
-
console.log(
|
|
5891
|
+
console.log(chalk12.red(`
|
|
5628
5892
|
${error instanceof Error ? error.message : "Failed to receive callback"}`));
|
|
5629
5893
|
return;
|
|
5630
5894
|
}
|
|
5631
|
-
console.log(
|
|
5895
|
+
console.log(chalk12.green(" Authorisation received"));
|
|
5632
5896
|
const result = await exchangeOAuthCode(clientId, clientSecret, code, REDIRECT_URI);
|
|
5633
5897
|
if (!result.ok || !result.token) {
|
|
5634
|
-
console.log(
|
|
5898
|
+
console.log(chalk12.red(`
|
|
5635
5899
|
Slack API error: ${result.error}`));
|
|
5636
5900
|
if (result.error === "invalid_code") {
|
|
5637
|
-
console.log(
|
|
5901
|
+
console.log(chalk12.gray(" The code may have expired. Try again."));
|
|
5638
5902
|
}
|
|
5639
5903
|
return;
|
|
5640
5904
|
}
|
|
5641
|
-
console.log(
|
|
5905
|
+
console.log(chalk12.green(" Token exchanged successfully"));
|
|
5642
5906
|
const { rcPath } = getShellInfo();
|
|
5643
5907
|
const { writeToRc } = await inquirer5.prompt([
|
|
5644
5908
|
{
|
|
@@ -5651,91 +5915,91 @@ async function integrationsSetupSlackCommand() {
|
|
|
5651
5915
|
if (writeToRc) {
|
|
5652
5916
|
const written = writeTokenToShellRc("SLACK_USER_TOKEN", result.token);
|
|
5653
5917
|
if (written) {
|
|
5654
|
-
console.log(
|
|
5918
|
+
console.log(chalk12.green(`
|
|
5655
5919
|
Token saved to ${rcPath}`));
|
|
5656
|
-
console.log(
|
|
5920
|
+
console.log(chalk12.gray(" Source your shell or open a new tab to use it."));
|
|
5657
5921
|
} else {
|
|
5658
|
-
console.log(
|
|
5922
|
+
console.log(chalk12.yellow(`
|
|
5659
5923
|
Could not write to ${rcPath}. Add manually:
|
|
5660
5924
|
`));
|
|
5661
5925
|
const { isFish } = getShellInfo();
|
|
5662
|
-
console.log(
|
|
5926
|
+
console.log(chalk12.white(` ${buildExportLine("SLACK_USER_TOKEN", result.token, isFish)}
|
|
5663
5927
|
`));
|
|
5664
5928
|
}
|
|
5665
5929
|
} else {
|
|
5666
5930
|
const { isFish } = getShellInfo();
|
|
5667
|
-
console.log(
|
|
5668
|
-
console.log(
|
|
5931
|
+
console.log(chalk12.yellow("\n Add to your shell config manually:\n"));
|
|
5932
|
+
console.log(chalk12.white(` ${buildExportLine("SLACK_USER_TOKEN", result.token, isFish)}
|
|
5669
5933
|
`));
|
|
5670
5934
|
}
|
|
5671
5935
|
setConfigValue("integrations.slack.configured", true);
|
|
5672
|
-
console.log(
|
|
5936
|
+
console.log(chalk12.green("\n Slack integration configured!\n"));
|
|
5673
5937
|
}
|
|
5674
5938
|
async function integrationsStatusCommand() {
|
|
5675
|
-
console.log(
|
|
5676
|
-
console.log(
|
|
5939
|
+
console.log(chalk12.bold("\nIntegrations Status\n"));
|
|
5940
|
+
console.log(chalk12.bold(" Slack"));
|
|
5677
5941
|
const configured = getConfigValue("integrations.slack.configured");
|
|
5678
5942
|
const clientId = process.env.SLACK_CLIENT_ID;
|
|
5679
5943
|
const clientSecret = process.env.SLACK_CLIENT_SECRET;
|
|
5680
5944
|
const hasCredentials = clientId && clientSecret;
|
|
5681
5945
|
if (hasCredentials) {
|
|
5682
|
-
console.log(
|
|
5946
|
+
console.log(chalk12.green(" App credentials configured"));
|
|
5683
5947
|
} else {
|
|
5684
|
-
console.log(
|
|
5685
|
-
console.log(
|
|
5948
|
+
console.log(chalk12.yellow(" App credentials missing"));
|
|
5949
|
+
console.log(chalk12.gray(" Run: droid integrations setup slack"));
|
|
5686
5950
|
}
|
|
5687
5951
|
if (hasSlackToken()) {
|
|
5688
5952
|
const token = process.env.SLACK_USER_TOKEN;
|
|
5689
5953
|
const masked = token.slice(0, 10) + "..." + token.slice(-4);
|
|
5690
|
-
console.log(
|
|
5691
|
-
console.log(
|
|
5954
|
+
console.log(chalk12.green(" User token configured"));
|
|
5955
|
+
console.log(chalk12.gray(` Token: ${masked}`));
|
|
5692
5956
|
} else {
|
|
5693
|
-
console.log(
|
|
5957
|
+
console.log(chalk12.yellow(" User token missing"));
|
|
5694
5958
|
if (hasCredentials) {
|
|
5695
|
-
console.log(
|
|
5959
|
+
console.log(chalk12.gray(" Run: droid integrations setup slack"));
|
|
5696
5960
|
}
|
|
5697
5961
|
}
|
|
5698
5962
|
if (configured) {
|
|
5699
|
-
console.log(
|
|
5963
|
+
console.log(chalk12.green(" Status: configured"));
|
|
5700
5964
|
} else {
|
|
5701
|
-
console.log(
|
|
5965
|
+
console.log(chalk12.yellow(" Status: not configured"));
|
|
5702
5966
|
}
|
|
5703
5967
|
console.log("");
|
|
5704
|
-
console.log(
|
|
5968
|
+
console.log(chalk12.bold(" Atlassian"));
|
|
5705
5969
|
const atlassianConfigured = getConfigValue("integrations.atlassian.configured");
|
|
5706
5970
|
if (atlassianConfigured) {
|
|
5707
|
-
console.log(
|
|
5708
|
-
console.log(
|
|
5971
|
+
console.log(chalk12.green(" MCP: Connected"));
|
|
5972
|
+
console.log(chalk12.green(" Status: configured"));
|
|
5709
5973
|
} else {
|
|
5710
|
-
console.log(
|
|
5711
|
-
console.log(
|
|
5974
|
+
console.log(chalk12.yellow(" MCP: Not yet verified"));
|
|
5975
|
+
console.log(chalk12.gray(" Use /share confluence to verify, or see setup guide"));
|
|
5712
5976
|
}
|
|
5713
5977
|
console.log("");
|
|
5714
|
-
console.log(
|
|
5978
|
+
console.log(chalk12.bold(" GitHub"));
|
|
5715
5979
|
const githubConfigured = getConfigValue("integrations.github.configured");
|
|
5716
5980
|
if (githubConfigured) {
|
|
5717
|
-
console.log(
|
|
5718
|
-
console.log(
|
|
5981
|
+
console.log(chalk12.green(" CLI: Installed"));
|
|
5982
|
+
console.log(chalk12.green(" Status: configured"));
|
|
5719
5983
|
} else {
|
|
5720
|
-
console.log(
|
|
5721
|
-
console.log(
|
|
5984
|
+
console.log(chalk12.yellow(" CLI: Not verified"));
|
|
5985
|
+
console.log(chalk12.gray(" Run: gh auth login"));
|
|
5722
5986
|
}
|
|
5723
5987
|
console.log("");
|
|
5724
|
-
console.log(
|
|
5988
|
+
console.log(chalk12.bold(" Granola"));
|
|
5725
5989
|
const granolaConfigured = getConfigValue("integrations.granola.configured");
|
|
5726
5990
|
if (granolaConfigured) {
|
|
5727
|
-
console.log(
|
|
5728
|
-
console.log(
|
|
5991
|
+
console.log(chalk12.green(" MCP: Connected"));
|
|
5992
|
+
console.log(chalk12.green(" Status: configured"));
|
|
5729
5993
|
} else {
|
|
5730
|
-
console.log(
|
|
5731
|
-
console.log(
|
|
5994
|
+
console.log(chalk12.yellow(" MCP: Not yet verified"));
|
|
5995
|
+
console.log(chalk12.gray(" Use /mcp to add the Granola server, then verify with a meeting query"));
|
|
5732
5996
|
}
|
|
5733
5997
|
console.log("");
|
|
5734
5998
|
}
|
|
5735
5999
|
async function slackPostCommand(options) {
|
|
5736
6000
|
let input;
|
|
5737
6001
|
try {
|
|
5738
|
-
input =
|
|
6002
|
+
input = readFileSync12(0, "utf-8").trim();
|
|
5739
6003
|
} catch {
|
|
5740
6004
|
console.log(JSON.stringify({ ok: false, error: "Failed to read from stdin. Pipe JSON payload via stdin." }));
|
|
5741
6005
|
process.exit(1);
|
|
@@ -5787,6 +6051,7 @@ program.command("install <tool>").description("Install a tool and run its setup
|
|
|
5787
6051
|
program.command("uninstall <tool>").description("Uninstall a tool").action(uninstallCommand);
|
|
5788
6052
|
program.command("update").description("Update droid and installed tools").option("--tools", "Only update tools").option("--cli", "Only update the CLI").argument("[tool]", "Update a specific tool").action(updateCommand);
|
|
5789
6053
|
program.command("tui").description("Launch interactive TUI dashboard").action(tuiCommand);
|
|
6054
|
+
program.command("pack").description("Create audience-filtered zip packs for distribution").argument("[audience]", "Target audience (e.g., engineering, customer-support)").option("-l, --list", "List available audiences and tool counts").option("-o, --output <dir>", "Output directory (default: cwd)").action(packCommand);
|
|
5790
6055
|
program.command("exec <tool> <script>").description("Execute a tool script").argument("[args...]", "Arguments to pass to the script").allowUnknownOption().action(execCommand);
|
|
5791
6056
|
var integrations = program.command("integrations").description("Manage external service integrations");
|
|
5792
6057
|
var integrationsSetup = integrations.command("setup").description("Set up an integration");
|
|
@@ -5799,8 +6064,8 @@ if (configExists()) {
|
|
|
5799
6064
|
const config = loadConfig();
|
|
5800
6065
|
const newPlatforms = syncNewPlatforms(config);
|
|
5801
6066
|
if (newPlatforms.length > 0) {
|
|
5802
|
-
console.log(
|
|
5803
|
-
console.log(
|
|
6067
|
+
console.log(chalk13.green(`\u2713 Detected new platform(s): ${newPlatforms.join(", ")}`));
|
|
6068
|
+
console.log(chalk13.gray(" Synced installed tools to new platform(s)\n"));
|
|
5804
6069
|
saveConfig(config);
|
|
5805
6070
|
}
|
|
5806
6071
|
}
|