docks-kit 0.17.0 → 0.17.2

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 (84) hide show
  1. package/AGENTS.md +37 -33
  2. package/README.md +1 -0
  3. package/cli/docs/omp-models.md +114 -58
  4. package/cli/src/argv.ts +38 -469
  5. package/cli/src/argvSurface.ts +371 -0
  6. package/cli/src/argvValidate.ts +122 -0
  7. package/cli/src/commands/docs.ts +57 -42
  8. package/cli/src/commands/harnesses.ts +38 -45
  9. package/cli/src/commands/model.ts +48 -53
  10. package/cli/src/commands/models.ts +24 -26
  11. package/cli/src/commands/omp.ts +178 -88
  12. package/cli/src/commands/plugins.ts +20 -20
  13. package/cli/src/commands/skills.ts +22 -20
  14. package/cli/src/commands/status.ts +87 -80
  15. package/cli/src/commands/sync.ts +113 -87
  16. package/cli/src/commands/toolchain.ts +21 -21
  17. package/cli/src/commands/update.ts +139 -117
  18. package/cli/src/efforts.ts +35 -34
  19. package/cli/src/engine-native/DESIGN.md +30 -30
  20. package/cli/src/engine-native/bun.ts +77 -55
  21. package/cli/src/engine-native/claudeLsp.ts +154 -0
  22. package/cli/src/engine-native/claudeOptionalPlugins.ts +113 -0
  23. package/cli/src/engine-native/claudePluginPasses.ts +348 -0
  24. package/cli/src/engine-native/claudeRemovals.ts +195 -0
  25. package/cli/src/engine-native/claudeRetired.ts +4 -4
  26. package/cli/src/engine-native/claudeRuntime.ts +94 -68
  27. package/cli/src/engine-native/claudeSettings.ts +174 -0
  28. package/cli/src/engine-native/claudeSettingsModifiers.ts +50 -54
  29. package/cli/src/engine-native/claudeSync.ts +176 -456
  30. package/cli/src/engine-native/codexConfig.ts +158 -0
  31. package/cli/src/engine-native/codexHooks.ts +91 -0
  32. package/cli/src/engine-native/codexPlugins.ts +290 -0
  33. package/cli/src/engine-native/codexStatus.ts +24 -0
  34. package/cli/src/engine-native/codexSync.ts +110 -568
  35. package/cli/src/engine-native/codexToml.ts +140 -138
  36. package/cli/src/engine-native/deps.ts +144 -107
  37. package/cli/src/engine-native/engineCtx.ts +126 -0
  38. package/cli/src/engine-native/exec.ts +98 -87
  39. package/cli/src/engine-native/failures.ts +3 -3
  40. package/cli/src/engine-native/harnesses.ts +62 -72
  41. package/cli/src/engine-native/index.ts +34 -315
  42. package/cli/src/engine-native/jq.ts +25 -24
  43. package/cli/src/engine-native/logger.ts +98 -100
  44. package/cli/src/engine-native/models.ts +50 -45
  45. package/cli/src/engine-native/modes.ts +83 -80
  46. package/cli/src/engine-native/ompFileDeploy.ts +111 -0
  47. package/cli/src/engine-native/ompMarketplace.ts +136 -0
  48. package/cli/src/engine-native/ompOverlay.ts +93 -53
  49. package/cli/src/engine-native/ompPaths.ts +49 -38
  50. package/cli/src/engine-native/ompPlugins.ts +170 -0
  51. package/cli/src/engine-native/ompSync.ts +64 -408
  52. package/cli/src/engine-native/ompYaml.ts +43 -41
  53. package/cli/src/engine-native/os/darwin.ts +5 -5
  54. package/cli/src/engine-native/os/index.ts +15 -15
  55. package/cli/src/engine-native/os/linux.ts +5 -5
  56. package/cli/src/engine-native/os/posix.ts +28 -24
  57. package/cli/src/engine-native/os/targets.ts +17 -17
  58. package/cli/src/engine-native/os/types.ts +31 -31
  59. package/cli/src/engine-native/os/windows.ts +61 -61
  60. package/cli/src/engine-native/parseArgs.ts +122 -372
  61. package/cli/src/engine-native/parseHelp.ts +66 -0
  62. package/cli/src/engine-native/parseModifiers.ts +222 -0
  63. package/cli/src/engine-native/services.ts +34 -34
  64. package/cli/src/engine-native/settings.ts +15 -15
  65. package/cli/src/engine-native/sharedTypes.d.ts +46 -0
  66. package/cli/src/engine-native/skillsInstall.ts +105 -0
  67. package/cli/src/engine-native/skillsLinks.ts +203 -0
  68. package/cli/src/engine-native/skillsManifest.ts +16 -0
  69. package/cli/src/engine-native/skillsPrune.ts +108 -0
  70. package/cli/src/engine-native/skillsSync.ts +28 -362
  71. package/cli/src/engine-native/syncConcurrency.ts +55 -0
  72. package/cli/src/engine-native/syncDispatch.ts +141 -0
  73. package/cli/src/engine-native/toolchain.ts +65 -62
  74. package/cli/src/engine.ts +65 -57
  75. package/cli/src/generated/sotPayload.ts +7 -7
  76. package/cli/src/kitHome.ts +44 -40
  77. package/cli/src/main.ts +63 -56
  78. package/cli/src/manifests.ts +53 -54
  79. package/cli/src/md.d.ts +2 -2
  80. package/cli/src/payload.ts +9 -9
  81. package/cli/src/services.ts +21 -13
  82. package/cli/tsconfig.json +4 -1
  83. package/package.json +9 -2
  84. package/cli/src/engine-native/claudePlugins.ts +0 -510
