localptp 0.1.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 (186) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +159 -0
  3. package/dist/cli.d.ts +24 -0
  4. package/dist/cli.js +344 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/config.d.ts +14 -0
  7. package/dist/commands/config.js +65 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/context.d.ts +12 -0
  10. package/dist/commands/context.js +176 -0
  11. package/dist/commands/context.js.map +1 -0
  12. package/dist/commands/doctor.d.ts +16 -0
  13. package/dist/commands/doctor.js +54 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/index.d.ts +13 -0
  16. package/dist/commands/index.js +70 -0
  17. package/dist/commands/index.js.map +1 -0
  18. package/dist/commands/init.d.ts +15 -0
  19. package/dist/commands/init.js +46 -0
  20. package/dist/commands/init.js.map +1 -0
  21. package/dist/commands/plan.d.ts +17 -0
  22. package/dist/commands/plan.js +170 -0
  23. package/dist/commands/plan.js.map +1 -0
  24. package/dist/commands/resume.d.ts +17 -0
  25. package/dist/commands/resume.js +75 -0
  26. package/dist/commands/resume.js.map +1 -0
  27. package/dist/commands/review.d.ts +17 -0
  28. package/dist/commands/review.js +67 -0
  29. package/dist/commands/review.js.map +1 -0
  30. package/dist/commands/run.d.ts +24 -0
  31. package/dist/commands/run.js +65 -0
  32. package/dist/commands/run.js.map +1 -0
  33. package/dist/commands/step.d.ts +44 -0
  34. package/dist/commands/step.js +50 -0
  35. package/dist/commands/step.js.map +1 -0
  36. package/dist/commands/summarize.d.ts +17 -0
  37. package/dist/commands/summarize.js +276 -0
  38. package/dist/commands/summarize.js.map +1 -0
  39. package/dist/commands/task.d.ts +13 -0
  40. package/dist/commands/task.js +53 -0
  41. package/dist/commands/task.js.map +1 -0
  42. package/dist/core/activePointer.d.ts +28 -0
  43. package/dist/core/activePointer.js +84 -0
  44. package/dist/core/activePointer.js.map +1 -0
  45. package/dist/core/approval.d.ts +12 -0
  46. package/dist/core/approval.js +34 -0
  47. package/dist/core/approval.js.map +1 -0
  48. package/dist/core/configManager.d.ts +32 -0
  49. package/dist/core/configManager.js +177 -0
  50. package/dist/core/configManager.js.map +1 -0
  51. package/dist/core/contextBuilder.d.ts +40 -0
  52. package/dist/core/contextBuilder.js +406 -0
  53. package/dist/core/contextBuilder.js.map +1 -0
  54. package/dist/core/memoryLoader.d.ts +4 -0
  55. package/dist/core/memoryLoader.js +35 -0
  56. package/dist/core/memoryLoader.js.map +1 -0
  57. package/dist/core/memoryManager.d.ts +41 -0
  58. package/dist/core/memoryManager.js +181 -0
  59. package/dist/core/memoryManager.js.map +1 -0
  60. package/dist/core/memoryPolicy.d.ts +23 -0
  61. package/dist/core/memoryPolicy.js +73 -0
  62. package/dist/core/memoryPolicy.js.map +1 -0
  63. package/dist/core/modelClient.d.ts +37 -0
  64. package/dist/core/modelClient.js +160 -0
  65. package/dist/core/modelClient.js.map +1 -0
  66. package/dist/core/patchManager.d.ts +89 -0
  67. package/dist/core/patchManager.js +801 -0
  68. package/dist/core/patchManager.js.map +1 -0
  69. package/dist/core/plannerJson.d.ts +23 -0
  70. package/dist/core/plannerJson.js +118 -0
  71. package/dist/core/plannerJson.js.map +1 -0
  72. package/dist/core/promptManager.d.ts +16 -0
  73. package/dist/core/promptManager.js +35 -0
  74. package/dist/core/promptManager.js.map +1 -0
  75. package/dist/core/prompts.d.ts +8 -0
  76. package/dist/core/prompts.js +18 -0
  77. package/dist/core/prompts.js.map +1 -0
  78. package/dist/core/repoIndexer.d.ts +21 -0
  79. package/dist/core/repoIndexer.js +557 -0
  80. package/dist/core/repoIndexer.js.map +1 -0
  81. package/dist/core/reviewEngine.d.ts +53 -0
  82. package/dist/core/reviewEngine.js +229 -0
  83. package/dist/core/reviewEngine.js.map +1 -0
  84. package/dist/core/runLoop.d.ts +26 -0
  85. package/dist/core/runLoop.js +103 -0
  86. package/dist/core/runLoop.js.map +1 -0
  87. package/dist/core/runStep.d.ts +42 -0
  88. package/dist/core/runStep.js +586 -0
  89. package/dist/core/runStep.js.map +1 -0
  90. package/dist/core/safetyManager.d.ts +7 -0
  91. package/dist/core/safetyManager.js +202 -0
  92. package/dist/core/safetyManager.js.map +1 -0
  93. package/dist/core/sessionManager.d.ts +35 -0
  94. package/dist/core/sessionManager.js +265 -0
  95. package/dist/core/sessionManager.js.map +1 -0
  96. package/dist/core/stopConditions.d.ts +24 -0
  97. package/dist/core/stopConditions.js +18 -0
  98. package/dist/core/stopConditions.js.map +1 -0
  99. package/dist/core/taskManager.d.ts +26 -0
  100. package/dist/core/taskManager.js +312 -0
  101. package/dist/core/taskManager.js.map +1 -0
  102. package/dist/core/testRunner.d.ts +27 -0
  103. package/dist/core/testRunner.js +71 -0
  104. package/dist/core/testRunner.js.map +1 -0
  105. package/dist/prompts/coder.d.ts +3 -0
  106. package/dist/prompts/coder.js +46 -0
  107. package/dist/prompts/coder.js.map +1 -0
  108. package/dist/prompts/planner.d.ts +3 -0
  109. package/dist/prompts/planner.js +44 -0
  110. package/dist/prompts/planner.js.map +1 -0
  111. package/dist/prompts/reviewer.d.ts +3 -0
  112. package/dist/prompts/reviewer.js +41 -0
  113. package/dist/prompts/reviewer.js.map +1 -0
  114. package/dist/prompts/summarizer.d.ts +3 -0
  115. package/dist/prompts/summarizer.js +65 -0
  116. package/dist/prompts/summarizer.js.map +1 -0
  117. package/dist/prompts/testFixer.d.ts +3 -0
  118. package/dist/prompts/testFixer.js +33 -0
  119. package/dist/prompts/testFixer.js.map +1 -0
  120. package/dist/repl/approver.d.ts +15 -0
  121. package/dist/repl/approver.js +21 -0
  122. package/dist/repl/approver.js.map +1 -0
  123. package/dist/repl/dispatch.d.ts +48 -0
  124. package/dist/repl/dispatch.js +164 -0
  125. package/dist/repl/dispatch.js.map +1 -0
  126. package/dist/repl/loop.d.ts +14 -0
  127. package/dist/repl/loop.js +124 -0
  128. package/dist/repl/loop.js.map +1 -0
  129. package/dist/repl/tokenize.d.ts +13 -0
  130. package/dist/repl/tokenize.js +56 -0
  131. package/dist/repl/tokenize.js.map +1 -0
  132. package/dist/templates/memory.d.ts +13 -0
  133. package/dist/templates/memory.js +32 -0
  134. package/dist/templates/memory.js.map +1 -0
  135. package/dist/types/config.d.ts +235 -0
  136. package/dist/types/config.js +66 -0
  137. package/dist/types/config.js.map +1 -0
  138. package/dist/types/context.d.ts +78 -0
  139. package/dist/types/context.js +141 -0
  140. package/dist/types/context.js.map +1 -0
  141. package/dist/types/index.d.ts +117 -0
  142. package/dist/types/index.js +24 -0
  143. package/dist/types/index.js.map +1 -0
  144. package/dist/types/model.d.ts +35 -0
  145. package/dist/types/model.js +16 -0
  146. package/dist/types/model.js.map +1 -0
  147. package/dist/types/patch.d.ts +38 -0
  148. package/dist/types/patch.js +11 -0
  149. package/dist/types/patch.js.map +1 -0
  150. package/dist/types/plan.d.ts +86 -0
  151. package/dist/types/plan.js +27 -0
  152. package/dist/types/plan.js.map +1 -0
  153. package/dist/types/review.d.ts +33 -0
  154. package/dist/types/review.js +24 -0
  155. package/dist/types/review.js.map +1 -0
  156. package/dist/types/run.d.ts +34 -0
  157. package/dist/types/run.js +2 -0
  158. package/dist/types/run.js.map +1 -0
  159. package/dist/types/session.d.ts +21 -0
  160. package/dist/types/session.js +2 -0
  161. package/dist/types/session.js.map +1 -0
  162. package/dist/types/summary.d.ts +65 -0
  163. package/dist/types/summary.js +26 -0
  164. package/dist/types/summary.js.map +1 -0
  165. package/dist/types/task.d.ts +31 -0
  166. package/dist/types/task.js +10 -0
  167. package/dist/types/task.js.map +1 -0
  168. package/dist/types/test.d.ts +16 -0
  169. package/dist/types/test.js +2 -0
  170. package/dist/types/test.js.map +1 -0
  171. package/dist/utils/fs.d.ts +13 -0
  172. package/dist/utils/fs.js +65 -0
  173. package/dist/utils/fs.js.map +1 -0
  174. package/dist/utils/gitRoot.d.ts +5 -0
  175. package/dist/utils/gitRoot.js +21 -0
  176. package/dist/utils/gitRoot.js.map +1 -0
  177. package/dist/utils/logger.d.ts +15 -0
  178. package/dist/utils/logger.js +60 -0
  179. package/dist/utils/logger.js.map +1 -0
  180. package/dist/utils/paths.d.ts +13 -0
  181. package/dist/utils/paths.js +24 -0
  182. package/dist/utils/paths.js.map +1 -0
  183. package/dist/utils/tokenEstimate.d.ts +5 -0
  184. package/dist/utils/tokenEstimate.js +8 -0
  185. package/dist/utils/tokenEstimate.js.map +1 -0
  186. package/package.json +44 -0
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maayan Almog
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.
22
+ </content>
23
+ </invoke>
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # LocalPTP — LocalCode Orchestrator
2
+
3
+ A command-line orchestrator that drives a **local** coding model (served by [LM Studio](https://lmstudio.ai/)) over a large codebase. It indexes your repo, builds focused context packages, decomposes a task into ordered subtasks, and applies model-generated diffs through safety gates with approval checkpoints — then reviews and summarizes the work.
4
+
5
+ Everything runs against a model on your own machine. No code leaves your computer.
6
+
7
+ ## Features
8
+
9
+ - **Repo indexing** — scans the codebase into `.ai-orchestrator/index.json` and a `/ai` memory map.
10
+ - **Context builder** — assembles role-scoped, token-budgeted context for the model.
11
+ - **Task planning** — decomposes a task into ordered subtasks via the model.
12
+ - **Step/run loop** — model → diff → safety gates → approval → apply → tests, one subtask at a time or looped.
13
+ - **Safety gates** — approval prompts, risky-path confirmation, changed-file limits, binary/path-traversal refusals.
14
+ - **Review** — advisory review of the current Git diff (modifies nothing).
15
+ - **Summarize** — closes the loop by updating `/ai` memory from the session.
16
+
17
+ ## Requirements
18
+
19
+ - **Node.js ≥ 20**
20
+ - **[LM Studio](https://lmstudio.ai/)** running locally with a model loaded and its OpenAI-compatible server started (default `http://localhost:1234/v1`).
21
+ - Default model: **`qwen/qwen3.6-27b`** (configurable — see [Configuration](#configuration)).
22
+ - **Git** (the orchestrator operates on a Git working tree).
23
+
24
+ ## Installation
25
+
26
+ ### Install from npm (recommended)
27
+
28
+ ```bash
29
+ npm install -g localptp
30
+ localptp <command>
31
+ ```
32
+
33
+ ### Try it without installing
34
+
35
+ ```bash
36
+ npx localptp <command>
37
+ ```
38
+
39
+ ### Clone and build (for contributors)
40
+
41
+ ```bash
42
+ # 1. Clone
43
+ git clone https://github.com/AlmogMaayan/LocalPTP.git
44
+ cd LocalPTP
45
+
46
+ # 2. Install dependencies
47
+ npm install
48
+
49
+ # 3. Build
50
+ npm run build
51
+ ```
52
+
53
+ #### Run it (contributor workflow)
54
+
55
+ During development (no build step, runs the TypeScript directly):
56
+
57
+ ```bash
58
+ npm run localptp -- <command>
59
+ ```
60
+
61
+ After building, run the compiled CLI:
62
+
63
+ ```bash
64
+ node dist/cli.js <command>
65
+ ```
66
+
67
+ Or install it globally so `localptp` is on your `PATH`:
68
+
69
+ ```bash
70
+ npm install -g .
71
+ localptp <command>
72
+ ```
73
+
74
+ > **Deprecated alias:** The `localcoder` binary resolves to the same CLI for one release and will be removed thereafter. Please update any scripts to use `localptp`.
75
+
76
+ ## Quick start
77
+
78
+ ```bash
79
+ # 0. Start LM Studio, load qwen/qwen3.6-27b, and start its local server.
80
+
81
+ # 1. Scaffold /ai memory + .ai-orchestrator/config.yml (idempotent)
82
+ localptp init
83
+
84
+ # 2. Verify LM Studio is reachable and the model responds
85
+ localptp doctor
86
+
87
+ # 3. Index the repo
88
+ localptp index
89
+
90
+ # 4. Create a task
91
+ localptp task "add input validation to the signup form"
92
+
93
+ # 5. Plan it into subtasks (calls the model)
94
+ localptp plan
95
+
96
+ # 6. Execute — one subtask, or loop until a stop condition
97
+ localptp step
98
+ localptp run
99
+
100
+ # 7. Review the diff and summarize the session
101
+ localptp review
102
+ localptp summarize
103
+ ```
104
+
105
+ ## Commands
106
+
107
+ | Command | Description |
108
+ |---------|-------------|
109
+ | `init` | Scaffold `/ai` memory + `.ai-orchestrator/config.yml` (idempotent; no source edits). |
110
+ | `config [key] [value]` | Show the merged config, a sub-tree, or set a dotted key (e.g. `config model.model`). |
111
+ | `doctor` | Verify LM Studio is reachable and the model responds. |
112
+ | `index` | Scan the repo and write `.ai-orchestrator/index.json` + update `/ai` memory map files. |
113
+ | `context [--role <role>]` | Preview the context package for a role (read-only; no model call). |
114
+ | `task <text>` | Create a scoped task + session and mark them active. |
115
+ | `plan` | Decompose the active task into ordered subtasks (calls the model). |
116
+ | `resume [index]` | List past sessions and continue from a selected one. |
117
+ | `step` | Run the next pending subtask: model → diff → safety gates → approval → apply → tests. |
118
+ | `run` | Loop the step cycle over pending subtasks with approval checkpoints until a stop condition. |
119
+ | `review` | Review the current Git diff with the model (advisory; modifies nothing). |
120
+ | `summarize` | Summarize the session and update `/ai` memory files. |
121
+
122
+ **Global flags:** `--json` (structured output) · `--debug` (verbose logging).
123
+
124
+ ## Configuration
125
+
126
+ `localptp init` writes `.ai-orchestrator/config.yml`. Sensible defaults apply when a field is absent. Key model settings:
127
+
128
+ ```yaml
129
+ model:
130
+ provider: lmstudio
131
+ base_url: http://localhost:1234/v1
132
+ model: qwen/qwen3.6-27b
133
+ api_key: lm-studio
134
+ temperature: 0.2
135
+ max_context_tokens: 32768
136
+ timeout_ms: 60000
137
+ ```
138
+
139
+ Read or change values from the CLI:
140
+
141
+ ```bash
142
+ localptp config model.model # show current model
143
+ localptp config model.model qwen/qwen3.6-27b # set the model
144
+ localptp config model.baseUrl # show the LM Studio endpoint
145
+ ```
146
+
147
+ Safety, context, and command settings (typecheck/lint/test/build) are also configurable — run `localptp config` to see the full merged tree.
148
+
149
+ ## Development
150
+
151
+ ```bash
152
+ npm run build # compile TypeScript to dist/
153
+ npm run typecheck # type-check without emitting
154
+ npm test # run the vitest suite
155
+ ```
156
+
157
+ ## License
158
+
159
+ [MIT](./LICENSE) © 2026 Maayan Almog
package/dist/cli.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `localptp` CLI entry (HLD-SRD §3.1, §8).
4
+ *
5
+ * Registers the full MVP command surface: `init`, `config`, `doctor` are live;
6
+ * the remaining nine are stubs that print "not implemented yet (slice 000X)"
7
+ * and exit non-zero. Global flags: `--json`, `--debug`.
8
+ */
9
+ import { Command } from "commander";
10
+ /** Deferred commands and the slice that will implement each. */
11
+ export declare const STUB_COMMANDS: Record<string, string>;
12
+ /**
13
+ * Returns `true` iff this is a bare TTY invocation that should start the REPL:
14
+ * - strip `--json` and `--debug` from `argv.slice(2)`
15
+ * - if NO tokens remain AND `process.stdin.isTTY === true` AND `--json` is absent
16
+ *
17
+ * Any remaining token (sub-command, unknown positional, `--help`, `--version`,
18
+ * `--`) counts as "not bare" and falls through to Commander.
19
+ *
20
+ * `program` is accepted for API symmetry (future name-aware checks) but unused.
21
+ */
22
+ export declare function shouldStartRepl(_program: Command, argv: string[]): boolean;
23
+ export declare function buildProgram(): Command;
24
+ export declare function main(argv: string[]): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,344 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `localptp` CLI entry (HLD-SRD §3.1, §8).
4
+ *
5
+ * Registers the full MVP command surface: `init`, `config`, `doctor` are live;
6
+ * the remaining nine are stubs that print "not implemented yet (slice 000X)"
7
+ * and exit non-zero. Global flags: `--json`, `--debug`.
8
+ */
9
+ import { Command } from "commander";
10
+ import { pathToFileURL, fileURLToPath } from "node:url";
11
+ import { realpathSync } from "node:fs";
12
+ import { createRequire } from "node:module";
13
+ const _require = createRequire(import.meta.url);
14
+ const { version: PKG_VERSION } = _require("../package.json");
15
+ import { runInit, formatInitReport } from "./commands/init.js";
16
+ import { runConfig, formatConfigResult } from "./commands/config.js";
17
+ import { runDoctor, formatDoctorResult } from "./commands/doctor.js";
18
+ import { runIndex, formatIndexResult } from "./commands/index.js";
19
+ import { runContext, formatContextResult } from "./commands/context.js";
20
+ import { runTask, formatTaskResult } from "./commands/task.js";
21
+ import { runPlan, formatPlanResult } from "./commands/plan.js";
22
+ import { runResume, formatResumeResult } from "./commands/resume.js";
23
+ import { runStep, formatStepResult } from "./commands/step.js";
24
+ import { run as runRun, formatRunResult } from "./commands/run.js";
25
+ import { runReview, formatReviewResult } from "./commands/review.js";
26
+ import { runSummarize, formatSummarizeResult } from "./commands/summarize.js";
27
+ import { ModelClientError } from "./types/model.js";
28
+ import { redactSecrets } from "./utils/logger.js";
29
+ import { startRepl } from "./repl/loop.js";
30
+ /** Deferred commands and the slice that will implement each. */
31
+ export const STUB_COMMANDS = {};
32
+ /**
33
+ * Returns `true` iff this is a bare TTY invocation that should start the REPL:
34
+ * - strip `--json` and `--debug` from `argv.slice(2)`
35
+ * - if NO tokens remain AND `process.stdin.isTTY === true` AND `--json` is absent
36
+ *
37
+ * Any remaining token (sub-command, unknown positional, `--help`, `--version`,
38
+ * `--`) counts as "not bare" and falls through to Commander.
39
+ *
40
+ * `program` is accepted for API symmetry (future name-aware checks) but unused.
41
+ */
42
+ export function shouldStartRepl(_program, argv) {
43
+ const hasJson = argv.includes("--json");
44
+ if (hasJson)
45
+ return false;
46
+ const rest = argv.slice(2).filter((a) => a !== "--json" && a !== "--debug");
47
+ return rest.length === 0 && process.stdin.isTTY === true;
48
+ }
49
+ function globalOpts(command) {
50
+ // Walk to the root program to read global options.
51
+ let root = command;
52
+ while (root.parent)
53
+ root = root.parent;
54
+ return root.opts();
55
+ }
56
+ export function buildProgram() {
57
+ const program = new Command();
58
+ program
59
+ .name("localptp")
60
+ .description("LocalCode Orchestrator — drive a local coding model over a codebase.")
61
+ .version(PKG_VERSION, "-V, --version", "output the version number")
62
+ .option("--json", "emit structured output as JSON")
63
+ .option("--debug", "raise log verbosity")
64
+ .enablePositionalOptions();
65
+ // --- live commands ---
66
+ program
67
+ .command("init")
68
+ .description("Scaffold /ai memory + .ai-orchestrator/config.yml (idempotent, no source edits)")
69
+ .action(async function () {
70
+ const opts = globalOpts(this);
71
+ const report = await runInit({ cwd: process.cwd(), json: opts.json });
72
+ if (opts.json) {
73
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
74
+ }
75
+ else {
76
+ process.stdout.write(formatInitReport(report) + "\n");
77
+ }
78
+ });
79
+ program
80
+ .command("config")
81
+ .description("Show the merged config, a sub-tree, or set a dotted key")
82
+ .argument("[key]", "dotted config key or sub-tree (e.g. model.baseUrl)")
83
+ .argument("[value]", "value to set; omit to show")
84
+ .action(async function (key, value) {
85
+ const opts = globalOpts(this);
86
+ const result = await runConfig({ cwd: process.cwd(), key, value, json: opts.json });
87
+ if (opts.json) {
88
+ process.stdout.write(JSON.stringify(result.value, null, 2) + "\n");
89
+ }
90
+ else {
91
+ process.stdout.write(formatConfigResult(result) + "\n");
92
+ }
93
+ });
94
+ program
95
+ .command("doctor")
96
+ .description("Verify LM Studio is reachable and the model responds")
97
+ .action(async function () {
98
+ const opts = globalOpts(this);
99
+ const result = await runDoctor({ cwd: process.cwd(), json: opts.json });
100
+ if (opts.json) {
101
+ process.stdout.write(JSON.stringify({ reachable: result.reachable, model: result.model, latencyMs: result.latencyMs }, null, 2) + "\n");
102
+ }
103
+ else {
104
+ process.stdout.write(formatDoctorResult(result) + "\n");
105
+ }
106
+ });
107
+ program
108
+ .command("index")
109
+ .description("Scan the repo and write .ai-orchestrator/index.json + update /ai memory map files")
110
+ .action(async function () {
111
+ const opts = globalOpts(this);
112
+ const result = await runIndex({ cwd: process.cwd(), json: opts.json });
113
+ if (opts.json) {
114
+ process.stdout.write(JSON.stringify({ indexed: result.indexed, ignored: result.ignored, durationMs: result.durationMs }, null, 2) + "\n");
115
+ }
116
+ else {
117
+ process.stdout.write(formatIndexResult(result) + "\n");
118
+ }
119
+ });
120
+ program
121
+ .command("context")
122
+ .description("Preview the context package for a role (read-only; no model call)")
123
+ .option("--role <role>", "agent role to preview (default: coder)")
124
+ .action(async function () {
125
+ const opts = globalOpts(this);
126
+ const local = this.opts();
127
+ const result = await runContext({
128
+ cwd: process.cwd(),
129
+ role: local.role,
130
+ json: opts.json,
131
+ });
132
+ if (opts.json) {
133
+ process.stdout.write(JSON.stringify(result.pkg, null, 2) + "\n");
134
+ }
135
+ else {
136
+ process.stdout.write(formatContextResult(result) + "\n");
137
+ }
138
+ });
139
+ program
140
+ .command("task")
141
+ .description("Create a scoped task + session and mark them active")
142
+ .argument("<text>", "the task description")
143
+ .action(async function (text) {
144
+ const opts = globalOpts(this);
145
+ const result = await runTask({ cwd: process.cwd(), text, json: opts.json });
146
+ if (opts.json) {
147
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
148
+ }
149
+ else {
150
+ process.stdout.write(formatTaskResult(result) + "\n");
151
+ }
152
+ });
153
+ program
154
+ .command("plan")
155
+ .description("Decompose the active task into ordered subtasks (calls the model)")
156
+ .action(async function () {
157
+ const opts = globalOpts(this);
158
+ const result = await runPlan({ cwd: process.cwd(), json: opts.json });
159
+ if (opts.json) {
160
+ // --json: only the validated plan on stdout (human summary suppressed).
161
+ process.stdout.write(JSON.stringify(result.plan, null, 2) + "\n");
162
+ }
163
+ else {
164
+ process.stdout.write(formatPlanResult(result) + "\n");
165
+ }
166
+ });
167
+ program
168
+ .command("resume")
169
+ .description("List past sessions and continue from a selected one")
170
+ .argument("[index]", "1-based index of the session to resume")
171
+ .action(async function (index) {
172
+ const opts = globalOpts(this);
173
+ const parsed = index !== undefined && index.trim().length > 0
174
+ ? Number(index)
175
+ : undefined;
176
+ const result = await runResume({
177
+ cwd: process.cwd(),
178
+ index: parsed,
179
+ json: opts.json,
180
+ });
181
+ if (opts.json) {
182
+ process.stdout.write(JSON.stringify({
183
+ sessions: result.sessions.map((s) => ({
184
+ path: s.path,
185
+ status: s.status,
186
+ nextStep: s.nextStep,
187
+ })),
188
+ selected: result.selected?.path,
189
+ }, null, 2) + "\n");
190
+ }
191
+ else {
192
+ process.stdout.write(formatResumeResult(result) + "\n");
193
+ }
194
+ });
195
+ program
196
+ .command("step")
197
+ .description("Run the next pending subtask: model → diff → safety gates → approval → apply → tests")
198
+ .action(async function () {
199
+ const opts = globalOpts(this);
200
+ const result = await runStep({ cwd: process.cwd(), json: opts.json });
201
+ if (opts.json) {
202
+ process.stdout.write(JSON.stringify({
203
+ applied: result.applied,
204
+ done: result.done,
205
+ subtaskId: result.subtaskId,
206
+ patchPath: result.patchPath,
207
+ needsContext: result.needsContext,
208
+ testResults: result.testResults,
209
+ }, null, 2) + "\n");
210
+ }
211
+ else {
212
+ process.stdout.write(formatStepResult(result) + "\n");
213
+ }
214
+ });
215
+ program
216
+ .command("run")
217
+ .description("Loop the step cycle over pending subtasks with approval checkpoints until a stop condition")
218
+ .action(async function () {
219
+ const opts = globalOpts(this);
220
+ const result = await runRun({ cwd: process.cwd(), json: opts.json });
221
+ if (opts.json) {
222
+ process.stdout.write(JSON.stringify({
223
+ stopReason: result.stopReason,
224
+ applied: result.applied,
225
+ iterations: result.iterations,
226
+ }, null, 2) + "\n");
227
+ }
228
+ else {
229
+ process.stdout.write(formatRunResult(result) + "\n");
230
+ }
231
+ });
232
+ program
233
+ .command("review")
234
+ .description("Review the current Git diff with the model (advisory; modifies nothing)")
235
+ .action(async function () {
236
+ const opts = globalOpts(this);
237
+ const result = await runReview({ cwd: process.cwd(), json: opts.json });
238
+ if (opts.json) {
239
+ process.stdout.write(JSON.stringify({ hadChanges: result.hadChanges, report: result.report, raw: result.raw }, null, 2) + "\n");
240
+ }
241
+ else {
242
+ process.stdout.write(formatReviewResult(result) + "\n");
243
+ }
244
+ });
245
+ program
246
+ .command("summarize")
247
+ .description("Summarize the session and update /ai memory files (closes the daily loop)")
248
+ .action(async function () {
249
+ const opts = globalOpts(this);
250
+ const result = await runSummarize({ cwd: process.cwd(), json: opts.json });
251
+ if (opts.json) {
252
+ process.stdout.write(JSON.stringify({
253
+ session: { path: result.session.path, status: result.session.status },
254
+ updatedFiles: result.updatedFiles,
255
+ ignored: result.ignored,
256
+ }, null, 2) + "\n");
257
+ }
258
+ else {
259
+ process.stdout.write(formatSummarizeResult(result) + "\n");
260
+ }
261
+ });
262
+ // --- stub commands ---
263
+ for (const [name, slice] of Object.entries(STUB_COMMANDS)) {
264
+ program
265
+ .command(name)
266
+ .description(`(not implemented yet — slice ${slice})`)
267
+ .allowExcessArguments(true)
268
+ .allowUnknownOption(true)
269
+ .action(() => {
270
+ console.error(`${name}: not implemented yet (slice ${slice})`);
271
+ const err = new Error(`not implemented: ${name}`);
272
+ err.exitCode = 1;
273
+ throw err;
274
+ });
275
+ }
276
+ return program;
277
+ }
278
+ /** Map an error to a user-facing message + exit code. */
279
+ function reportError(err) {
280
+ if (err instanceof ModelClientError) {
281
+ // baseUrl may carry credentials (user:pass@host) — redact before stderr.
282
+ console.error(redactSecrets(err.message));
283
+ return 1;
284
+ }
285
+ if (err instanceof Error) {
286
+ const code = err.exitCode;
287
+ // Stub errors print their own message before throwing (a generic `Error`
288
+ // named "Error" carrying an exitCode); everything else still needs its
289
+ // message surfaced to stderr — including the Patch Manager refusals
290
+ // (PatchValidationError / PatchApplyError / WorkingTreeUnsafeError), whose
291
+ // reason must reach the user, not just a bare non-zero exit.
292
+ const isSelfPrintedStub = code !== undefined && err.name === "Error";
293
+ if (!isSelfPrintedStub) {
294
+ console.error(redactSecrets(err.message));
295
+ }
296
+ return typeof code === "number" ? code : 1;
297
+ }
298
+ console.error(redactSecrets(String(err)));
299
+ return 1;
300
+ }
301
+ export async function main(argv) {
302
+ const program = buildProgram();
303
+ if (shouldStartRepl(program, argv)) {
304
+ return await startRepl({ cwd: process.cwd() });
305
+ }
306
+ program.exitOverride();
307
+ try {
308
+ await program.parseAsync(argv);
309
+ return 0;
310
+ }
311
+ catch (err) {
312
+ // commander's help/version exits surface as CommanderError with exitCode 0.
313
+ const commanderCode = err.code;
314
+ if (commanderCode === "commander.helpDisplayed" ||
315
+ commanderCode === "commander.version" ||
316
+ commanderCode === "commander.help") {
317
+ return err.exitCode ?? 0;
318
+ }
319
+ return reportError(err);
320
+ }
321
+ }
322
+ // Only run when invoked directly (not when imported by tests). Compare RESOLVED
323
+ // real paths: when installed via the npm `bin`, `process.argv[1]` is a symlink
324
+ // (e.g. node_modules/.bin/localptp) while `import.meta.url` is realpath-
325
+ // resolved — a raw string compare would miss and the CLI would silently no-op.
326
+ // Falls back to the unresolved compare if realpath fails (e.g. file removed).
327
+ function isDirectRun() {
328
+ const argv1 = process.argv[1];
329
+ if (argv1 === undefined)
330
+ return false;
331
+ const modulePath = fileURLToPath(import.meta.url);
332
+ try {
333
+ return realpathSync(modulePath) === realpathSync(argv1);
334
+ }
335
+ catch {
336
+ return import.meta.url === pathToFileURL(argv1).href;
337
+ }
338
+ }
339
+ if (isDirectRun()) {
340
+ main(process.argv).then((code) => {
341
+ process.exitCode = code;
342
+ });
343
+ }
344
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChD,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAwB,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,GAAG,IAAI,MAAM,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,gEAAgE;AAChE,MAAM,CAAC,MAAM,aAAa,GAA2B,EAAE,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,QAAiB,EAAE,IAAc;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,OAAO;QAAE,OAAO,KAAK,CAAC;IAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC;AAC3D,CAAC;AAOD,SAAS,UAAU,CAAC,OAAgB;IAClC,mDAAmD;IACnD,IAAI,IAAI,GAAY,OAAO,CAAC;IAC5B,OAAO,IAAI,CAAC,MAAM;QAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,OAAO,IAAI,CAAC,IAAI,EAAgB,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CAAC,sEAAsE,CAAC;SACnF,OAAO,CAAC,WAAW,EAAE,eAAe,EAAE,2BAA2B,CAAC;SAClE,MAAM,CAAC,QAAQ,EAAE,gCAAgC,CAAC;SAClD,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC;SACxC,uBAAuB,EAAE,CAAC;IAE7B,wBAAwB;IAExB,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,iFAAiF,CAAC;SAC9F,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yDAAyD,CAAC;SACtE,QAAQ,CAAC,OAAO,EAAE,oDAAoD,CAAC;SACvE,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;SACjD,MAAM,CAAC,KAAK,WAA0B,GAAY,EAAE,KAAc;QACjE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACpF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,EACjF,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,mFAAmF,CAAC;SAChG,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACvE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,EACnF,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,mEAAmE,CAAC;SAChF,MAAM,CAAC,eAAe,EAAE,wCAAwC,CAAC;SACjE,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAuB,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,qDAAqD,CAAC;SAClE,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;SAC1C,MAAM,CAAC,KAAK,WAA0B,IAAY;QACjD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5E,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,mEAAmE,CAAC;SAChF,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,wEAAwE;YACxE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qDAAqD,CAAC;SAClE,QAAQ,CAAC,SAAS,EAAE,wCAAwC,CAAC;SAC7D,MAAM,CAAC,KAAK,WAA0B,KAAc;QACnD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GACV,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAC5C,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACf,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ;gBACE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACpC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;iBACrB,CAAC,CAAC;gBACH,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI;aAChC,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CACV,sFAAsF,CACvF;SACA,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ;gBACE,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,WAAW,EAAE,MAAM,CAAC,WAAW;aAChC,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CACV,4FAA4F,CAC7F;SACA,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ;gBACE,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,UAAU,EAAE,MAAM,CAAC,UAAU;aAC9B,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yEAAyE,CAAC;SACtF,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,EACzE,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,2EAA2E,CAAC;SACxF,MAAM,CAAC,KAAK;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ;gBACE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE;gBACrE,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,wBAAwB;IAExB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1D,OAAO;aACJ,OAAO,CAAC,IAAI,CAAC;aACb,WAAW,CAAC,gCAAgC,KAAK,GAAG,CAAC;aACrD,oBAAoB,CAAC,IAAI,CAAC;aAC1B,kBAAkB,CAAC,IAAI,CAAC;aACxB,MAAM,CAAC,GAAG,EAAE;YACX,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,gCAAgC,KAAK,GAAG,CAAC,CAAC;YAC/D,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAE/C,CAAC;YACF,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC;YACjB,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,yDAAyD;AACzD,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;QACpC,yEAAyE;QACzE,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAI,GAA6B,CAAC,QAAQ,CAAC;QACrD,yEAAyE;QACzE,uEAAuE;QACvE,oEAAoE;QACpE,2EAA2E;QAC3E,6DAA6D;QAC7D,MAAM,iBAAiB,GAAG,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC;QACrE,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAC/B,IAAI,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,CAAC,YAAY,EAAE,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,MAAM,aAAa,GAAI,GAA4C,CAAC,IAAI,CAAC;QACzE,IACE,aAAa,KAAK,yBAAyB;YAC3C,aAAa,KAAK,mBAAmB;YACrC,aAAa,KAAK,gBAAgB,EAClC,CAAC;YACD,OAAQ,GAA6B,CAAC,QAAQ,IAAI,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,+EAA+E;AAC/E,yEAAyE;AACzE,+EAA+E;AAC/E,8EAA8E;AAC9E,SAAS,WAAW;IAClB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,UAAU,CAAC,KAAK,YAAY,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;IACvD,CAAC;AACH,CAAC;AAED,IAAI,WAAW,EAAE,EAAE,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface ConfigOptions {
2
+ cwd: string;
3
+ key?: string;
4
+ value?: string;
5
+ json?: boolean;
6
+ }
7
+ export interface ConfigResult {
8
+ mode: "show" | "set";
9
+ /** For show: the (redacted) config object or sub-tree. For set: the redacted full config. */
10
+ value: unknown;
11
+ key?: string;
12
+ }
13
+ export declare function runConfig(opts: ConfigOptions): Promise<ConfigResult>;
14
+ export declare function formatConfigResult(result: ConfigResult): string;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `localptp config` (HLD-SRD §3.2).
3
+ *
4
+ * - `config` → show the full merged config (api_key redacted).
5
+ * - `config <subtree>` → show that sub-tree (e.g. `config model`).
6
+ * - `config <key> <value>` → coerce, set the dotted path, re-validate, write.
7
+ *
8
+ * The redaction keeps the api_key off stdout/JSON (no-secret display control).
9
+ */
10
+ import { layout } from "../utils/paths.js";
11
+ import { detectGitRoot } from "../utils/gitRoot.js";
12
+ import { ConfigManager } from "../core/configManager.js";
13
+ const REDACTED = "[REDACTED]";
14
+ /** Deep-clone the config and redact the api_key for display. */
15
+ function redactConfig(config) {
16
+ const clone = structuredClone(config);
17
+ clone.model.apiKey = REDACTED;
18
+ return clone;
19
+ }
20
+ const FORBIDDEN_KEYS = new Set(["__proto__", "prototype", "constructor"]);
21
+ function getSubtree(obj, dotted) {
22
+ let cursor = obj;
23
+ for (const part of dotted.split(".")) {
24
+ if (part.length === 0 ||
25
+ FORBIDDEN_KEYS.has(part) ||
26
+ typeof cursor !== "object" ||
27
+ cursor === null ||
28
+ !Object.prototype.hasOwnProperty.call(cursor, part)) {
29
+ return undefined;
30
+ }
31
+ cursor = cursor[part];
32
+ }
33
+ return cursor;
34
+ }
35
+ export async function runConfig(opts) {
36
+ // Resolve the repo root (like `init`) so config is read/written at the repo
37
+ // root regardless of the subdirectory the command is run from; fall back to
38
+ // cwd outside a Git repo.
39
+ const git = await detectGitRoot(opts.cwd);
40
+ const l = layout(git.root ?? opts.cwd);
41
+ const cm = new ConfigManager(l.configFile);
42
+ // Set mode: a key AND a value were given.
43
+ if (opts.key !== undefined && opts.value !== undefined) {
44
+ const updated = await cm.set(opts.key, opts.value);
45
+ return { mode: "set", key: opts.key, value: redactConfig(updated) };
46
+ }
47
+ // Show mode: full config or a sub-tree.
48
+ const config = await cm.load();
49
+ const redacted = redactConfig(config);
50
+ if (opts.key !== undefined) {
51
+ const subtree = getSubtree(redacted, opts.key);
52
+ if (subtree === undefined) {
53
+ throw new Error(`Unknown config key: ${opts.key}`);
54
+ }
55
+ return { mode: "show", key: opts.key, value: subtree };
56
+ }
57
+ return { mode: "show", value: redacted };
58
+ }
59
+ export function formatConfigResult(result) {
60
+ if (result.mode === "set") {
61
+ return `Set ${result.key}`;
62
+ }
63
+ return JSON.stringify(result.value, null, 2);
64
+ }
65
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAiBzD,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B,gEAAgE;AAChE,SAAS,YAAY,CAAC,MAAiB;IACrC,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;AAE1E,SAAS,UAAU,CAAC,GAAY,EAAE,MAAc;IAC9C,IAAI,MAAM,GAAY,GAAG,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,IACE,IAAI,CAAC,MAAM,KAAK,CAAC;YACjB,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;YACxB,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EACnD,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,GAAI,MAAkC,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,4EAA4E;IAC5E,4EAA4E;IAC5E,0BAA0B;IAC1B,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAE3C,0CAA0C;IAC1C,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,wCAAwC;IACxC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type ContextPackage } from "../types/context.js";
2
+ export interface ContextOptions {
3
+ cwd: string;
4
+ role?: string;
5
+ json?: boolean;
6
+ }
7
+ export interface ContextResult {
8
+ pkg: ContextPackage;
9
+ maxContextTokens: number;
10
+ }
11
+ export declare function runContext(opts: ContextOptions): Promise<ContextResult>;
12
+ export declare function formatContextResult(result: ContextResult): string;