ultracode-ai 1.3.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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/dist/commands/authoring-agents.d.ts +19 -0
  4. package/dist/commands/authoring-agents.d.ts.map +1 -0
  5. package/dist/commands/authoring-agents.js +123 -0
  6. package/dist/commands/authoring-agents.js.map +1 -0
  7. package/dist/commands/budget.d.ts +16 -0
  8. package/dist/commands/budget.d.ts.map +1 -0
  9. package/dist/commands/budget.js +105 -0
  10. package/dist/commands/budget.js.map +1 -0
  11. package/dist/commands/config.d.ts +15 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +147 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +65 -0
  16. package/dist/commands/doctor.d.ts.map +1 -0
  17. package/dist/commands/doctor.js +188 -0
  18. package/dist/commands/doctor.js.map +1 -0
  19. package/dist/commands/ext-format.d.ts +22 -0
  20. package/dist/commands/ext-format.d.ts.map +1 -0
  21. package/dist/commands/ext-format.js +115 -0
  22. package/dist/commands/ext-format.js.map +1 -0
  23. package/dist/commands/ext-helpers.d.ts +25 -0
  24. package/dist/commands/ext-helpers.d.ts.map +1 -0
  25. package/dist/commands/ext-helpers.js +36 -0
  26. package/dist/commands/ext-helpers.js.map +1 -0
  27. package/dist/commands/learn.d.ts +29 -0
  28. package/dist/commands/learn.d.ts.map +1 -0
  29. package/dist/commands/learn.js +190 -0
  30. package/dist/commands/learn.js.map +1 -0
  31. package/dist/commands/list.d.ts +11 -0
  32. package/dist/commands/list.d.ts.map +1 -0
  33. package/dist/commands/list.js +58 -0
  34. package/dist/commands/list.js.map +1 -0
  35. package/dist/commands/run.d.ts +13 -0
  36. package/dist/commands/run.d.ts.map +1 -0
  37. package/dist/commands/run.js +46 -0
  38. package/dist/commands/run.js.map +1 -0
  39. package/dist/commands/setup.d.ts +40 -0
  40. package/dist/commands/setup.d.ts.map +1 -0
  41. package/dist/commands/setup.js +146 -0
  42. package/dist/commands/setup.js.map +1 -0
  43. package/dist/commands/skills.d.ts +16 -0
  44. package/dist/commands/skills.d.ts.map +1 -0
  45. package/dist/commands/skills.js +148 -0
  46. package/dist/commands/skills.js.map +1 -0
  47. package/dist/commands/versioning.d.ts +13 -0
  48. package/dist/commands/versioning.d.ts.map +1 -0
  49. package/dist/commands/versioning.js +63 -0
  50. package/dist/commands/versioning.js.map +1 -0
  51. package/dist/context.d.ts +60 -0
  52. package/dist/context.d.ts.map +1 -0
  53. package/dist/context.js +69 -0
  54. package/dist/context.js.map +1 -0
  55. package/dist/core-loader.d.ts +22 -0
  56. package/dist/core-loader.d.ts.map +1 -0
  57. package/dist/core-loader.js +22 -0
  58. package/dist/core-loader.js.map +1 -0
  59. package/dist/format.d.ts +15 -0
  60. package/dist/format.d.ts.map +1 -0
  61. package/dist/format.js +80 -0
  62. package/dist/format.js.map +1 -0
  63. package/dist/index.d.ts +22 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +59 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/program.d.ts +19 -0
  68. package/dist/program.d.ts.map +1 -0
  69. package/dist/program.js +120 -0
  70. package/dist/program.js.map +1 -0
  71. package/dist/themes/dark.d.ts +4 -0
  72. package/dist/themes/dark.d.ts.map +1 -0
  73. package/dist/themes/dark.js +16 -0
  74. package/dist/themes/dark.js.map +1 -0
  75. package/dist/themes/dracula.d.ts +4 -0
  76. package/dist/themes/dracula.d.ts.map +1 -0
  77. package/dist/themes/dracula.js +16 -0
  78. package/dist/themes/dracula.js.map +1 -0
  79. package/dist/themes/index.d.ts +32 -0
  80. package/dist/themes/index.d.ts.map +1 -0
  81. package/dist/themes/index.js +45 -0
  82. package/dist/themes/index.js.map +1 -0
  83. package/dist/themes/light.d.ts +4 -0
  84. package/dist/themes/light.d.ts.map +1 -0
  85. package/dist/themes/light.js +16 -0
  86. package/dist/themes/light.js.map +1 -0
  87. package/dist/themes/theme.d.ts +34 -0
  88. package/dist/themes/theme.d.ts.map +1 -0
  89. package/dist/themes/theme.js +2 -0
  90. package/dist/themes/theme.js.map +1 -0
  91. package/dist/ui/App.d.ts +24 -0
  92. package/dist/ui/App.d.ts.map +1 -0
  93. package/dist/ui/App.js +217 -0
  94. package/dist/ui/App.js.map +1 -0
  95. package/dist/ui/ChatInput.d.ts +21 -0
  96. package/dist/ui/ChatInput.d.ts.map +1 -0
  97. package/dist/ui/ChatInput.js +88 -0
  98. package/dist/ui/ChatInput.js.map +1 -0
  99. package/dist/ui/ChatOutput.d.ts +22 -0
  100. package/dist/ui/ChatOutput.d.ts.map +1 -0
  101. package/dist/ui/ChatOutput.js +27 -0
  102. package/dist/ui/ChatOutput.js.map +1 -0
  103. package/dist/ui/StatusBar.d.ts +22 -0
  104. package/dist/ui/StatusBar.d.ts.map +1 -0
  105. package/dist/ui/StatusBar.js +17 -0
  106. package/dist/ui/StatusBar.js.map +1 -0
  107. package/dist/ui/ToolOutput.d.ts +20 -0
  108. package/dist/ui/ToolOutput.d.ts.map +1 -0
  109. package/dist/ui/ToolOutput.js +14 -0
  110. package/dist/ui/ToolOutput.js.map +1 -0
  111. package/dist/ui/ctrl-c.d.ts +21 -0
  112. package/dist/ui/ctrl-c.d.ts.map +1 -0
  113. package/dist/ui/ctrl-c.js +27 -0
  114. package/dist/ui/ctrl-c.js.map +1 -0
  115. package/dist/ui/start.d.ts +13 -0
  116. package/dist/ui/start.d.ts.map +1 -0
  117. package/dist/ui/start.js +25 -0
  118. package/dist/ui/start.js.map +1 -0
  119. package/dist/utils/cli-version.d.ts +15 -0
  120. package/dist/utils/cli-version.d.ts.map +1 -0
  121. package/dist/utils/cli-version.js +33 -0
  122. package/dist/utils/cli-version.js.map +1 -0
  123. package/dist/utils/resolve-home.d.ts +19 -0
  124. package/dist/utils/resolve-home.d.ts.map +1 -0
  125. package/dist/utils/resolve-home.js +28 -0
  126. package/dist/utils/resolve-home.js.map +1 -0
  127. package/dist/utils/text.d.ts +50 -0
  128. package/dist/utils/text.d.ts.map +1 -0
  129. package/dist/utils/text.js +133 -0
  130. package/dist/utils/text.js.map +1 -0
  131. package/package.json +45 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UltraCode Team / SIMO GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # ultracode-ai