@@ -1,4 +1,4 @@
1
- import { AsyncLocalStorage } from "node:async_hooks"
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
2
 
3
3
  /**
4
4
  * Leveled stderr logger, one run-scoped terminal lease, and stdout data
@@ -10,43 +10,42 @@ import { AsyncLocalStorage } from "node:async_hooks"
10
10
  */
11
11
  export interface TerminalLease {
12
12
  /** Replace the coordinator-owned transient line. */
13
- readonly update: (message: string) => void
13
+ readonly update: (message: string) => void;
14
14
  /** Serialize terminal input owners and suspend transient redraw while held. */
15
- readonly withExclusive: <T>(action: () => T | Promise<T>) => Promise<T>
15
+ readonly withExclusive: <T>(action: () => T | Promise<T>) => Promise<T>;
16
16
  /** Clear coordinator progress and return ownership to ordinary progress calls. */
17
- readonly release: () => void
17
+ readonly release: () => void;
18
18
  }
19
19
 
20
-
21
20
  export interface Logger {
22
21
  /** `[ok]` green — an operation actually mutated something. Always visible. */
23
- readonly change: (msg: string) => void
22
+ readonly change: (msg: string) => void;
24
23
  /** Dim, transient single-line status for blocking work. */
25
- readonly progress: (msg: string) => void
24
+ readonly progress: (msg: string) => void;
26
25
  /** Erase a pending transient status line. */
27
- readonly clearProgress: () => void
26
+ readonly clearProgress: () => void;
28
27
  /** `[ok]` green — status-quo confirmation; visible only with verbosity on. */
29
- readonly verbose: (msg: string) => void
30
- readonly warn: (msg: string) => void
31
- readonly err: (msg: string) => void
28
+ readonly verbose: (msg: string) => void;
29
+ readonly warn: (msg: string) => void;
30
+ readonly err: (msg: string) => void;
32
31
  /** stdout data line (dry-run report, summary, usage) — never filtered. */
33
- readonly echo: (line: string) => void
32
+ readonly echo: (line: string) => void;
34
33
  /** Acquire the run-scoped coordinator lease for terminal progress and input. */
35
- readonly acquireTerminal: (message: string) => TerminalLease
34
+ readonly acquireTerminal: (message: string) => TerminalLease;
36
35
  }
37
36
 
38
37
  export interface LoggerSinks {
39
- readonly stderr?: (chunk: string) => void
40
- readonly progress?: (chunk: string) => void
41
- readonly stdout?: (chunk: string) => void
38
+ readonly stderr?: (chunk: string) => void;
39
+ readonly progress?: (chunk: string) => void;
40
+ readonly stdout?: (chunk: string) => void;
42
41
  }
43
42
 
