@uluops/setup 0.4.0 → 0.6.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/LICENSE +21 -0
- package/README.md +67 -50
- package/assets/auto-tracker-save.mjs +142 -0
- package/assets/{agents → claude-code/agents}/api-contract-validator-agent.md +9 -228
- package/assets/{agents → claude-code/agents}/aristotle-analyst-agent.md +51 -4
- package/assets/{agents → claude-code/agents}/aristotle-explorer-agent.md +6 -2
- package/assets/{agents → claude-code/agents}/aristotle-forecaster-agent.md +15 -230
- package/assets/{agents → claude-code/agents}/aristotle-validator-agent.md +12 -252
- package/assets/{agents → claude-code/agents}/assumption-excavator-agent.md +21 -247
- package/assets/{agents → claude-code/agents}/code-auditor-agent.md +12 -255
- package/assets/{agents → claude-code/agents}/code-optimizer-agent.md +15 -236
- package/assets/{agents → claude-code/agents}/code-validator-agent.md +31 -300
- package/assets/claude-code/agents/docs-validator-agent.md +472 -0
- package/assets/{agents → claude-code/agents}/frontend-validator-agent.md +15 -258
- package/assets/{agents → claude-code/agents}/mcp-validator-agent.md +8 -252
- package/assets/{agents → claude-code/agents}/pre-implementation-architect-agent.md +8 -224
- package/assets/{agents → claude-code/agents}/prompt-engineer-agent.md +57 -290
- package/assets/{agents → claude-code/agents}/prompt-pattern-analyzer-agent.md +10 -225
- package/assets/{agents → claude-code/agents}/prompt-quality-validator-agent.md +11 -249
- package/assets/{agents → claude-code/agents}/public-interface-validator-agent.md +15 -268
- package/assets/claude-code/agents/release-readiness-agent.md +495 -0
- package/assets/{agents → claude-code/agents}/security-analyst-agent.md +236 -480
- package/assets/{agents → claude-code/agents}/test-architect-agent.md +16 -259
- package/assets/{agents → claude-code/agents}/type-safety-validator-agent.md +23 -266
- package/assets/{agents → claude-code/agents}/workflow-synthesis-agent.md +23 -226
- package/assets/{commands → claude-code/commands}/agents/anxiety-reader.md +12 -15
- package/assets/{commands → claude-code/commands}/agents/api-contract.md +156 -136
- package/assets/{commands → claude-code/commands}/agents/architect.md +156 -136
- package/assets/claude-code/commands/agents/aristotle-analyst.md +157 -0
- package/assets/claude-code/commands/agents/aristotle-explorer.md +157 -0
- package/assets/claude-code/commands/agents/aristotle-forecaster.md +157 -0
- package/assets/claude-code/commands/agents/aristotle-validator.md +157 -0
- package/assets/{commands → claude-code/commands}/agents/assumption-excavator.md +49 -7
- package/assets/{commands → claude-code/commands}/agents/audit.md +156 -137
- package/assets/{commands → claude-code/commands}/agents/docs-validate.md +156 -134
- package/assets/{commands → claude-code/commands}/agents/frontend.md +156 -136
- package/assets/{commands → claude-code/commands}/agents/mcp-validate.md +156 -137
- package/assets/{commands → claude-code/commands}/agents/optimize.md +156 -134
- package/assets/{commands → claude-code/commands}/agents/pattern-analyzer.md +150 -127
- package/assets/{commands → claude-code/commands}/agents/prompt-quality.md +155 -135
- package/assets/claude-code/commands/agents/prompt-validate.md +155 -0
- package/assets/{commands → claude-code/commands}/agents/public-interface.md +156 -135
- package/assets/{commands → claude-code/commands}/agents/release.md +156 -136
- package/assets/{commands → claude-code/commands}/agents/security.md +156 -138
- package/assets/{commands → claude-code/commands}/agents/test-review.md +156 -137
- package/assets/{commands → claude-code/commands}/agents/type-safety.md +156 -136
- package/assets/{commands/agents/code-validate.md → claude-code/commands/agents/validate.md} +156 -135
- package/assets/claude-code/commands/agents/workflow-synthesis.md +157 -0
- package/assets/{commands → claude-code/commands}/pipelines/aristotle.md +8 -8
- package/assets/{commands → claude-code/commands}/pipelines/ship.md +8 -8
- package/assets/claude-code/commands/workflows/post-implementation.md +60 -0
- package/assets/claude-code/commands/workflows/pre-implementation.md +46 -0
- package/assets/{commands → claude-code/commands}/workflows/prompt-audit.md +2 -2
- package/assets/codex/agents/anxiety-reader-agent.toml +462 -0
- package/assets/codex/agents/api-contract-validator-agent.toml +738 -0
- package/assets/codex/agents/aristotle-analyst-agent.toml +750 -0
- package/assets/codex/agents/aristotle-explorer-agent.toml +155 -0
- package/assets/codex/agents/aristotle-forecaster-agent.toml +449 -0
- package/assets/codex/agents/aristotle-validator-agent.toml +424 -0
- package/assets/codex/agents/assumption-excavator-agent.toml +1126 -0
- package/assets/codex/agents/code-auditor-agent.toml +815 -0
- package/assets/codex/agents/code-optimizer-agent.toml +652 -0
- package/assets/codex/agents/code-validator-agent.toml +573 -0
- package/assets/codex/agents/docs-validator-agent.toml +468 -0
- package/assets/codex/agents/frontend-validator-agent.toml +598 -0
- package/assets/codex/agents/mcp-validator-agent.toml +580 -0
- package/assets/codex/agents/pre-implementation-architect-agent.toml +817 -0
- package/assets/codex/agents/prompt-engineer-agent.toml +922 -0
- package/assets/codex/agents/prompt-pattern-analyzer-agent.toml +689 -0
- package/assets/codex/agents/prompt-quality-validator-agent.toml +777 -0
- package/assets/codex/agents/public-interface-validator-agent.toml +695 -0
- package/assets/codex/agents/release-readiness-agent.toml +491 -0
- package/assets/codex/agents/security-analyst-agent.toml +847 -0
- package/assets/codex/agents/test-architect-agent.toml +615 -0
- package/assets/codex/agents/type-safety-validator-agent.toml +686 -0
- package/assets/codex/agents/workflow-synthesis-agent.toml +631 -0
- package/assets/gemini-cli/agents/anxiety-reader-agent.md +470 -0
- package/assets/gemini-cli/agents/api-contract-validator-agent.md +747 -0
- package/assets/gemini-cli/agents/aristotle-analyst-agent.md +758 -0
- package/assets/gemini-cli/agents/aristotle-explorer-agent.md +163 -0
- package/assets/gemini-cli/agents/aristotle-forecaster-agent.md +457 -0
- package/assets/gemini-cli/agents/aristotle-validator-agent.md +432 -0
- package/assets/gemini-cli/agents/assumption-excavator-agent.md +1134 -0
- package/assets/gemini-cli/agents/code-auditor-agent.md +827 -0
- package/assets/gemini-cli/agents/code-optimizer-agent.md +661 -0
- package/assets/gemini-cli/agents/code-validator-agent.md +582 -0
- package/assets/gemini-cli/agents/docs-validator-agent.md +477 -0
- package/assets/gemini-cli/agents/frontend-validator-agent.md +610 -0
- package/assets/gemini-cli/agents/mcp-validator-agent.md +589 -0
- package/assets/gemini-cli/agents/pre-implementation-architect-agent.md +826 -0
- package/assets/gemini-cli/agents/prompt-engineer-agent.md +931 -0
- package/assets/gemini-cli/agents/prompt-pattern-analyzer-agent.md +698 -0
- package/assets/gemini-cli/agents/prompt-quality-validator-agent.md +786 -0
- package/assets/gemini-cli/agents/public-interface-validator-agent.md +707 -0
- package/assets/gemini-cli/agents/release-readiness-agent.md +500 -0
- package/assets/gemini-cli/agents/security-analyst-agent.md +859 -0
- package/assets/gemini-cli/agents/test-architect-agent.md +624 -0
- package/assets/gemini-cli/agents/type-safety-validator-agent.md +695 -0
- package/assets/gemini-cli/agents/workflow-synthesis-agent.md +639 -0
- package/assets/gemini-cli/commands/agents/anxiety-reader.toml +155 -0
- package/assets/gemini-cli/commands/agents/api-contract.toml +154 -0
- package/assets/gemini-cli/commands/agents/architect.toml +154 -0
- package/assets/gemini-cli/commands/agents/aristotle-analyst.toml +155 -0
- package/assets/gemini-cli/commands/agents/aristotle-explorer.toml +155 -0
- package/assets/gemini-cli/commands/agents/aristotle-forecaster.toml +155 -0
- package/assets/gemini-cli/commands/agents/aristotle-validator.toml +155 -0
- package/assets/gemini-cli/commands/agents/assumption-excavator.toml +155 -0
- package/assets/gemini-cli/commands/agents/audit.toml +154 -0
- package/assets/gemini-cli/commands/agents/docs-validate.toml +154 -0
- package/assets/gemini-cli/commands/agents/frontend.toml +154 -0
- package/assets/gemini-cli/commands/agents/mcp-validate.toml +154 -0
- package/assets/gemini-cli/commands/agents/optimize.toml +154 -0
- package/assets/gemini-cli/commands/agents/pattern-analyzer.toml +148 -0
- package/assets/gemini-cli/commands/agents/prompt-quality.toml +153 -0
- package/assets/gemini-cli/commands/agents/prompt-validate.toml +153 -0
- package/assets/gemini-cli/commands/agents/public-interface.toml +154 -0
- package/assets/gemini-cli/commands/agents/release.toml +154 -0
- package/assets/gemini-cli/commands/agents/security.toml +154 -0
- package/assets/gemini-cli/commands/agents/test-review.toml +154 -0
- package/assets/gemini-cli/commands/agents/type-safety.toml +154 -0
- package/assets/gemini-cli/commands/agents/validate.toml +154 -0
- package/assets/gemini-cli/commands/agents/workflow-synthesis.toml +155 -0
- package/assets/gemini-cli/commands/pipelines/aristotle.toml +139 -0
- package/assets/gemini-cli/commands/pipelines/ship.toml +184 -0
- package/assets/gemini-cli/commands/workflows/post-implementation.toml +56 -0
- package/assets/gemini-cli/commands/workflows/pre-implementation.toml +42 -0
- package/assets/gemini-cli/commands/workflows/prompt-audit.toml +40 -0
- package/assets/opencode/agents/anxiety-reader-agent.md +472 -0
- package/assets/opencode/agents/api-contract-validator-agent.md +749 -0
- package/assets/opencode/agents/aristotle-analyst-agent.md +760 -0
- package/assets/opencode/agents/aristotle-explorer-agent.md +164 -0
- package/assets/opencode/agents/aristotle-forecaster-agent.md +459 -0
- package/assets/opencode/agents/aristotle-validator-agent.md +434 -0
- package/assets/opencode/agents/assumption-excavator-agent.md +1136 -0
- package/assets/opencode/agents/code-auditor-agent.md +826 -0
- package/assets/opencode/agents/code-optimizer-agent.md +663 -0
- package/assets/opencode/agents/code-validator-agent.md +584 -0
- package/assets/opencode/agents/docs-validator-agent.md +479 -0
- package/assets/opencode/agents/frontend-validator-agent.md +609 -0
- package/assets/opencode/agents/mcp-validator-agent.md +591 -0
- package/assets/opencode/agents/pre-implementation-architect-agent.md +828 -0
- package/assets/opencode/agents/prompt-engineer-agent.md +933 -0
- package/assets/opencode/agents/prompt-pattern-analyzer-agent.md +700 -0
- package/assets/opencode/agents/prompt-quality-validator-agent.md +788 -0
- package/assets/opencode/agents/public-interface-validator-agent.md +706 -0
- package/assets/opencode/agents/release-readiness-agent.md +502 -0
- package/assets/opencode/agents/security-analyst-agent.md +858 -0
- package/assets/opencode/agents/test-architect-agent.md +626 -0
- package/assets/opencode/agents/type-safety-validator-agent.md +697 -0
- package/assets/opencode/agents/workflow-synthesis-agent.md +641 -0
- package/dist/cli.js +12 -414
- package/dist/commands/helpers.d.ts +73 -0
- package/dist/commands/helpers.js +274 -0
- package/dist/commands/setup.d.ts +13 -0
- package/dist/commands/setup.js +93 -0
- package/dist/commands/uninstall.d.ts +3 -0
- package/dist/commands/uninstall.js +126 -0
- package/dist/commands/verify.d.ts +1 -0
- package/dist/commands/verify.js +28 -0
- package/dist/harnesses/claude-code.d.ts +1 -1
- package/dist/harnesses/claude-code.js +3 -1
- package/dist/harnesses/codex.js +6 -5
- package/dist/harnesses/gemini-cli.d.ts +4 -8
- package/dist/harnesses/gemini-cli.js +47 -21
- package/dist/harnesses/index.d.ts +10 -1
- package/dist/harnesses/index.js +11 -2
- package/dist/harnesses/opencode.d.ts +1 -1
- package/dist/harnesses/opencode.js +15 -6
- package/dist/harnesses/types.d.ts +19 -0
- package/dist/harnesses/types.js +2 -0
- package/dist/lib/asset-catalog.js +2 -2
- package/dist/lib/config-merger.d.ts +2 -1
- package/dist/lib/config-merger.js +12 -4
- package/dist/lib/file-ops.d.ts +5 -0
- package/dist/lib/file-ops.js +18 -3
- package/dist/lib/hash.d.ts +1 -1
- package/dist/lib/hash.js +2 -2
- package/dist/lib/manifest.d.ts +30 -1
- package/dist/lib/manifest.js +5 -7
- package/dist/lib/paths.d.ts +16 -1
- package/dist/lib/paths.js +31 -3
- package/dist/lib/settings-merger.d.ts +24 -9
- package/dist/lib/settings-merger.js +57 -22
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.js +10 -0
- package/dist/steps/agents.d.ts +1 -2
- package/dist/steps/agents.js +7 -18
- package/dist/steps/cli.d.ts +53 -0
- package/dist/steps/cli.js +90 -0
- package/dist/steps/commands.d.ts +1 -1
- package/dist/steps/commands.js +20 -71
- package/dist/steps/detect.js +4 -0
- package/dist/steps/mcp.js +7 -15
- package/dist/steps/metrics.d.ts +12 -0
- package/dist/steps/metrics.js +52 -22
- package/dist/steps/shell.js +11 -1
- package/dist/steps/signup.d.ts +2 -2
- package/dist/steps/signup.js +9 -12
- package/dist/steps/verify.js +47 -8
- package/package.json +12 -11
- package/assets/agents/docs-validator-agent.md +0 -490
- package/assets/agents/release-readiness-agent.md +0 -482
- package/assets/commands/agents/aristotle-analyst.md +0 -116
- package/assets/commands/agents/aristotle-explorer.md +0 -93
- package/assets/commands/agents/aristotle-forecaster.md +0 -115
- package/assets/commands/agents/aristotle-validator.md +0 -115
- package/assets/commands/agents/prompt-validate.md +0 -136
- package/assets/commands/agents/workflow-synthesis.md +0 -102
- package/assets/commands/workflows/post-implementation.md +0 -577
- package/assets/commands/workflows/pre-implementation.md +0 -670
- /package/assets/{agents → claude-code/agents}/anxiety-reader-agent.md +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readdir } from "node:fs/promises";
|
|
4
|
+
import { detect } from "../steps/detect.js";
|
|
5
|
+
import { signup } from "../steps/signup.js";
|
|
6
|
+
import { resolveApiKey } from "../steps/auth.js";
|
|
7
|
+
import { installMcp } from "../steps/mcp.js";
|
|
8
|
+
import { installAgents } from "../steps/agents.js";
|
|
9
|
+
import { installCommands } from "../steps/commands.js";
|
|
10
|
+
import { installMetrics } from "../steps/metrics.js";
|
|
11
|
+
import { installCli, CLI_PACKAGE } from "../steps/cli.js";
|
|
12
|
+
import { writeShellExport } from "../steps/shell.js";
|
|
13
|
+
import { probeHookSupport } from "../lib/settings-merger.js";
|
|
14
|
+
import { findProjectRoot, ASSETS_DIR } from "../lib/paths.js";
|
|
15
|
+
import { getHealthTimeout } from "../lib/health.js";
|
|
16
|
+
import { ok, warn, fail, info } from "../lib/display.js";
|
|
17
|
+
/** Resolve API key via flag, env, file, signup, or interactive prompt. Returns env detection + key. */
|
|
18
|
+
export async function initContext(opts) {
|
|
19
|
+
const env = await detect();
|
|
20
|
+
let apiKey;
|
|
21
|
+
try {
|
|
22
|
+
if (opts.signup) {
|
|
23
|
+
info("Create your UluOps account\n");
|
|
24
|
+
const auth = await signup();
|
|
25
|
+
apiKey = auth.apiKey;
|
|
26
|
+
ok(`Account created (${auth.email})`);
|
|
27
|
+
ok(`API key generated`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const auth = await resolveApiKey({
|
|
31
|
+
apiKeyFlag: opts.apiKey,
|
|
32
|
+
skipValidation: opts.skipValidation,
|
|
33
|
+
interactive: !opts.yes && !opts.apiKey && !process.env["ULUOPS_API_KEY"],
|
|
34
|
+
});
|
|
35
|
+
apiKey = auth.apiKey;
|
|
36
|
+
if (auth.email)
|
|
37
|
+
ok(`Key validated (${auth.email})`);
|
|
38
|
+
else if (opts.skipValidation)
|
|
39
|
+
ok("Key accepted (validation skipped)");
|
|
40
|
+
else
|
|
41
|
+
ok("Key validated");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
return { env, apiKey };
|
|
49
|
+
}
|
|
50
|
+
/** Write MCP server entries to harness config and report warnings. */
|
|
51
|
+
export async function configureMcpStep(profile, apiKey, opts) {
|
|
52
|
+
const res = await installMcp(profile, apiKey, opts.scope, opts.dryRun);
|
|
53
|
+
ok(`MCP config → ${res.configPath} (2 servers)`);
|
|
54
|
+
for (const w of res.packageWarnings)
|
|
55
|
+
warn(w);
|
|
56
|
+
return res;
|
|
57
|
+
}
|
|
58
|
+
/** Copy agent definitions from assets to harness directory. */
|
|
59
|
+
export async function installAgentsDefs(profile, opts, prev) {
|
|
60
|
+
const res = await installAgents(profile, opts.localDefs, opts.dryRun, prev);
|
|
61
|
+
const parts = [];
|
|
62
|
+
if (res.copied > 0)
|
|
63
|
+
parts.push(`${res.copied} copied`);
|
|
64
|
+
if (res.skipped > 0)
|
|
65
|
+
parts.push(`${res.skipped} unchanged`);
|
|
66
|
+
if (res.removed > 0)
|
|
67
|
+
parts.push(`${res.removed} removed`);
|
|
68
|
+
const dest = opts.localDefs
|
|
69
|
+
? "./uluops/agents/"
|
|
70
|
+
: `${profile.paths.agentsDir.replace(process.env["HOME"] ?? "", "~")}/`;
|
|
71
|
+
ok(`${res.files.length} agents → ${dest}${parts.length ? ` (${parts.join(", ")})` : ""}`);
|
|
72
|
+
return res;
|
|
73
|
+
}
|
|
74
|
+
/** Copy slash-command definitions from assets (Claude Code only). */
|
|
75
|
+
export async function installCommandsDefs(profile, opts, prev) {
|
|
76
|
+
const res = await installCommands(profile, opts.localDefs, opts.dryRun, prev);
|
|
77
|
+
if (res.skippedReason === "not-supported") {
|
|
78
|
+
info(chalk.dim(`Commands not yet supported for ${profile.displayName} (coming soon)`));
|
|
79
|
+
return res;
|
|
80
|
+
}
|
|
81
|
+
const total = res.agentCommands + res.workflowCommands + res.pipelineCommands;
|
|
82
|
+
const parts = [];
|
|
83
|
+
if (total > 0)
|
|
84
|
+
parts.push(`${total} copied`);
|
|
85
|
+
if (res.skipped > 0)
|
|
86
|
+
parts.push(`${res.skipped} unchanged`);
|
|
87
|
+
if (res.removed > 0)
|
|
88
|
+
parts.push(`${res.removed} removed`);
|
|
89
|
+
const dest = opts.localDefs
|
|
90
|
+
? "./uluops/commands/"
|
|
91
|
+
: `${profile.paths.commandsDir.replace(process.env["HOME"] ?? "", "~")}/`;
|
|
92
|
+
ok(`${res.files.length} commands → ${dest}${parts.length ? ` (${parts.join(", ")})` : ""}`);
|
|
93
|
+
return res;
|
|
94
|
+
}
|
|
95
|
+
/** Install agent-metrics hook and tool files (Claude Code only). */
|
|
96
|
+
export async function configureMetricsStep(profile, opts) {
|
|
97
|
+
if (!profile.hooks) {
|
|
98
|
+
info(chalk.dim(`Metrics hooks not supported for ${profile.displayName}`));
|
|
99
|
+
return { toolFilesCopied: 0, hookConfigured: false, hooksInstalledVersion: null };
|
|
100
|
+
}
|
|
101
|
+
const probe = probeHookSupport();
|
|
102
|
+
if (probe.warning)
|
|
103
|
+
warn(probe.warning);
|
|
104
|
+
const res = await installMetrics(profile, opts.dryRun);
|
|
105
|
+
if (res.hookConfigured) {
|
|
106
|
+
const parts = [];
|
|
107
|
+
if (res.toolFilesCopied > 0)
|
|
108
|
+
parts.push(`${res.toolFilesCopied} files`);
|
|
109
|
+
parts.push("hook configured");
|
|
110
|
+
const toolPath = profile.paths.toolsDir?.replace(process.env["HOME"] ?? "", "~");
|
|
111
|
+
ok(`Agent metrics → ${toolPath}/ (${parts.join(", ")})`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
warn("Agent metrics hook not configured (tool files not found)");
|
|
115
|
+
}
|
|
116
|
+
return res;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Decide whether to install `@uluops/cli` globally and do it (or not).
|
|
120
|
+
*
|
|
121
|
+
* Decision matrix:
|
|
122
|
+
* - `--no-cli` (opts.cli === false) → skip, no prompt
|
|
123
|
+
* - `--with-cli` (opts.withCli === true) → install, no prompt
|
|
124
|
+
* - Neither flag + non-interactive (--yes / --api-key / no TTY) → skip
|
|
125
|
+
* - Neither flag + interactive → prompt (default Y)
|
|
126
|
+
*
|
|
127
|
+
* Returns null when the step did not run (skipped). Returns a `CliInstallResult`
|
|
128
|
+
* when an install attempt was made, with details for the manifest.
|
|
129
|
+
*/
|
|
130
|
+
export async function configureCliStep(opts) {
|
|
131
|
+
if (opts.cli === false) {
|
|
132
|
+
info(chalk.dim(`Skipped global ${CLI_PACKAGE} install (--no-cli)`));
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
let shouldInstall;
|
|
136
|
+
if (opts.withCli === true) {
|
|
137
|
+
shouldInstall = true;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const nonInteractive = opts.yes || !!opts.apiKey || !process.stdin.isTTY;
|
|
141
|
+
if (nonInteractive) {
|
|
142
|
+
info(chalk.dim(`Skipped global ${CLI_PACKAGE} install (non-interactive — pass --with-cli to install)`));
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
146
|
+
shouldInstall = await confirm({
|
|
147
|
+
message: `Install ${CLI_PACKAGE} globally (provides the ${chalk.cyan("ulu")} command)?`,
|
|
148
|
+
default: true,
|
|
149
|
+
});
|
|
150
|
+
if (!shouldInstall) {
|
|
151
|
+
info(chalk.dim(`Skipped global ${CLI_PACKAGE} install`));
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const res = await installCli({
|
|
156
|
+
dryRun: opts.dryRun,
|
|
157
|
+
executor: opts.executor,
|
|
158
|
+
});
|
|
159
|
+
if (opts.dryRun && !res.alreadyPresent) {
|
|
160
|
+
ok(`Would install ${CLI_PACKAGE} globally`);
|
|
161
|
+
return res;
|
|
162
|
+
}
|
|
163
|
+
if (res.alreadyPresent) {
|
|
164
|
+
ok(`${CLI_PACKAGE} already installed${res.version ? ` (${res.version})` : ""} — no change`);
|
|
165
|
+
return res;
|
|
166
|
+
}
|
|
167
|
+
if (res.installed) {
|
|
168
|
+
ok(`${CLI_PACKAGE} installed globally${res.version ? ` (${res.version})` : ""}`);
|
|
169
|
+
return res;
|
|
170
|
+
}
|
|
171
|
+
warn(`Could not install ${CLI_PACKAGE} globally — try ${chalk.cyan(`npm install -g ${CLI_PACKAGE}`)} manually`);
|
|
172
|
+
if (res.error) {
|
|
173
|
+
const oneLine = res.error.split("\n")[0]?.slice(0, 120) ?? "";
|
|
174
|
+
if (oneLine)
|
|
175
|
+
info(chalk.dim(` ${oneLine}`));
|
|
176
|
+
}
|
|
177
|
+
return res;
|
|
178
|
+
}
|
|
179
|
+
/** Ping tracker and registry health endpoints. */
|
|
180
|
+
export async function runHealthCheck(opts) {
|
|
181
|
+
if (!opts.skipValidation && !opts.dryRun) {
|
|
182
|
+
try {
|
|
183
|
+
const [trackerOk, registryOk] = await Promise.all([
|
|
184
|
+
checkEndpoint("https://api.uluops.ai/api/v1/health"),
|
|
185
|
+
checkEndpoint("https://api.uluops.ai/api/v1/registry/health"),
|
|
186
|
+
]);
|
|
187
|
+
if (trackerOk && registryOk)
|
|
188
|
+
ok("Health check passed — both APIs reachable");
|
|
189
|
+
else
|
|
190
|
+
warn("Some APIs unreachable (MCP tools may have limited functionality)");
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
warn("Health check skipped (network issue)");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Optionally write ULUOPS_API_KEY export to shell profile. */
|
|
198
|
+
export async function configureShell(env, apiKey, opts) {
|
|
199
|
+
let modified = false;
|
|
200
|
+
if (opts.shell && env.shellProfile) {
|
|
201
|
+
if (!opts.yes && !opts.dryRun) {
|
|
202
|
+
const confirmed = await confirmShellWrite(env.shellProfile);
|
|
203
|
+
if (!confirmed) {
|
|
204
|
+
warn("Skipped writing API key to shell profile");
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
await writeShellExport(env.shellProfile, apiKey, opts.dryRun);
|
|
209
|
+
ok(`ULUOPS_API_KEY added to ${env.shellProfile}`);
|
|
210
|
+
warn("API key stored in plaintext in shell profile. Consider rotating if shared machine.");
|
|
211
|
+
modified = true;
|
|
212
|
+
}
|
|
213
|
+
else if (opts.shell) {
|
|
214
|
+
warn("--shell requested but no supported shell detected ($SHELL). Skipping.");
|
|
215
|
+
}
|
|
216
|
+
return modified;
|
|
217
|
+
}
|
|
218
|
+
/** Interactive y/N confirmation before writing API key to shell profile. */
|
|
219
|
+
export async function confirmShellWrite(profilePath) {
|
|
220
|
+
const readline = await import("node:readline/promises");
|
|
221
|
+
const rl = readline.createInterface({
|
|
222
|
+
input: process.stdin,
|
|
223
|
+
output: process.stdout,
|
|
224
|
+
});
|
|
225
|
+
const answer = await rl.question(`Write ULUOPS_API_KEY to ${profilePath}? (y/N) `);
|
|
226
|
+
rl.close();
|
|
227
|
+
return answer.trim().toLowerCase() === "y";
|
|
228
|
+
}
|
|
229
|
+
/** Warn if existing agent files will be overwritten and prompt for confirmation. */
|
|
230
|
+
export async function checkConflicts(profile, localDefs) {
|
|
231
|
+
const destDir = localDefs
|
|
232
|
+
? join(await findProjectRoot(), "uluops", "agents")
|
|
233
|
+
: profile.paths.agentsDir;
|
|
234
|
+
const srcDir = join(ASSETS_DIR, profile.name, "agents");
|
|
235
|
+
let existingFiles;
|
|
236
|
+
let assetFiles;
|
|
237
|
+
try {
|
|
238
|
+
existingFiles = await readdir(destDir);
|
|
239
|
+
assetFiles = await readdir(srcDir);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const conflicts = assetFiles.filter((f) => existingFiles.includes(f));
|
|
245
|
+
if (conflicts.length === 0)
|
|
246
|
+
return;
|
|
247
|
+
warn(`Found ${conflicts.length} existing agents that match UluOps definitions:`);
|
|
248
|
+
for (const f of conflicts.slice(0, 5)) {
|
|
249
|
+
info(` ${f}`);
|
|
250
|
+
}
|
|
251
|
+
if (conflicts.length > 5) {
|
|
252
|
+
info(` ... and ${conflicts.length - 5} more`);
|
|
253
|
+
}
|
|
254
|
+
console.log();
|
|
255
|
+
info("These will be overwritten.");
|
|
256
|
+
console.log();
|
|
257
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
258
|
+
const proceed = await confirm({ message: "Continue?", default: true });
|
|
259
|
+
if (!proceed) {
|
|
260
|
+
process.exit(0);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** Fetch a URL and return true if the response is OK, false on any failure. */
|
|
264
|
+
async function checkEndpoint(url) {
|
|
265
|
+
try {
|
|
266
|
+
const res = await fetch(url, {
|
|
267
|
+
signal: AbortSignal.timeout(getHealthTimeout()),
|
|
268
|
+
});
|
|
269
|
+
return res.ok;
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function runSetup(opts: {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
signup: boolean;
|
|
4
|
+
scope: "global" | "local";
|
|
5
|
+
localDefs: boolean;
|
|
6
|
+
shell: boolean;
|
|
7
|
+
skipValidation: boolean;
|
|
8
|
+
dryRun: boolean;
|
|
9
|
+
yes: boolean;
|
|
10
|
+
harness: string;
|
|
11
|
+
withCli?: boolean;
|
|
12
|
+
cli?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { loadManifest, saveManifest, } from "../lib/manifest.js";
|
|
4
|
+
import { findProjectRoot } from "../lib/paths.js";
|
|
5
|
+
import { info, printSetupSummary } from "../lib/display.js";
|
|
6
|
+
import { getVersion } from "../lib/version.js";
|
|
7
|
+
import { getProfile } from "../harnesses/index.js";
|
|
8
|
+
import { initContext, checkConflicts, configureMcpStep, installAgentsDefs, installCommandsDefs, configureMetricsStep, configureCliStep, runHealthCheck, configureShell, } from "./helpers.js";
|
|
9
|
+
export async function runSetup(opts) {
|
|
10
|
+
const version = await getVersion();
|
|
11
|
+
const profile = getProfile(opts.harness);
|
|
12
|
+
console.log();
|
|
13
|
+
console.log(` ${chalk.dim("⟨u⟩")} ${chalk.cyan.bold("ulu")}${chalk.bold("·ops")}`);
|
|
14
|
+
console.log(` ${chalk.dim("operating intelligence as infrastructure")}`);
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(` Setup v${version} — ${chalk.bold(profile.displayName)}`);
|
|
17
|
+
console.log();
|
|
18
|
+
if (opts.dryRun) {
|
|
19
|
+
info(chalk.dim("(dry run — no changes will be made)\n"));
|
|
20
|
+
}
|
|
21
|
+
const { env, apiKey } = await initContext(opts);
|
|
22
|
+
console.log();
|
|
23
|
+
// Load existing manifest for update detection
|
|
24
|
+
const existingManifest = await loadManifest();
|
|
25
|
+
const existingHarness = existingManifest?.harnesses[profile.name];
|
|
26
|
+
if (existingManifest && existingManifest.version !== version) {
|
|
27
|
+
info(`Updating ${chalk.dim(existingManifest.version)} → ${chalk.green(version)}`);
|
|
28
|
+
console.log();
|
|
29
|
+
}
|
|
30
|
+
else if (existingHarness) {
|
|
31
|
+
info(chalk.dim(`Already at v${version} — checking for changes`));
|
|
32
|
+
console.log();
|
|
33
|
+
}
|
|
34
|
+
// Check for conflicts on first install for this harness
|
|
35
|
+
if (!existingHarness && !opts.yes && !opts.dryRun) {
|
|
36
|
+
await checkConflicts(profile, opts.localDefs);
|
|
37
|
+
}
|
|
38
|
+
const mcpResult = await configureMcpStep(profile, apiKey, opts);
|
|
39
|
+
const agentsResult = await installAgentsDefs(profile, opts, existingHarness?.agents);
|
|
40
|
+
const commandsResult = await installCommandsDefs(profile, opts, existingHarness?.commands);
|
|
41
|
+
const metricsResult = await configureMetricsStep(profile, opts);
|
|
42
|
+
const cliResult = await configureCliStep({
|
|
43
|
+
withCli: opts.withCli,
|
|
44
|
+
cli: opts.cli,
|
|
45
|
+
yes: opts.yes,
|
|
46
|
+
apiKey: opts.apiKey,
|
|
47
|
+
dryRun: opts.dryRun,
|
|
48
|
+
});
|
|
49
|
+
await runHealthCheck(opts);
|
|
50
|
+
const shellModified = await configureShell(env, apiKey, opts);
|
|
51
|
+
// Save manifest
|
|
52
|
+
if (!opts.dryRun) {
|
|
53
|
+
const now = new Date().toISOString();
|
|
54
|
+
const harnessEntry = {
|
|
55
|
+
installedAt: now,
|
|
56
|
+
setupVersion: version,
|
|
57
|
+
mcpScope: opts.scope,
|
|
58
|
+
mcpConfigPath: mcpResult.configPath,
|
|
59
|
+
defsScope: opts.localDefs ? "local" : "global",
|
|
60
|
+
defsPath: opts.localDefs
|
|
61
|
+
? join(await findProjectRoot(), "uluops")
|
|
62
|
+
: profile.paths.home,
|
|
63
|
+
agents: agentsResult.files,
|
|
64
|
+
commands: commandsResult.files,
|
|
65
|
+
hooksInstalled: metricsResult.hookConfigured,
|
|
66
|
+
hooksInstalledVersion: metricsResult.hooksInstalledVersion,
|
|
67
|
+
};
|
|
68
|
+
const manifest = existingManifest ?? {
|
|
69
|
+
version,
|
|
70
|
+
installedAt: now,
|
|
71
|
+
shellModified: false,
|
|
72
|
+
harnesses: {},
|
|
73
|
+
};
|
|
74
|
+
manifest.version = version;
|
|
75
|
+
manifest.installedAt = now;
|
|
76
|
+
manifest.shellModified = shellModified || manifest.shellModified;
|
|
77
|
+
manifest.harnesses[profile.name] = harnessEntry;
|
|
78
|
+
// Only flip cliInstalled to true when WE installed it (not when user-installed).
|
|
79
|
+
// Once true, persist across re-runs so uninstall remains symmetric — until the
|
|
80
|
+
// user explicitly removes it with --no-cli + uninstall, this manifest owns it.
|
|
81
|
+
if (cliResult && cliResult.installed && !cliResult.alreadyPresent) {
|
|
82
|
+
manifest.cliInstalled = true;
|
|
83
|
+
manifest.cliInstalledVersion = cliResult.version;
|
|
84
|
+
}
|
|
85
|
+
await saveManifest(manifest);
|
|
86
|
+
}
|
|
87
|
+
await printSetupSummary({
|
|
88
|
+
profile,
|
|
89
|
+
agentCount: agentsResult.files.length,
|
|
90
|
+
commandCount: commandsResult.files.length,
|
|
91
|
+
apiKey,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { loadManifest, deleteManifest, validateManifest, } from "../lib/manifest.js";
|
|
3
|
+
import { uninstallMcp } from "../steps/mcp.js";
|
|
4
|
+
import { uninstallAgents } from "../steps/agents.js";
|
|
5
|
+
import { uninstallCommands } from "../steps/commands.js";
|
|
6
|
+
import { removeShellExport } from "../steps/shell.js";
|
|
7
|
+
import { uninstallMetrics } from "../steps/metrics.js";
|
|
8
|
+
import { uninstallCli, CLI_PACKAGE } from "../steps/cli.js";
|
|
9
|
+
import { ok, warn, fail, info } from "../lib/display.js";
|
|
10
|
+
import { getVersion } from "../lib/version.js";
|
|
11
|
+
import { getProfile } from "../harnesses/index.js";
|
|
12
|
+
export async function runUninstall(opts) {
|
|
13
|
+
const version = await getVersion();
|
|
14
|
+
console.log();
|
|
15
|
+
console.log(` ${chalk.dim("⟨u⟩")} ${chalk.cyan.bold("ulu")}${chalk.bold("·ops")} ${chalk.red("Uninstall")} v${version}`);
|
|
16
|
+
console.log();
|
|
17
|
+
if (opts.dryRun) {
|
|
18
|
+
info(chalk.dim("(dry run — no changes will be made)\n"));
|
|
19
|
+
}
|
|
20
|
+
const manifest = await loadManifest();
|
|
21
|
+
if (!manifest) {
|
|
22
|
+
warn("No manifest found — nothing to uninstall.");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const validation = await validateManifest(manifest);
|
|
26
|
+
if (!validation.valid) {
|
|
27
|
+
fail("Manifest references paths that no longer exist:");
|
|
28
|
+
for (const err of validation.errors)
|
|
29
|
+
info(` ${err}`);
|
|
30
|
+
console.log();
|
|
31
|
+
info("Uninstall may be incomplete. Proceeding with what's available.");
|
|
32
|
+
console.log();
|
|
33
|
+
}
|
|
34
|
+
if (validation.warnings.length > 0) {
|
|
35
|
+
for (const w of validation.warnings)
|
|
36
|
+
warn(w);
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
for (const [harnessName, hm] of Object.entries(manifest.harnesses)) {
|
|
40
|
+
let profile;
|
|
41
|
+
try {
|
|
42
|
+
profile = getProfile(harnessName);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
warn(`Unknown harness "${harnessName}" in manifest — skipping`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
info(chalk.bold(profile.displayName));
|
|
49
|
+
if (!opts.dryRun) {
|
|
50
|
+
const agentCount = await uninstallAgents(hm.agents, hm.defsPath);
|
|
51
|
+
ok(`Removed ${agentCount} agent(s)`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
ok(`Would remove ${hm.agents.length} agent(s)`);
|
|
55
|
+
}
|
|
56
|
+
if (hm.commands.length > 0) {
|
|
57
|
+
if (!opts.dryRun) {
|
|
58
|
+
const cmdCount = await uninstallCommands(hm.commands, hm.defsPath);
|
|
59
|
+
ok(`Removed ${cmdCount} command(s)`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
ok(`Would remove ${hm.commands.length} command(s)`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!opts.dryRun) {
|
|
66
|
+
try {
|
|
67
|
+
await uninstallMcp(profile, hm.mcpConfigPath);
|
|
68
|
+
ok(`Removed MCP servers from ${hm.mcpConfigPath}`);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
warn(`Could not remove MCP servers from ${hm.mcpConfigPath}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
ok(`Would remove MCP servers from ${hm.mcpConfigPath}`);
|
|
76
|
+
}
|
|
77
|
+
if (hm.hooksInstalled) {
|
|
78
|
+
if (!opts.dryRun) {
|
|
79
|
+
await uninstallMetrics(profile, false);
|
|
80
|
+
ok("Removed agent-metrics hook and tool files");
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
ok("Would remove agent-metrics hook and tool files");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
// Remove global @uluops/cli if WE installed it (per manifest).
|
|
89
|
+
// We never auto-remove a user-installed CLI — manifest.cliInstalled gates this.
|
|
90
|
+
if (manifest.cliInstalled) {
|
|
91
|
+
const res = await uninstallCli({ dryRun: opts.dryRun });
|
|
92
|
+
if (opts.dryRun) {
|
|
93
|
+
ok(`Would remove ${CLI_PACKAGE} (global)`);
|
|
94
|
+
}
|
|
95
|
+
else if (res.removed) {
|
|
96
|
+
ok(`Removed ${CLI_PACKAGE} (global)`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
warn(`Could not remove ${CLI_PACKAGE} (global) — try \`npm uninstall -g ${CLI_PACKAGE}\` manually`);
|
|
100
|
+
if (res.error) {
|
|
101
|
+
const oneLine = res.error.split("\n")[0]?.slice(0, 120) ?? "";
|
|
102
|
+
if (oneLine)
|
|
103
|
+
info(` ${oneLine}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Remove shell export
|
|
108
|
+
if (manifest.shellModified) {
|
|
109
|
+
const { getShellProfile } = await import("../lib/paths.js");
|
|
110
|
+
const shellProfile = getShellProfile();
|
|
111
|
+
if (shellProfile && !opts.dryRun) {
|
|
112
|
+
await removeShellExport(shellProfile.path);
|
|
113
|
+
ok(`Removed export from ${shellProfile.path}`);
|
|
114
|
+
}
|
|
115
|
+
else if (shellProfile) {
|
|
116
|
+
ok(`Would remove export from ${shellProfile.path}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!opts.dryRun) {
|
|
120
|
+
await deleteManifest();
|
|
121
|
+
ok("Manifest deleted");
|
|
122
|
+
}
|
|
123
|
+
console.log();
|
|
124
|
+
info("UluOps has been removed. Restart your harness to complete.");
|
|
125
|
+
console.log();
|
|
126
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runVerify(): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { verify } from "../steps/verify.js";
|
|
3
|
+
import { ok, fail, info } from "../lib/display.js";
|
|
4
|
+
import { getVersion } from "../lib/version.js";
|
|
5
|
+
export async function runVerify() {
|
|
6
|
+
const version = await getVersion();
|
|
7
|
+
console.log();
|
|
8
|
+
console.log(` ${chalk.dim("⟨u⟩")} ${chalk.cyan.bold("ulu")}${chalk.bold("·ops")} Installation Check v${version}`);
|
|
9
|
+
console.log();
|
|
10
|
+
const result = await verify();
|
|
11
|
+
for (const check of result.checks) {
|
|
12
|
+
if (check.passed) {
|
|
13
|
+
ok(check.label);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
fail(`${check.label}${check.detail ? ` — ${check.detail}` : ""}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
console.log();
|
|
20
|
+
if (result.ok) {
|
|
21
|
+
info(chalk.green("All checks passed."));
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
info(chalk.red("Some checks failed. Run npx @uluops/setup to fix."));
|
|
25
|
+
}
|
|
26
|
+
console.log();
|
|
27
|
+
process.exit(result.ok ? 0 : 1);
|
|
28
|
+
}
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* Wraps existing config-merger.ts and settings-merger.ts logic
|
|
5
5
|
* behind the HarnessProfile abstraction.
|
|
6
6
|
*/
|
|
7
|
-
import type
|
|
7
|
+
import { type HarnessProfile } from "./types.js";
|
|
8
8
|
export declare const claudeCodeProfile: HarnessProfile;
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* behind the HarnessProfile abstraction.
|
|
6
6
|
*/
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
+
import { ULUOPS_SERVERS, } from "./types.js";
|
|
8
9
|
import { readConfig, mergeUluopsMcp, removeUluopsMcp, writeConfig, } from "../lib/config-merger.js";
|
|
9
10
|
import { readSettings, writeSettings, mergeUluopsHook, removeUluopsHook, hasUluopsHook, } from "../lib/settings-merger.js";
|
|
10
11
|
import { getClaudeHome, getClaudeJsonPath } from "../lib/paths.js";
|
|
11
|
-
const ULUOPS_SERVERS = ["uluops-tracker", "uluops-registry"];
|
|
12
12
|
class ClaudeCodeMcpConfig {
|
|
13
13
|
async read(path) {
|
|
14
14
|
return readConfig(path);
|
|
@@ -34,6 +34,7 @@ class ClaudeCodeHooks {
|
|
|
34
34
|
if (dryRun)
|
|
35
35
|
return true;
|
|
36
36
|
const settings = await readSettings(settingsPath);
|
|
37
|
+
// Claude Code uses SubagentStop as the default event for auto-save
|
|
37
38
|
const merged = mergeUluopsHook(settings, hookCommand);
|
|
38
39
|
await writeSettings(settingsPath, merged);
|
|
39
40
|
return true;
|
|
@@ -54,6 +55,7 @@ const home = getClaudeHome();
|
|
|
54
55
|
export const claudeCodeProfile = {
|
|
55
56
|
name: "claude-code",
|
|
56
57
|
displayName: "Claude Code",
|
|
58
|
+
status: "stable",
|
|
57
59
|
homeDir: home,
|
|
58
60
|
agentFormat: "markdown",
|
|
59
61
|
factoryTarget: "claude-code",
|
package/dist/harnesses/codex.js
CHANGED
|
@@ -16,25 +16,26 @@ import { join } from "node:path";
|
|
|
16
16
|
import { HarnessNotTestedError } from "./types.js";
|
|
17
17
|
class CodexMcpConfig {
|
|
18
18
|
async read() {
|
|
19
|
-
throw new HarnessNotTestedError("Codex");
|
|
19
|
+
throw new HarnessNotTestedError("Codex (agent format compatibility under review)");
|
|
20
20
|
}
|
|
21
21
|
merge() {
|
|
22
|
-
throw new HarnessNotTestedError("Codex");
|
|
22
|
+
throw new HarnessNotTestedError("Codex (agent format compatibility under review)");
|
|
23
23
|
}
|
|
24
24
|
remove() {
|
|
25
|
-
throw new HarnessNotTestedError("Codex");
|
|
25
|
+
throw new HarnessNotTestedError("Codex (agent format compatibility under review)");
|
|
26
26
|
}
|
|
27
27
|
async write() {
|
|
28
|
-
throw new HarnessNotTestedError("Codex");
|
|
28
|
+
throw new HarnessNotTestedError("Codex (agent format compatibility under review)");
|
|
29
29
|
}
|
|
30
30
|
check() {
|
|
31
|
-
|
|
31
|
+
throw new HarnessNotTestedError("Codex (MCP config check not supported)");
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
const home = join(homedir(), ".codex");
|
|
35
35
|
export const codexProfile = {
|
|
36
36
|
name: "codex",
|
|
37
37
|
displayName: "Codex",
|
|
38
|
+
status: "experimental",
|
|
38
39
|
homeDir: home,
|
|
39
40
|
agentFormat: "toml",
|
|
40
41
|
factoryTarget: "codex",
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Gemini CLI Harness Profile
|
|
2
|
+
* Gemini CLI Harness Profile
|
|
3
3
|
*
|
|
4
4
|
* Paths and metadata are verified from vendor docs.
|
|
5
5
|
* MCP config uses `mcpServers` key (same shape as Claude Code)
|
|
6
6
|
* but at a different file path (~/.gemini/settings.json).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Note: Gemini CLI cannot have underscores in MCP server names
|
|
12
|
-
* (FQN format mcp_serverName_toolName uses underscore as delimiter).
|
|
13
|
-
* Our names use hyphens — safe.
|
|
8
|
+
* Gemini CLI requires `trust: true` in MCP server config to
|
|
9
|
+
* allow automatic tool execution without confirmation prompts.
|
|
14
10
|
*/
|
|
15
|
-
import type
|
|
11
|
+
import { type HarnessProfile } from "./types.js";
|
|
16
12
|
export declare const geminiCliProfile: HarnessProfile;
|