2
+
3
+ > Interactive AI code assistant for the terminal — with AI-powered versioning and release planning.
4
+
5
+ Part of the [UltraCode AI](https://github.com/AndreasSchwan-SIMO/UltraCode) monorepo.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g ultracode-ai
11
+ # or run ad hoc
12
+ npx ultracode-ai
13
+ ```
14
+
15
+ Requires Node.js `>=22.13.0`.
16
+
17
+ ## Usage
18
+
19
+ ```bash
20
+ ultracode-ai # start the interactive assistant
21
+ ultracode-ai --help # list commands and flags
22
+ ```
23
+
24
+ The CLI bundles the agentic coding assistant (multiple LLM providers, a sandboxed
25
+ tool layer, persistent sessions) together with the UltraCode AI versioning subsystem:
26
+ it derives a SemVer bump from your Git diffs and commits, drafts a changelog and
27
+ checks the configured release quality gates.
28
+
29
+ ## Packages
30
+
31
+ - [`ultracode-core`](https://www.npmjs.com/package/ultracode-core) — agents, tools, memory, context, providers, config and AI versioning.
32
+ - [`ultracode-shared`](https://www.npmjs.com/package/ultracode-shared) — shared types, contracts, errors and utilities.
33
+
34
+ ## License
35
+
36
+ [MIT](./LICENSE) © UltraCode AI Team / SIMO GmbH
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `ultracode agents create|evolve|test`
3
+ *
4
+ * Agent authoring commands backed by the facade's `authoring` sub-API
5
+ * (Module B). These extend the existing `agents list` group (registered by
6
+ * `./list.ts`) with proposal-generating subcommands. Generated agents never
7
+ * escalate tool permissions; `persist` is gated behind `--yes`.
8
+ *
9
+ * Material is supplied via `--file <material.json>` or inline
10
+ * `--topic`/`--catalog` flags (same convention as `skills create`).
11
+ */
12
+ import type { Command } from "commander";
13
+ import type { CliContext } from "../context.js";
14
+ /**
15
+ * Register agent-authoring subcommands. Must be called AFTER
16
+ * `registerListCommands` so it attaches to the existing `agents` group.
17
+ */
18
+ export declare function registerAuthoringAgentCommands(program: Command, ctx: CliContext): void;
19
+ //# sourceMappingURL=authoring-agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring-agents.d.ts","sourceRoot":"","sources":["../../src/commands/authoring-agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAqGhD;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAqCtF"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * `ultracode agents create|evolve|test`
3
+ *
4
+ * Agent authoring commands backed by the facade's `authoring` sub-API
5
+ * (Module B). These extend the existing `agents list` group (registered by
6
+ * `./list.ts`) with proposal-generating subcommands. Generated agents never
7
+ * escalate tool permissions; `persist` is gated behind `--yes`.
8
+ *
9
+ * Material is supplied via `--file <material.json>` or inline
10
+ * `--topic`/`--catalog` flags (same convention as `skills create`).
11
+ */
12
+ import path from "node:path";
13
+ import process from "node:process";
14
+ import { promises as fs } from "node:fs";
15
+ import { ValidationError } from "ultracode-shared";
16
+ import { authoringOf, withExtFacade } from "./ext-helpers.js";
17
+ import { formatBlock, formatTestResult } from "./ext-format.js";
18
+ async function loadMaterial(ctx, opts) {
19
+ if (opts.file !== undefined) {
20
+ const target = path.resolve(ctx.cwd, opts.file);
21
+ let raw;
22
+ try {
23
+ raw = await fs.readFile(target, "utf8");
24
+ }
25
+ catch (cause) {
26
+ throw new ValidationError(`Cannot read material file: ${target}`, { cause });
27
+ }
28
+ let parsed;
29
+ try {
30
+ parsed = JSON.parse(raw.replace(/^/, ""));
31
+ }
32
+ catch (cause) {
33
+ throw new ValidationError(`Invalid JSON in material file: ${target}`, { cause });
34
+ }
35
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
36
+ throw new ValidationError(`Material file must contain a JSON object: ${target}`);
37
+ }
38
+ return parsed;
39
+ }
40
+ if (opts.topic === undefined || opts.catalog === undefined) {
41
+ throw new ValidationError("Provide --file <material.json>, or both --topic and --catalog to create agent material inline.");
42
+ }
43
+ return {
44
+ catalog: opts.catalog,
45
+ topic: opts.topic,
46
+ summary: opts.summary ?? "",
47
+ facts: [],
48
+ codeSnippets: [],
49
+ sources: [],
50
+ };
51
+ }
52
+ function writeProposal(ctx, proposal, json) {
53
+ if (json) {
54
+ ctx.stdout.write(`${JSON.stringify(proposal)}\n`);
55
+ return;
56
+ }
57
+ ctx.stdout.write(`Proposal (${proposal.kind}): ${proposal.name}\n`);
58
+ ctx.stdout.write(formatBlock("Rationale", proposal.rationale));
59
+ if (proposal.diffFromExisting !== undefined) {
60
+ ctx.stdout.write(formatBlock("Diff", proposal.diffFromExisting));
61
+ }
62
+ }
63
+ /** Resolve the create/evolve method, failing clearly when core lacks it. */
64
+ function agentMethod(authoring, which) {
65
+ const fn = which === "create" ? authoring.createAgent : authoring.evolveAgent;
66
+ if (typeof fn !== "function") {
67
+ throw new ValidationError(`Agent ${which} is not available in this build of ultracode-core.`);
68
+ }
69
+ return fn.bind(authoring);
70
+ }
71
+ async function proposeAgent(ctx, which, opts) {
72
+ await withExtFacade(ctx, async (facade) => {
73
+ const authoring = authoringOf(facade);
74
+ const material = await loadMaterial(ctx, opts);
75
+ const proposal = await agentMethod(authoring, which)(material);
76
+ writeProposal(ctx, proposal, opts.json === true);
77
+ if (opts.yes === true) {
78
+ await authoring.persist(proposal, { approved: true });
79
+ if (opts.json !== true)
80
+ ctx.stdout.write(`✓ agent "${proposal.name}" persisted\n`);
81
+ }
82
+ else if (opts.json !== true) {
83
+ ctx.stdout.write("Run again with --yes to persist this agent.\n");
84
+ }
85
+ });
86
+ }
87
+ const materialOptions = (cmd) => cmd
88
+ .option("--file <path>", "knowledge material JSON file")
89
+ .option("--topic <topic>", "agent topic (inline material)")
90
+ .option("--catalog <catalog>", "agent catalog (inline material)")
91
+ .option("--summary <text>", "agent summary (inline material)");
92
+ /**
93
+ * Register agent-authoring subcommands. Must be called AFTER
94
+ * `registerListCommands` so it attaches to the existing `agents` group.
95
+ */
96
+ export function registerAuthoringAgentCommands(program, ctx) {
97
+ const agents = program.commands.find((c) => c.name() === "agents") ??
98
+ program.command("agents").description("inspect and author agents");
99
+ materialOptions(agents
100
+ .command("create")
101
+ .description("create a new agent from knowledge material (proposal only unless --yes)"))
102
+ .option("--yes", "persist the proposal instead of only printing it")
103
+ .option("--json", "output as JSON")
104
+ .action(async (opts) => proposeAgent(ctx, "create", opts));
105
+ materialOptions(agents
106
+ .command("evolve")
107
+ .description("evolve an existing agent from new material (proposal only unless --yes)"))
108
+ .option("--yes", "persist the proposal instead of only printing it")
109
+ .option("--json", "output as JSON")
110
+ .action(async (opts) => proposeAgent(ctx, "evolve", opts));
111
+ materialOptions(agents.command("test").description("test an agent proposal built from material, without persisting"))
112
+ .option("--json", "output as JSON")
113
+ .action(async (opts) => withExtFacade(ctx, async (facade) => {
114
+ const authoring = authoringOf(facade);
115
+ const material = await loadMaterial(ctx, opts);
116
+ const proposal = await agentMethod(authoring, "create")(material);
117
+ const result = await authoring.test(proposal);
118
+ ctx.stdout.write(opts.json ? `${JSON.stringify(result)}\n` : formatTestResult(result));
119
+ if (!result.passed)
120
+ process.exitCode = 1;
121
+ }));
122
+ }
123
+ //# sourceMappingURL=authoring-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring-agents.js","sourceRoot":"","sources":["../../src/commands/authoring-agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `ultracode budget plan|show|set|status|history`
3
+ *
4
+ * Cost-control commands backed by the facade's `budget` sub-API (Module A).
5
+ * - `budget show` / `budget status` print the current spend snapshot.
6
+ * - `budget plan` installs/reads a plan (interactive answers via `--cap`/`--threshold`).
7
+ * - `budget set <file>` loads a plan from a JSON file.
8
+ * - `budget history [--limit n]` prints the ledger.
9
+ *
10
+ * Every subcommand supports `--json` for machine-readable output.
11
+ */
12
+ import type { Command } from "commander";
13
+ import type { CliContext } from "../context.js";
14
+ /** Register the `budget` command group on `program`. */
15
+ export declare function registerBudgetCommands(program: Command, ctx: CliContext): void;
16
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/commands/budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAyBhD,wDAAwD;AACxD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CA0F9E"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * `ultracode budget plan|show|set|status|history`
3
+ *
4
+ * Cost-control commands backed by the facade's `budget` sub-API (Module A).
5
+ * - `budget show` / `budget status` print the current spend snapshot.
6
+ * - `budget plan` installs/reads a plan (interactive answers via `--cap`/`--threshold`).
7
+ * - `budget set <file>` loads a plan from a JSON file.
8
+ * - `budget history [--limit n]` prints the ledger.
9
+ *
10
+ * Every subcommand supports `--json` for machine-readable output.
11
+ */
12
+ import path from "node:path";
13
+ import { promises as fs } from "node:fs";
14
+ import { ValidationError } from "ultracode-shared";
15
+ import { budgetOf, withExtFacade } from "./ext-helpers.js";
16
+ import { formatBudgetStatus, formatLedger } from "./ext-format.js";
17
+ /** Parse a numeric CLI option, throwing {@link ValidationError} when invalid. */
18
+ function parseNumber(raw, label) {
19
+ const n = Number(raw);
20
+ if (!Number.isFinite(n))
21
+ throw new ValidationError(`${label} must be a finite number, got "${raw}"`);
22
+ return n;
23
+ }
24
+ /** Register the `budget` command group on `program`. */
25
+ export function registerBudgetCommands(program, ctx) {
26
+ const budget = program.command("budget").description("cost control: plan, status and spend history");
27
+ const showAction = async (opts) => withExtFacade(ctx, async (facade) => {
28
+ const status = await budgetOf(facade).status();
29
+ ctx.stdout.write(opts.json ? `${JSON.stringify(status)}\n` : formatBudgetStatus(status));
30
+ });
31
+ budget
32
+ .command("show")
33
+ .description("print the current budget status (spend, cap, remaining)")
34
+ .option("--json", "output as JSON")
35
+ .action(showAction);
36
+ budget
37
+ .command("status")
38
+ .description("alias of `budget show`")
39
+ .option("--json", "output as JSON")
40
+ .action(showAction);
41
+ budget
42
+ .command("plan")
43
+ .description("install or read the budget plan (caps / approval threshold)")
44
+ .option("--cap <usd>", "monthly USD cap (omit for no cap)")
45
+ .option("--threshold <usd>", "USD value above which a run requires approval")
46
+ .option("--json", "output as JSON")
47
+ .action(async (opts) => withExtFacade(ctx, async (facade) => {
48
+ const answers = {};
49
+ if (opts.cap !== undefined)
50
+ answers["capUsd"] = parseNumber(opts.cap, "--cap");
51
+ if (opts.threshold !== undefined) {
52
+ answers["approvalThresholdUsd"] = parseNumber(opts.threshold, "--threshold");
53
+ }
54
+ const plan = await budgetOf(facade).plan(Object.keys(answers).length > 0 ? answers : undefined);
55
+ if (Object.keys(answers).length > 0) {
56
+ await budgetOf(facade).setPlan(plan);
57
+ }
58
+ if (opts.json) {
59
+ ctx.stdout.write(`${JSON.stringify(plan)}\n`);
60
+ }
61
+ else {
62
+ ctx.stdout.write(`Budget Plan\n Cap: ${plan.capUsd === null ? "(none)" : `$${plan.capUsd}`}\n`);
63
+ if (plan.approvalThresholdUsd !== undefined) {
64
+ ctx.stdout.write(` Approval threshold: $${plan.approvalThresholdUsd}\n`);
65
+ }
66
+ }
67
+ }));
68
+ budget
69
+ .command("set")
70
+ .description("load and persist a budget plan from a JSON file")
71
+ .argument("<file>", "JSON file describing a BudgetPlan")
72
+ .action(async (file) => withExtFacade(ctx, async (facade) => {
73
+ const target = path.resolve(ctx.cwd, file);
74
+ let raw;
75
+ try {
76
+ raw = await fs.readFile(target, "utf8");
77
+ }
78
+ catch (cause) {
79
+ throw new ValidationError(`Cannot read budget plan file: ${target}`, { cause });
80
+ }
81
+ let parsed;
82
+ try {
83
+ parsed = JSON.parse(raw.replace(/^/, ""));
84
+ }
85
+ catch (cause) {
86
+ throw new ValidationError(`Invalid JSON in budget plan file: ${target}`, { cause });
87
+ }
88
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
89
+ throw new ValidationError(`Budget plan file must contain a JSON object: ${target}`);
90
+ }
91
+ await budgetOf(facade).setPlan(parsed);
92
+ ctx.stdout.write(`✓ budget plan loaded from ${target}\n`);
93
+ }));
94
+ budget
95
+ .command("history")
96
+ .description("print the spend ledger (estimated vs. actual)")
97
+ .option("--limit <n>", "maximum number of entries to show")
98
+ .option("--json", "output as JSON")
99
+ .action(async (opts) => withExtFacade(ctx, async (facade) => {
100
+ const limit = opts.limit !== undefined ? parseNumber(opts.limit, "--limit") : undefined;
101
+ const entries = await budgetOf(facade).history(limit);
102
+ ctx.stdout.write(opts.json ? `${JSON.stringify(entries)}\n` : formatLedger(entries));
103
+ }));
104
+ }
105
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/commands/budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `ultracode config show|get|set|validate|export|import`
3
+ *
4
+ * Configuration inspection and modification through the UltraCode facade.
5
+ * Mutating subcommands (`set`, `import`) require the optional `configManager`
6
+ * exposed by the facade (ConfigManager semantics: `set(path, value)` +
7
+ * `save("user")`); without it they fail with a clear {@link ConfigError}.
8
+ * `show` prefers core's redacted view and falls back to a local key-masking
9
+ * redaction so secrets are never printed.
10
+ */
11
+ import type { Command } from "commander";
12
+ import type { CliContext } from "../context.js";
13
+ /** Register the `config` command group on `program`. */
14
+ export declare function registerConfigCommand(program: Command, ctx: CliContext): void;
15
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,eAAe,CAAC;AAsCjE,wDAAwD;AACxD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAwH7E"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * `ultracode config show|get|set|validate|export|import`
3
+ *
4
+ * Configuration inspection and modification through the UltraCode facade.
5
+ * Mutating subcommands (`set`, `import`) require the optional `configManager`
6
+ * exposed by the facade (ConfigManager semantics: `set(path, value)` +
7
+ * `save("user")`); without it they fail with a clear {@link ConfigError}.
8
+ * `show` prefers core's redacted view and falls back to a local key-masking
9
+ * redaction so secrets are never printed.
10
+ */
11
+ import path from "node:path";
12
+ import { promises as fs } from "node:fs";
13
+ import { ConfigError, isPlainObject } from "ultracode-shared";
14
+ import { safeDispose } from "../context.js";
15
+ import { flattenLeaves, getAtPath, parseCliValue, redactConfig } from "../utils/text.js";
16
+ /** Run `fn` against a fresh facade, always disposing it afterwards. */
17
+ async function withFacade(ctx, fn) {
18
+ const facade = await ctx.createFacade({ cwd: ctx.cwd });
19
+ try {
20
+ return await fn(facade);
21
+ }
22
+ finally {
23
+ await safeDispose(facade);
24
+ }
25
+ }
26
+ function requireManager(facade) {
27
+ const manager = facade.configManager;
28
+ if (!manager || typeof manager.set !== "function" || typeof manager.save !== "function") {
29
+ throw new ConfigError("Modifying configuration requires the ConfigManager, which this build of ultracode-core does not expose. " +
30
+ "Edit ~/.ultracode/config.toml manually instead.");
31
+ }
32
+ return manager;
33
+ }
34
+ function redactedView(facade) {
35
+ const manager = facade.configManager;
36
+ if (manager && typeof manager.redacted === "function")
37
+ return manager.redacted();
38
+ return redactConfig(facade.config);
39
+ }
40
+ /** Register the `config` command group on `program`. */
41
+ export function registerConfigCommand(program, ctx) {
42
+ const config = program.command("config").description("inspect and modify the configuration");
43
+ config
44
+ .command("show")
45
+ .description("print the resolved configuration (secrets masked)")
46
+ .option("--json", "output as JSON")
47
+ .action(async (opts) => withFacade(ctx, async (facade) => {
48
+ const view = redactedView(facade);
49
+ if (opts.json) {
50
+ ctx.stdout.write(`${JSON.stringify(view)}\n`);
51
+ return;
52
+ }
53
+ const flat = isPlainObject(view)
54
+ ? flattenLeaves(view)
55
+ : [["config", view]];
56
+ for (const [key, value] of flat) {
57
+ ctx.stdout.write(`${key} = ${JSON.stringify(value)}\n`);
58
+ }
59
+ }));
60
+ config
61
+ .command("get")
62
+ .description("print a single configuration value by dotted path")
63
+ .argument("<path>", 'dotted config path, e.g. "core.activeModel"')
64
+ .option("--json", "output as JSON ({ path, value })")
65
+ .action(async (dotted, opts) => withFacade(ctx, async (facade) => {
66
+ const manager = facade.configManager;
67
+ const value = manager && typeof manager.get === "function"
68
+ ? manager.get(dotted)
69
+ : getAtPath(facade.config, dotted);
70
+ if (value === undefined) {
71
+ throw new ConfigError(`Unknown config path: "${dotted}"`);
72
+ }
73
+ if (opts.json) {
74
+ ctx.stdout.write(`${JSON.stringify({ path: dotted, value })}\n`);
75
+ }
76
+ else {
77
+ ctx.stdout.write(`${typeof value === "string" ? value : JSON.stringify(value)}\n`);
78
+ }
79
+ }));
80
+ config
81
+ .command("set")
82
+ .description("set a configuration value and persist it to the user layer")
83
+ .argument("<path>", 'dotted config path, e.g. "ui.theme"')
84
+ .argument("<value>", "new value (JSON literals are parsed, otherwise string)")
85
+ .action(async (dotted, raw) => withFacade(ctx, async (facade) => {
86
+ const manager = requireManager(facade);
87
+ const value = parseCliValue(raw);
88
+ manager.set(dotted, value);
89
+ await manager.save("user");
90
+ ctx.stdout.write(`✓ ${dotted} = ${JSON.stringify(value)} (saved to user config)\n`);
91
+ }));
92
+ config
93
+ .command("validate")
94
+ .description("validate the resolved configuration")
95
+ .action(async () => withFacade(ctx, async (facade) => {
96
+ const manager = facade.configManager;
97
+ if (manager && typeof manager.validate === "function")
98
+ manager.validate();
99
+ ctx.stdout.write("✓ configuration is valid\n");
100
+ }));
101
+ config
102
+ .command("export")
103
+ .description("export the resolved configuration as JSON (stdout or file)")
104
+ .argument("[file]", "target file; prints to stdout when omitted")
105
+ .action(async (file) => withFacade(ctx, async (facade) => {
106
+ const json = JSON.stringify(facade.config, null, 2);
107
+ if (file === undefined) {
108
+ ctx.stdout.write(`${json}\n`);
109
+ return;
110
+ }
111
+ const target = path.resolve(ctx.cwd, file);
112
+ await fs.writeFile(target, `${json}\n`, "utf8");
113
+ ctx.stdout.write(`✓ configuration exported to ${target}\n`);
114
+ }));
115
+ config
116
+ .command("import")
117
+ .description("import configuration overrides from a JSON file into the user layer")
118
+ .argument("<file>", "JSON file produced by `config export` (or compatible)")
119
+ .action(async (file) => withFacade(ctx, async (facade) => {
120
+ const manager = requireManager(facade);
121
+ const target = path.resolve(ctx.cwd, file);
122
+ let raw;
123
+ try {
124
+ raw = await fs.readFile(target, "utf8");
125
+ }
126
+ catch (cause) {
127
+ throw new ConfigError(`Cannot read config file: ${target}`, { cause });
128
+ }
129
+ let parsed;
130
+ try {
131
+ parsed = JSON.parse(raw.replace(/^\uFEFF/, ""));
132
+ }
133
+ catch (cause) {
134
+ throw new ConfigError(`Invalid JSON in config file: ${target}`, { cause });
135
+ }
136
+ if (!isPlainObject(parsed)) {
137
+ throw new ConfigError(`Config file must contain a JSON object: ${target}`);
138
+ }
139
+ const leaves = flattenLeaves(parsed);
140
+ for (const [key, value] of leaves) {
141
+ manager.set(key, value);
142
+ }
143
+ await manager.save("user");
144
+ ctx.stdout.write(`✓ imported ${leaves.length} value(s) from ${target} (saved to user config)\n`);
145
+ }));
146
+ }
147
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `ultracode doctor [--json]`
3
+ *
4
+ * Fully offline environment check: Node version, git availability, config
5
+ * directory writability, config validity, API-key presence (masked — the key
6
+ * value is never printed) and terminal capabilities. Critical failures set
7
+ * exit code 1.
8
+ */
9
+ import type { Command } from "commander";
10
+ import type { CliContext } from "../context.js";
11
+ /** Result of a single doctor check. */
12
+ export interface DoctorCheck {
13
+ /** Stable check identifier. */
14
+ name: string;
15
+ /** Whether the check passed. */
16
+ ok: boolean;
17
+ /** Whether a failure of this check is fatal (drives the exit code). */
18
+ critical: boolean;
19
+ /** Human-readable detail (secrets always masked). */
20
+ detail: string;
21
+ }
22
+ /** Aggregated doctor report. `ok` is false iff a *critical* check failed. */
23
+ export interface DoctorReport {
24
+ ok: boolean;
25
+ checks: DoctorCheck[];
26
+ }
27
+ /** Injectable dependencies for {@link collectDoctorReport} (offline by design). */
28
+ export interface DoctorDeps {
29
+ /** Node.js version string, e.g. `"20.11.1"`. */
30
+ nodeVersion: string;
31
+ /** Environment snapshot for API-key/colour checks. */
32
+ env: NodeJS.ProcessEnv;
33
+ /** Whether stdout is an interactive terminal. */
34
+ isTTY: boolean;
35
+ /** Resolve `git --version`, `null` when git is missing. */
36
+ gitVersion(): Promise<string | null>;
37
+ /** Resolved user config directory. */
38
+ configDir: string;
39
+ /** Probe write access; resolves `true` or an error description. */
40
+ checkWritable(dir: string): Promise<true | string>;
41
+ /** Load + validate the configuration (throws on failure). */
42
+ loadConfig(): Promise<void>;
43
+ }
44
+ /** Environment variables checked for API-key presence. */
45
+ export declare const API_KEY_VARS: readonly ["MISTRAL_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY", "ULTRACODE_API_KEY"];
46
+ /** Minimum supported Node.js major version. */
47
+ export declare const MIN_NODE_MAJOR = 22;
48
+ /**
49
+ * Minimum supported Node.js minor version *within* {@link MIN_NODE_MAJOR}.
50
+ * A newer major satisfies the requirement regardless of its minor; only the
51
+ * boundary major is gated on this minor. Mirrors the `engines.node`
52
+ * (`>=22.13.0`) declared by every workspace package.
53
+ */
54
+ export declare const MIN_NODE_MINOR = 13;
55
+ /** Default writability probe: mkdir -p, then create + delete a marker file. */
56
+ export declare function defaultCheckWritable(dir: string): Promise<true | string>;
57
+ /** Build the production {@link DoctorDeps} from a {@link CliContext}. */
58
+ export declare function makeDefaultDoctorDeps(ctx: CliContext): DoctorDeps;
59
+ /** Run all doctor checks. Never throws — failures become `ok: false` checks. */
60
+ export declare function collectDoctorReport(deps: DoctorDeps): Promise<DoctorReport>;
61
+ /** Render a {@link DoctorReport} as a ✓/✗ checklist. */
62
+ export declare function renderDoctorReport(report: DoctorReport): string;
63
+ /** Register the `doctor` command on `program`. */
64
+ export declare function registerDoctorCommand(program: Command, ctx: CliContext): void;
65
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKhD,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,mFAAmF;AACnF,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,iDAAiD;IACjD,KAAK,EAAE,OAAO,CAAC;IACf,2DAA2D;IAC3D,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACrC,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACnD,6DAA6D;IAC7D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,0DAA0D;AAC1D,eAAO,MAAM,YAAY,0FAKf,CAAC;AAEX,+CAA+C;AAC/C,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,+EAA+E;AAC/E,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAU9E;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAajE;AAED,gFAAgF;AAChF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAuGjF;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAO/D;AAED,kDAAkD;AAClD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAc7E"}