44
43
  interface WritableStreamLike {
45
- write: (chunk: string) => unknown
46
- on?: (event: "error", listener: (error: unknown) => void) => unknown
44
+ write: (chunk: string) => unknown;
45
+ on?: (event: "error", listener: (error: unknown) => void) => unknown;
47
46
  }
48
47
 
49
- const epipeGuarded = new WeakSet<WritableStreamLike>()
48
+ const epipeGuarded = new WeakSet<WritableStreamLike>();
50
49
 
51
50
  /**
52
51
  * A downstream reader may close the pipe early (`docks-kit toolchain check |
@@ -55,144 +54,143 @@ const epipeGuarded = new WeakSet<WritableStreamLike>()
55
54
  */
56
55
  export function writeIgnoringEpipe(stream: WritableStreamLike, chunk: string): void {
57
56
  if (!epipeGuarded.has(stream)) {
58
- epipeGuarded.add(stream)
57
+ epipeGuarded.add(stream);
59
58
  stream.on?.("error", (error) => {
60
- if ((error as NodeJS.ErrnoException | null)?.code !== "EPIPE") throw error
61
- })
59
+ if ((error as NodeJS.ErrnoException | null)?.code !== "EPIPE") throw error;
60
+ });
62
61
  }
63
62
  try {
64
- stream.write(chunk)
63
+ stream.write(chunk);
65
64
  } catch (error) {
66
- if ((error as NodeJS.ErrnoException | null)?.code !== "EPIPE") throw error
65
+ if ((error as NodeJS.ErrnoException | null)?.code !== "EPIPE") throw error;
67
66
  }
68
67
  }
69
68
 
70
69
  export function makeLogger(sinks: LoggerSinks): Logger {
71
- const errWrite = sinks.stderr ?? ((chunk: string) => writeIgnoringEpipe(process.stderr, chunk))
72
- const outWrite = sinks.stdout ?? ((chunk: string) => writeIgnoringEpipe(process.stdout, chunk))
70
+ const errWrite = sinks.stderr ?? ((chunk: string) => writeIgnoringEpipe(process.stderr, chunk));
71
+ const outWrite = sinks.stdout ?? ((chunk: string) => writeIgnoringEpipe(process.stdout, chunk));
73
72
  const progressWrite =
74
73
  sinks.progress ??
75
74
  (sinks.stderr === undefined && process.stderr.isTTY === true
76
75
  ? (chunk: string) => writeIgnoringEpipe(process.stderr, chunk)
77
- : undefined)
78
- let progressPending = false
79
- let activeLease: TerminalLease | undefined
80
- let exclusiveActive = false
81
- const exclusiveContext = new AsyncLocalStorage<{ active: boolean }>()
82
- const durableBuffer: Array<() => void> = []
83
-
76
+ : undefined);
77
+ let progressPending = false;
78
+ let activeLease: TerminalLease | undefined;
79
+ let exclusiveActive = false;
80
+ const exclusiveContext = new AsyncLocalStorage<{ active: boolean }>();
81
+ const durableBuffer: Array<() => void> = [];
84
82
 
85
83
  const eraseProgress = (): void => {
86
- if (!progressPending || progressWrite === undefined) return
87
- progressWrite("\r\x1b[2K")
88
- progressPending = false
89
- }
84
+ if (!progressPending || progressWrite === undefined) return;
85
+ progressWrite("\r\x1b[2K");
86
+ progressPending = false;
87
+ };
90
88
  const drawProgress = (message: string): void => {
91
- if (progressWrite === undefined) return
92
- progressWrite(`\r\x1b[2K\x1b[2m${message}\x1b[0m`)
93
- progressPending = true
94
- }
89
+ if (progressWrite === undefined) return;
90
+ progressWrite(`\r\x1b[2K\x1b[2m${message}\x1b[0m`);
91
+ progressPending = true;
92
+ };
95
93
  const clearProgress = (): void => {
96
- if (activeLease !== undefined) return
97
- eraseProgress()
98
- }
94
+ if (activeLease !== undefined) return;
95
+ eraseProgress();
96
+ };
99
97
  const writeDurable = (write: () => void): void => {
100
98
  if (exclusiveActive) {
101
- durableBuffer.push(write)
102
- return
99
+ durableBuffer.push(write);
100
+ return;
103
101
  }
104
- eraseProgress()
105
- write()
106
- }
102
+ eraseProgress();
103
+ write();
104
+ };
107
105
  const flushDurable = (): void => {
108
- let firstError: unknown
106
+ let firstError: unknown;
109
107
  while (durableBuffer.length > 0) {
110
108
  for (const write of durableBuffer.splice(0)) {
111
109
  try {
112
- write()
110
+ write();
113
111
  } catch (error) {
114
- firstError ??= error
112
+ firstError ??= error;
115
113
  }
116
114
  }
117
115
  }
118
- if (firstError !== undefined) throw firstError
119
- }
116
+ if (firstError !== undefined) throw firstError;
117
+ };
120
118
  const ok = (msg: string): void => {
121
- writeDurable(() => errWrite(`\x1b[1;32m[ok]\x1b[0m ${msg}\n`))
122
- }
119
+ writeDurable(() => errWrite(`\x1b[1;32m[ok]\x1b[0m ${msg}\n`));
120
+ };
123
121
 
