howtofixcli 0.7.13 → 0.7.15

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 (161) hide show
  1. package/dist/chunk-27TRKD65.js +2 -0
  2. package/dist/chunk-3FYCFLNK.js +1 -0
  3. package/dist/chunk-56SEAGAQ.js +1 -0
  4. package/dist/chunk-6FUWMLWO.js +1 -0
  5. package/dist/chunk-7CHDNTH6.js +1 -0
  6. package/dist/chunk-7DTQKDO4.js +2 -0
  7. package/dist/chunk-AGGIYXN7.js +2 -0
  8. package/dist/chunk-AUDMRGWF.js +189 -0
  9. package/dist/chunk-CPJKKHGH.js +1 -0
  10. package/dist/chunk-DAPXGSGD.js +12 -0
  11. package/dist/chunk-DOD7MUGX.js +1 -0
  12. package/dist/chunk-DV2BBBBJ.js +2 -0
  13. package/dist/chunk-EIBOS5KO.js +5 -0
  14. package/dist/chunk-EYWOVCSS.js +6 -0
  15. package/dist/chunk-FPXVDP32.js +8 -0
  16. package/dist/chunk-GXB7RZHH.js +1 -0
  17. package/dist/chunk-HT3MFLAV.js +34 -0
  18. package/dist/chunk-ILDDDLRC.js +1 -0
  19. package/dist/chunk-JFYVRWJI.js +2 -0
  20. package/dist/chunk-JMKK26AT.js +2 -0
  21. package/dist/chunk-LAHVHRCS.js +2 -0
  22. package/dist/chunk-LOOFOBTS.js +1 -0
  23. package/dist/chunk-LSJC73DG.js +1 -0
  24. package/dist/chunk-MOKUBKE7.js +1 -0
  25. package/dist/chunk-N345KWWK.js +1 -0
  26. package/dist/chunk-ONZLNFQ2.js +3 -0
  27. package/dist/chunk-ORJ2QZBG.js +3 -0
  28. package/dist/chunk-PCALBZOO.js +2 -0
  29. package/dist/chunk-SX5VE6XA.js +110 -0
  30. package/dist/chunk-TSEKPGK4.js +1 -0
  31. package/dist/chunk-UNK5HRQR.js +1 -0
  32. package/dist/chunk-UTYFLLSM.js +1 -0
  33. package/dist/chunk-V2RPZMLK.js +1 -0
  34. package/dist/chunk-V3R4FYTJ.js +1 -0
  35. package/dist/chunk-V656XVXV.js +8 -0
  36. package/dist/chunk-VLMQSD25.js +1 -0
  37. package/dist/chunk-WKUJ7CFO.js +1 -0
  38. package/dist/chunk-WOT6VMZA.js +1 -0
  39. package/dist/chunk-WUPU6LTD.js +4 -0
  40. package/dist/chunk-WX3V5P7U.js +5 -0
  41. package/dist/chunk-Y7YM5R75.js +5 -0
  42. package/dist/chunk-YW7NORH3.js +2 -0
  43. package/dist/main.js +99 -540
  44. package/package.json +17 -64
  45. package/dist/account-credential.js +0 -136
  46. package/dist/account-credential.test.js +0 -38
  47. package/dist/activity.js +0 -124
  48. package/dist/agent-defs.js +0 -237
  49. package/dist/agent-limiter.js +0 -68
  50. package/dist/agents.js +0 -554
  51. package/dist/anim.js +0 -361
  52. package/dist/args.js +0 -228
  53. package/dist/at-file.js +0 -28
  54. package/dist/brand-extension.js +0 -87
  55. package/dist/brand.js +0 -76
  56. package/dist/browser.js +0 -58
  57. package/dist/cache-report.js +0 -139
  58. package/dist/checkpoint.js +0 -437
  59. package/dist/claims.js +0 -167
  60. package/dist/cli-auth.js +0 -142
  61. package/dist/cli-checkin.js +0 -120
  62. package/dist/cli-credentials.js +0 -254
  63. package/dist/clipboard.js +0 -149
  64. package/dist/collapse.js +0 -129
  65. package/dist/commands.js +0 -294
  66. package/dist/compaction-guard.js +0 -81
  67. package/dist/context-extension.js +0 -17
  68. package/dist/dcp/commands.js +0 -172
  69. package/dist/dcp/compress-state.js +0 -139
  70. package/dist/dcp/compress.js +0 -329
  71. package/dist/dcp/dcp-extension.js +0 -295
  72. package/dist/dcp/dedup.js +0 -93
  73. package/dist/dcp/ids.js +0 -189
  74. package/dist/dcp/index.js +0 -25
  75. package/dist/dcp/middle-prune.js +0 -76
  76. package/dist/dcp/prompts.js +0 -68
  77. package/dist/dcp/protected-content.js +0 -221
  78. package/dist/dcp/protected.js +0 -161
  79. package/dist/dcp/prune.js +0 -418
  80. package/dist/dcp/state.js +0 -176
  81. package/dist/device-id.js +0 -90
  82. package/dist/device-id.test.js +0 -23
  83. package/dist/errors.js +0 -63
  84. package/dist/extensions.js +0 -48
  85. package/dist/fatal.js +0 -35
  86. package/dist/feed.js +0 -498
  87. package/dist/fs-atomic.js +0 -54
  88. package/dist/gateway-errors.js +0 -90
  89. package/dist/git.js +0 -230
  90. package/dist/goal-extension.js +0 -88
  91. package/dist/goal.js +0 -222
  92. package/dist/hooks-extension.js +0 -176
  93. package/dist/hooks.js +0 -443
  94. package/dist/howtofix-account.js +0 -735
  95. package/dist/hud-line.js +0 -153
  96. package/dist/hwid.js +0 -130
  97. package/dist/interrupt.js +0 -60
  98. package/dist/json-events.js +0 -50
  99. package/dist/level-style.js +0 -112
  100. package/dist/loop-guard.js +0 -95
  101. package/dist/lsp-tools.js +0 -32
  102. package/dist/lsp.js +0 -429
  103. package/dist/mcp-config.js +0 -85
  104. package/dist/mcp-lifecycle.js +0 -147
  105. package/dist/model-catalog.js +0 -217
  106. package/dist/model-facts.js +0 -35
  107. package/dist/model-resolve.js +0 -65
  108. package/dist/notes.js +0 -78
  109. package/dist/oauth-login.js +0 -568
  110. package/dist/paths.js +0 -61
  111. package/dist/permissions.js +0 -298
  112. package/dist/plan-mode.js +0 -363
  113. package/dist/preset-command.js +0 -227
  114. package/dist/preset-extension.js +0 -35
  115. package/dist/preset-mcp.js +0 -292
  116. package/dist/presets.js +0 -727
  117. package/dist/prompt-files.js +0 -103
  118. package/dist/prompt-text.js +0 -41
  119. package/dist/proxy.js +0 -137
  120. package/dist/quality/ast.js +0 -196
  121. package/dist/quality/cognitive.js +0 -83
  122. package/dist/quality/cyclomatic.js +0 -30
  123. package/dist/quality/halstead.js +0 -83
  124. package/dist/quality/index.js +0 -18
  125. package/dist/quality/length.js +0 -3
  126. package/dist/quality/maintainability.js +0 -15
  127. package/dist/quality/nesting.js +0 -57
  128. package/dist/quality/report.js +0 -803
  129. package/dist/quality/smells.js +0 -67
  130. package/dist/quality-tool.js +0 -63
  131. package/dist/read-only-commands.js +0 -597
  132. package/dist/repo-map.js +0 -292
  133. package/dist/rtk.js +0 -193
  134. package/dist/sandbox.js +0 -105
  135. package/dist/schema.js +0 -214
  136. package/dist/session-lifecycle.js +0 -19
  137. package/dist/session-retention.js +0 -111
  138. package/dist/session.js +0 -447
  139. package/dist/sessions.js +0 -100
  140. package/dist/settings.js +0 -148
  141. package/dist/skills.js +0 -35
  142. package/dist/slop-tool.js +0 -96
  143. package/dist/spend-cap.js +0 -43
  144. package/dist/subagent.js +0 -171
  145. package/dist/tar.js +0 -146
  146. package/dist/theme.js +0 -79
  147. package/dist/thinking.js +0 -45
  148. package/dist/todo.js +0 -114
  149. package/dist/tool-loadout.js +0 -97
  150. package/dist/tool-render.js +0 -769
  151. package/dist/tools.js +0 -176
  152. package/dist/ui.js +0 -4778
  153. package/dist/update.js +0 -551
  154. package/dist/usage-segment.js +0 -69
  155. package/dist/web-tools.js +0 -46
  156. package/dist/web.js +0 -265
  157. package/dist/welcome.js +0 -179
  158. package/dist/workflow-engine.js +0 -246
  159. package/dist/workflow-progress.js +0 -446
  160. package/dist/workflow-view.js +0 -195
  161. package/dist/workflow.js +0 -349