124
122
  const acquireTerminal = (message: string): TerminalLease => {
125
- if (activeLease !== undefined) throw new Error("terminal lease already acquired")
123
+ if (activeLease !== undefined) throw new Error("terminal lease already acquired");
126
124
 
127
- let released = false
128
- let coordinatorMessage = message
129
- let exclusiveTail = Promise.resolve()
130
- let exclusivePending = 0
125
+ let released = false;
126
+ let coordinatorMessage = message;
127
+ let exclusiveTail = Promise.resolve();
128
+ let exclusivePending = 0;
131
129
  const lease: TerminalLease = {
132
130
  update: (nextMessage) => {
133
- if (released) return
134
- coordinatorMessage = nextMessage
135
- if (exclusivePending === 0) drawProgress(coordinatorMessage)
131
+ if (released) return;
132
+ coordinatorMessage = nextMessage;
133
+ if (exclusivePending === 0) drawProgress(coordinatorMessage);
136
134
  },
137
135
  withExclusive: async <T>(action: () => T | Promise<T>): Promise<T> => {
138
136
  if (exclusiveContext.getStore()?.active === true) {
139
- throw new Error("terminal lease withExclusive cannot be re-entered")
137
+ throw new Error("terminal lease withExclusive cannot be re-entered");
140
138
  }
141
- if (released) return await action()
142
- exclusivePending += 1
143
- const previous = exclusiveTail
144
- let unlock!: () => void
139
+ if (released) return await action();
140
+ exclusivePending += 1;
141
+ const previous = exclusiveTail;
142
+ let unlock!: () => void;
145
143
  exclusiveTail = new Promise<void>((resolve) => {
146
- unlock = resolve
147
- })
148
- await previous
149
- eraseProgress()
150
- exclusiveActive = true
151
- const owner = { active: true }
144
+ unlock = resolve;
145
+ });
146
+ await previous;
147
+ eraseProgress();
148
+ exclusiveActive = true;
149
+ const owner = { active: true };
152
150
  try {
153
- return await exclusiveContext.run(owner, action)
151
+ return await exclusiveContext.run(owner, action);
154
152
  } finally {
155
- owner.active = false
153
+ owner.active = false;
156
154
  try {
157
- flushDurable()
155
+ flushDurable();
158
156
  } finally {
159
- exclusiveActive = false
160
- exclusivePending -= 1
161
- unlock()
162
- if (!released && exclusivePending === 0) drawProgress(coordinatorMessage)
157
+ exclusiveActive = false;
158
+ exclusivePending -= 1;
159
+ unlock();
160
+ if (!released && exclusivePending === 0) drawProgress(coordinatorMessage);
163
161
  }
164
162
  }
165
163
  },
166
164
  release: () => {
167
- if (released) return
168
- released = true
169
- if (activeLease === lease) activeLease = undefined
170
- eraseProgress()
171
- }
172
- }
173
- activeLease = lease
174
- drawProgress(coordinatorMessage)
175
- return lease
176
- }
165
+ if (released) return;
166
+ released = true;
167
+ if (activeLease === lease) activeLease = undefined;
168
+ eraseProgress();
169
+ },
170
+ };
171
+ activeLease = lease;
172
+ drawProgress(coordinatorMessage);
173
+ return lease;
174
+ };
177
175
 
178
176
  return {
179
177
  change: ok,
180
178
  verbose: ok,
181
179
  progress: (msg) => {
182
- if (activeLease !== undefined) return
183
- drawProgress(msg)
180
+ if (activeLease !== undefined) return;
181
+ drawProgress(msg);
184
182
  },
185
183
  clearProgress,
186
184
  warn: (msg) => {
187
- writeDurable(() => errWrite(`\x1b[1;33m[warn]\x1b[0m ${msg}\n`))
185
+ writeDurable(() => errWrite(`\x1b[1;33m[warn]\x1b[0m ${msg}\n`));
188
186
  },
189
187
  err: (msg) => {
190
- eraseProgress()
191
- errWrite(`\x1b[1;31m[err]\x1b[0m ${msg}\n`)
188
+ eraseProgress();
189
+ errWrite(`\x1b[1;31m[err]\x1b[0m ${msg}\n`);
192
190
  },
193
191
  echo: (line) => {
194
- writeDurable(() => outWrite(`${line}\n`))
192
+ writeDurable(() => outWrite(`${line}\n`));
195
193
  },
196
- acquireTerminal
197
- }
194
+ acquireTerminal,
195
+ };
198
196
  }
@@ -2,31 +2,32 @@
2
2
  * Model-catalog helpers: manifest listing plus Claude/Codex model validation.
3
3
  * Message strings are covered by the golden suites.
4
4
  */
5
- import type { Ctx } from "./index"
6
- import { isObject, parseJson, type Json } from "./jq"
7
- import { payloadDisplayPath, payloadText } from "../payload"
5
+ import type { Ctx } from "./index";
6
+ import { isObject, parseJson } from "./jq";
7
+ import { payloadDisplayPath, payloadText } from "../payload";
8
+ import type { JsonObject } from "./sharedTypes";
8
9
 
9
10
  export interface ModelEntry {
10
- readonly id: string
11
- readonly kind: "alias" | "id"
12
- readonly note?: string
11
+ readonly id: string;
12
+ readonly kind: "alias" | "id";
13
+ readonly note?: string;
13
14
  }
14
15
 
15
16
  export interface ModelCatalog {
16
- readonly verified: string
17
- readonly models: ReadonlyArray<ModelEntry>
17
+ readonly verified: string;
18
+ readonly models: ReadonlyArray<ModelEntry>;
18
19
  }
19
20
 