package/dist/schema.js DELETED
@@ -1,214 +0,0 @@
1
- /**
2
- * A small JSON Schema validator, sufficient for the `schema` option of
3
- * `agent()` in a workflow script.
4
- *
5
- * Why not a library: `ajv` is not installed and the SDK does not export a
6
- * validator, so a dependency would have to be vendored into a repo whose rule is
7
- * not to re-vendor the SDK. The supported subset is the one the workflow spec names
8
- * for structured output — `type`, `properties`, `required`, `items`, `enum`,
9
- * `anyOf`/`oneOf`/`allOf`, `$defs`/`definitions`, `additionalProperties` — which
10
- * is small enough to implement honestly, and the failure messages matter more
11
- * than breadth here: they are fed back to the model as a repair turn.
12
- *
13
- * Validation is intentionally permissive about keywords it does not understand
14
- * (they are ignored rather than failing the value), because the contract is that
15
- * a reply validating against the authored schema is accepted.
16
- */
17
- const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
18
- function typeOf(value) {
19
- if (value === null)
20
- return "null";
21
- if (Array.isArray(value))
22
- return "array";
23
- if (Number.isInteger(value))
24
- return "integer";
25
- return typeof value;
26
- }
27
- function matchesType(value, want) {
28
- const actual = typeOf(value);
29
- if (want === "number")
30
- return actual === "number" || actual === "integer";
31
- if (want === "integer")
32
- return actual === "integer";
33
- return actual === want;
34
- }
35
- /** Resolve a `$ref` against the document root (`#/$defs/name` or `#/definitions/name`). */
36
- function resolveRef(root, ref) {
37
- if (typeof ref !== "string" || !ref.startsWith("#/"))
38
- return undefined;
39
- let node = root;
40
- for (const rawPart of ref.slice(2).split("/")) {
41
- const part = rawPart.replace(/~1/g, "/").replace(/~0/g, "~");
42
- if (!isObject(node) && !Array.isArray(node))
43
- return undefined;
44
- node = node[part];
45
- }
46
- return isObject(node) ? node : undefined;
47
- }
48
- function validateNode(value, schema, root, path, issues) {
49
- if (!isObject(schema))
50
- return;
51
- if (schema.$ref !== undefined) {
52
- const target = resolveRef(root, schema.$ref);
53
- if (target)
54
- validateNode(value, target, root, path, issues);
55
- return;
56
- }
57
- // Combinators. `allOf` must hold everywhere; `anyOf`/`oneOf` need a passing branch.
58
- if (Array.isArray(schema.allOf)) {
59
- for (const branch of schema.allOf)
60
- validateNode(value, branch, root, path, issues);
61
- }
62
- for (const keyword of ["anyOf", "oneOf"]) {
63
- const branches = schema[keyword];
64
- if (!Array.isArray(branches) || branches.length === 0)
65
- continue;
66
- const passes = branches.filter((branch) => {
67
- const scratch = [];
68
- validateNode(value, branch, root, path, scratch);
69
- return scratch.length === 0;
70
- }).length;
71
- if (keyword === "anyOf" && passes === 0)
72
- issues.push({ path, message: "does not match any allowed shape" });
73
- if (keyword === "oneOf" && passes !== 1)
74
- issues.push({ path, message: `must match exactly one shape (matched ${passes})` });
75
- }
76
- const declaredType = schema.type;
77
- if (declaredType !== undefined) {
78
- const wanted = Array.isArray(declaredType) ? declaredType.map(String) : [String(declaredType)];
79
- if (!wanted.some((want) => matchesType(value, want))) {
80
- issues.push({ path, message: `expected ${wanted.join(" or ")}, got ${typeOf(value)}` });
81
- return; // A wrong type makes the remaining checks noise.
82
- }
83
- }
84
- if (Array.isArray(schema.enum) && !schema.enum.some((option) => JSON.stringify(option) === JSON.stringify(value))) {
85
- issues.push({ path, message: `must be one of ${schema.enum.map((option) => JSON.stringify(option)).join(", ")}` });
86
- }
87
- if (isObject(value)) {
88
- const properties = isObject(schema.properties) ? schema.properties : {};
89
- if (Array.isArray(schema.required)) {
90
- for (const key of schema.required.map(String)) {
91
- if (!(key in value))
92
- issues.push({ path: path ? `${path}.${key}` : key, message: "is required" });
93
- }
94
- }
95
- for (const [key, propertySchema] of Object.entries(properties)) {
96
- if (key in value)
97
- validateNode(value[key], propertySchema, root, path ? `${path}.${key}` : key, issues);
98
- }
99
- if (schema.additionalProperties === false) {
100
- for (const key of Object.keys(value)) {
101
- if (!(key in properties))
102
- issues.push({ path: path ? `${path}.${key}` : key, message: "is not an allowed property" });
103
- }
104
- }
105
- else if (isObject(schema.additionalProperties)) {
106
- for (const [key, entry] of Object.entries(value)) {
107
- if (!(key in properties))
108
- validateNode(entry, schema.additionalProperties, root, path ? `${path}.${key}` : key, issues);
109
- }
110
- }
111
- }
112
- if (Array.isArray(value) && schema.items !== undefined) {
113
- const items = schema.items;
114
- if (Array.isArray(items)) {
115
- // Tuple form: validate positionally.
116
- value.forEach((entry, index) => {
117
- if (index < items.length)
118
- validateNode(entry, items[index], root, `${path}[${index}]`, issues);
119
- });
120
- }
121
- else {
122
- value.forEach((entry, index) => validateNode(entry, items, root, `${path}[${index}]`, issues));
123
- }
124
- }
125
- if (typeof value === "string") {
126
- if (typeof schema.minLength === "number" && value.length < schema.minLength) {
127
- issues.push({ path, message: `is shorter than ${schema.minLength} characters` });
128
- }
129
- if (typeof schema.pattern === "string") {
130
- try {
131
- if (!new RegExp(schema.pattern).test(value))
132
- issues.push({ path, message: `does not match ${schema.pattern}` });
133
- }
134
- catch {
135
- // An invalid pattern is the schema author's problem, not the value's.
136
- }
137
- }
138
- }
139
- if (typeof value === "number") {
140
- if (typeof schema.minimum === "number" && value < schema.minimum)
141
- issues.push({ path, message: `is below ${schema.minimum}` });
142
- if (typeof schema.maximum === "number" && value > schema.maximum)
143
- issues.push({ path, message: `is above ${schema.maximum}` });
144
- }
145
- }
146
- /** Every way `value` fails `schema`. Empty means it validates. */
147
- export function validateSchema(value, schema) {
148
- if (!isObject(schema))
149
- return [];
150
- const issues = [];
151
- validateNode(value, schema, schema, "", issues);
152
- return issues;
153
- }
154
- /** One line per issue, for a repair turn. */
155
- export function formatIssues(issues) {
156
- return issues.map((issue) => `- ${issue.path || "(root)"}: ${issue.message}`).join("\n");
157
- }
158
- /**
159
- * Pull a JSON value out of a model reply.
160
- *
161
- * Models wrap JSON in prose or fences often enough that a bare `JSON.parse` is
162
- * not a fair test of whether they followed the schema. Only the first complete
163
- * value is taken; anything before or after it is ignored.
164
- */
165
- export function extractJson(text) {
166
- const trimmed = text.trim();
167
- const fenced = /```(?:json)?\s*([\s\S]*?)```/.exec(trimmed);
168
- const candidates = [trimmed, fenced?.[1]?.trim()].filter((candidate) => Boolean(candidate));
169
- for (const candidate of candidates) {
170
- try {
171
- return JSON.parse(candidate);
172
- }
173
- catch {
174
- /* try to find a balanced value inside */
175
- }
176
- for (let start = 0; start < candidate.length; start++) {
177
- const opener = candidate[start];
178
- if (opener !== "{" && opener !== "[")
179
- continue;
180
- const closer = opener === "{" ? "}" : "]";
181
- let depth = 0;
182
- let inString = false;
183
- let escaped = false;
184
- for (let index = start; index < candidate.length; index++) {
185
- const char = candidate[index];
186
- if (inString) {
187
- if (escaped)
188
- escaped = false;
189
- else if (char === "\\")
190
- escaped = true;
191
- else if (char === '"')
192
- inString = false;
193
- continue;
194
- }
195
- if (char === '"')
196
- inString = true;
197
- else if (char === opener)
198
- depth++;
199
- else if (char === closer) {
200
- depth--;
201
- if (depth === 0) {
202
- try {
203
- return JSON.parse(candidate.slice(start, index + 1));
204
- }
205
- catch {
206
- break;
207
- }
208
- }
209
- }
210
- }
211
- }
212
- }
213
- return undefined;
214
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Close extension-owned resources before disposing an agent session.
3
- *
4
- * AgentSession.dispose() disconnects the agent itself, but extension resources
5
- * (including MCP transports) are released by the session_shutdown event. The
6
- * SDK exposes the runner so callers can deliver that lifecycle event even when
7
- * a session is replaced outside the interactive mode.
8
- *
9
- * The returned promise settles once the shutdown has been delivered and the
10
- * session is disposed. Callers must await it: dropping the promise leaves the
11
- * MCP processes and tool registrations alive after the configuration that
12
- * created them is gone.
13
- */
14
- export function disposeAgentSession(session) {
15
- return session.extensionRunner
16
- .emit({ type: "session_shutdown", reason: "quit" })
17
- .catch(() => undefined)
18
- .finally(() => session.dispose());
19
- }
@@ -1,111 +0,0 @@
1
- import { readdir, rmdir, stat, unlink } from "node:fs/promises";
2
- import { dirname, join, resolve } from "node:path";
3
- import { RETENTION_DAYS } from "./checkpoint.js";
4
- import { AGENT_DIR } from "./paths.js";
5
- /**
6
- * Unlink session files idle for longer than `RETENTION_DAYS`, across every
7
- * project directory — the store's whole problem is that it is per-cwd and
8
- * nothing ever looked outside the current one.
9
- *
10
- * The SDK writes `<agentDir>/sessions/--<encoded-cwd>--/<timestamp>_<id>.jsonl`
11
- * and never removes one: `SessionManager` only appends, the TUI's delete is a
12
- * single user-chosen session (and prefers `trash`), and the CLI had no sweep at
13
- * all, so a machine that uses the product for a year keeps a transcript of every
14
- * folder it was ever pointed at. Rewind's shadow store already sweeps at 30 days
15
- * (checkpoint.ts, `RETENTION_DAYS`) — same window here on purpose, so "old" means
16
- * one thing across both stores and a session whose snapshots are gone does not
17
- * linger as a transcript.
18
- *
19
- * Age is the file's mtime, not the timestamp in its name: a session resumed last
20
- * week was written last week and must survive, while its filename still says the
21
- * day it was created. `keep` is the stronger rule on top of that — `--continue`
22
- * and `/resume` exist to bring an old session back, so the file this process just
23
- * opened is kept whatever its age.
24
- *
25
- * Housekeeping, so it never throws and never reports to the user: every step is
26
- * per-file, an error only leaves the store larger than it needed to be. Files are
27
- * unlinked rather than trashed — the TUI's `trash` path is a person deleting one
28
- * session they chose, this is a bulk sweep they did not ask to watch.
29
- */
30
- export async function sweepStaleSessions(options = {}) {
31
- const result = { removed: [], failed: [], removedDirs: [] };
32
- const root = join(options.agentDir ?? AGENT_DIR, "sessions");
33
- const cutoff = (options.now ?? Date.now()) - RETENTION_DAYS * 24 * 60 * 60 * 1000;
34
- const keep = options.keep ? resolve(options.keep) : undefined;
35
- let projects;
36
- try {
37
- projects = await readdir(root, { withFileTypes: true });
38
- }
39
- catch {
40
- // No store, or an unreadable one: nothing to sweep and nothing to say.
41
- return result;
42
- }
43
- for (const project of projects) {
44
- if (!project.isDirectory())
45
- continue;
46
- const dir = join(root, project.name);
47
- let files;
48
- try {
49
- files = await readdir(dir);
50
- }
51
- catch {
52
- continue;
53
- }
54
- // What will still be in the directory when the sweep is done. Sidecars a
55
- // stale session left behind (`plan.md`, `plan_mode.json`) count and keep the
56
- // directory on purpose: they are project state a later session of the same
57
- // folder still restores.
58
- const surviving = files.filter((file) => !file.endsWith(".jsonl"));
59
- for (const file of files) {
60
- if (!file.endsWith(".jsonl"))
61
- continue;
62
- const path = join(dir, file);
63
- let stale;
64
- try {
65
- if (keep && resolve(path) === keep)
66
- stale = false;
67
- else {
68
- // mtime, not the timestamp in the name: a session resumed last week
69
- // was written last week, whatever its filename says.
70
- stale = (await stat(path)).mtimeMs < cutoff;
71
- }
72
- }
73
- catch {
74
- // Raced with another sweeper (two processes starting at once).
75
- stale = false;
76
- }
77
- if (!stale) {
78
- surviving.push(file);
79
- continue;
80
- }
81
- try {
82
- await unlink(path);
83
- result.removed.push(path);
84
- }
85
- catch {
86
- // A directory called `x.jsonl`, a permission wall, a file another
87
- // process holds oddly: count it and keep going.
88
- result.failed.push(path);
89
- surviving.push(file);
90
- }
91
- }
92
- // Drop the per-project directory when nothing is left in it, so the encoded
93
- // cwd names stop piling up too.
94
- if (surviving.length === 0) {
95
- // Never drop the directory the live session writes into. On a fresh start
96
- // the session file does not exist yet, so the directory looks empty and
97
- // the sweep removed it — the next prompt then failed with ENOENT because
98
- // the writer's parent had been deleted underneath it.
99
- if (keep && dirname(keep) === dir)
100
- continue;
101
- try {
102
- await rmdir(dir);
103
- result.removedDirs.push(dir);
104
- }
105
- catch {
106
- // Non-empty after all, or racing a writer: the directory stays.
107
- }
108
- }
109
- }
110
- return result;
111
- }