20
- function toolEntry(tool: string): { [k: string]: Json } | undefined {
21
- const doc = parseJson(payloadText("SoT/models.json"))
22
- if (doc === undefined || !isObject(doc)) return undefined
23
- const entry = doc[tool]
24
- return entry !== undefined && isObject(entry) ? entry : undefined
21
+ function toolEntry(tool: string): JsonObject | undefined {
22
+ const doc = parseJson(payloadText("SoT/models.json"));
23
+ if (doc === undefined || !isObject(doc)) return undefined;
24
+ const entry = doc[tool];
25
+ return entry !== undefined && isObject(entry) ? entry : undefined;
25
26
  }
26
27
 
27
- function modelEntries(entry: { [k: string]: Json } | undefined): Array<{ [k: string]: Json }> {
28
- const models = entry?.["models"]
29
- return Array.isArray(models) ? models.filter(isObject) : []
28
+ function modelEntries(entry: JsonObject | undefined): Array<JsonObject> {
29
+ const models = entry?.["models"];
30
+ return Array.isArray(models) ? models.filter(isObject) : [];
30
31
  }
31
32
 
32
33
  /**
@@ -35,53 +36,57 @@ function modelEntries(entry: { [k: string]: Json } | undefined): Array<{ [k: str
35
36
  * yields `verified: "?"` and no models.
36
37
  */
37
38
  export function modelCatalog(tool: string): ModelCatalog {
38
- const entry = toolEntry(tool)
39
- const verified = entry?.["verified"]
40
- const models: Array<ModelEntry> = []
39
+ const entry = toolEntry(tool);
40
+ const verified = entry?.["verified"];
41
+ const models: Array<ModelEntry> = [];
41
42
  for (const m of modelEntries(entry)) {
42
- const id = m["id"]
43
- const kind = m["kind"]
44
- if (typeof id !== "string" || (kind !== "alias" && kind !== "id")) continue
45
- const note = m["note"]
46
- models.push(typeof note === "string" ? { id, kind, note } : { id, kind })
43
+ const id = m["id"];
44
+ const kind = m["kind"];
45
+ if (typeof id !== "string" || (kind !== "alias" && kind !== "id")) continue;
46
+ const note = m["note"];
47
+ models.push(typeof note === "string" ? { id, kind, note } : { id, kind });
47
48
  }
48
- return { verified: typeof verified === "string" ? verified : "?", models }
49
+ return { verified: typeof verified === "string" ? verified : "?", models };
49
50
  }
50
51
 
51
52
  export function printModels(ctx: Ctx, tool: string): void {
52
- const { echo, warn } = ctx.services.logger
53
- const entry = toolEntry(tool)
53
+ const { echo, warn } = ctx.services.logger;
54
+ const entry = toolEntry(tool);
54
55
  if (entry === undefined) {
55
- warn(`Model catalog unavailable (${payloadDisplayPath("SoT/models.json")})`)
56
- return
56
+ warn(`Model catalog unavailable (${payloadDisplayPath("SoT/models.json")})`);
57
+ return;
57
58
  }
58
- const verified = typeof entry["verified"] === "string" ? entry["verified"] : "?"
59
- const lines = [`Available ${tool} models (kit-verified ${verified} — SoT/models.json):`]
59
+ const verified = typeof entry["verified"] === "string" ? entry["verified"] : "?";
60
+ const lines = [`Available ${tool} models (kit-verified ${verified} — SoT/models.json):`];
60
61
  for (const m of modelEntries(entry)) {
61
- const note = typeof m["note"] === "string" ? ` — ${m["note"]}` : ""
62
- lines.push(` ${String(m["id"] ?? "")}${note}`)
62
+ const note = typeof m["note"] === "string" ? ` — ${m["note"]}` : "";
63
+ lines.push(` ${String(m["id"] ?? "")}${note}`);
63
64
  }
64
- if (tool === "claude") lines.push(" (full claude-* model IDs outside the catalog are accepted with a warning)")
65
- if (tool === "codex") lines.push(" (well-formed IDs outside the catalog are accepted with a warning)")
66
- for (const line of lines) echo(line)
65
+ if (tool === "claude")
66
+ lines.push(" (full claude-* model IDs outside the catalog are accepted with a warning)");
67
+ if (tool === "codex")
68
+ lines.push(" (well-formed IDs outside the catalog are accepted with a warning)");
69
+ for (const line of lines) echo(line);
67
70
  }
68
71
 
69
72
  export function validateClaudeModel(ctx: Ctx, m: string): boolean {
70
- if (m === "") return false
71
- if (modelCatalog("claude").models.some((entry) => entry.id === m)) return true
73
+ if (m === "") return false;
74
+ if (modelCatalog("claude").models.some((entry) => entry.id === m)) return true;
72
75
  if (m.startsWith("claude-")) {
73
- ctx.services.logger.warn(`Claude model '${m}' is not in the kit-verified catalog (SoT/models.json) — applying anyway`)
74
- return true
76
+ ctx.services.logger.warn(
77
+ `Claude model '${m}' is not in the kit-verified catalog (SoT/models.json) — applying anyway`,
78
+ );
79
+ return true;
75
80
  }
76
- return false
81
+ return false;
77
82
  }
78
83
 
79
84
  export function validateCodexModel(ctx: Ctx, m: string): boolean {
80
- if (!/^[A-Za-z0-9._-]+$/.test(m)) return false
85
+ if (!/^[A-Za-z0-9._-]+$/.test(m)) return false;
81
86
  if (!modelCatalog("codex").models.some((entry) => entry.id === m)) {
82
87
  ctx.services.logger.warn(
83
- `Codex model '${m}' is not in the kit-verified catalog (SoT/models.json) — applying anyway (check ~/.codex/config.toml if Codex rejects it)`
84
- )
88
+ `Codex model '${m}' is not in the kit-verified catalog (SoT/models.json) — applying anyway (check ~/.codex/config.toml if Codex rejects it)`,
89
+ );
85
90
  }
86
- return true
91
+ return true;
87
92
  }