@nodii/dev 0.6.34 → 0.6.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -8
- package/dist/api.js +6 -0
- package/dist/cli.js +57 -9
- package/dist/core.js +1 -1
- package/dist/devops-openapi.json +1 -1
- package/dist/freeze.js +38 -15
- package/dist/gather.js +105 -9
- package/dist/hooks.js +6 -2
- package/dist/lanes.js +73 -11
- package/dist/remote.js +281 -0
- package/dist/runs.js +41 -7
- package/dist/starting.js +24 -11
- package/dist/upload.js +15 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,18 +131,21 @@ nodii-dev decisions create|lock|supersede|amend
|
|
|
131
131
|
|
|
132
132
|
nodii-dev lane gather [KEY] [--delta] [--objective TEXT] [--done-check TEXT]
|
|
133
133
|
[--paths A,B] [--components K,L]
|
|
134
|
+
nodii-dev lane gather show [KEY] [--gather ID]
|
|
134
135
|
nodii-dev lane freeze add KEY --section SECTION --file ITEM.json --reason TEXT
|
|
135
136
|
nodii-dev lane freeze drop KEY --section SECTION --item ID --reason TEXT
|
|
136
137
|
nodii-dev lane freeze swap KEY --section SECTION [--item ID] --file VALUE.json --reason TEXT
|
|
137
138
|
nodii-dev lane freeze show KEY
|
|
138
139
|
nodii-dev lane freeze history KEY
|
|
139
140
|
nodii-dev rules find "QUESTION" [--limit N]
|
|
141
|
+
nodii-dev rules show CLAUSE_ID
|
|
140
142
|
nodii-dev gather tune cases|runs
|
|
141
143
|
nodii-dev gather tune replay CASE_ID
|
|
142
144
|
nodii-dev gather tune start --cases all|ID,ID --corpus-ref REF [--trigger T] [--settings JSON]
|
|
143
145
|
nodii-dev gather tune exec RUN_ID [--pickers shortlist-only,gemma-e4b,gemma-12b,gemma-26b]
|
|
144
146
|
nodii-dev gather tune trial RUN_ID --case ID --picker P --iteration N [--documents A,B]
|
|
145
147
|
nodii-dev gather tune finalize RUN_ID
|
|
148
|
+
nodii-dev gather timings [--model M] [--last N]
|
|
146
149
|
|
|
147
150
|
nodii-dev open-questions list|show|answer
|
|
148
151
|
nodii-dev feature-docs list|show|claim|release|status
|
|
@@ -152,7 +155,8 @@ nodii-dev libraries register-version LIBRARY_ID --version VERSION
|
|
|
152
155
|
nodii-dev state diff
|
|
153
156
|
nodii-dev heartbeat audit [SERVICE]
|
|
154
157
|
|
|
155
|
-
nodii-dev run [--kind build|test_run|subagent|deploy] [--name TEXT] -- COMMAND [ARGS...]
|
|
158
|
+
nodii-dev run [--kind build|test_run|subagent|deploy] [--name TEXT] [--artifact PATH] -- COMMAND [ARGS...]
|
|
159
|
+
nodii-dev run --remote-ssm INSTANCE SCRIPT [--artifact PATH] [--quiet-minutes N] [--poll-seconds N] [--region R]
|
|
156
160
|
|
|
157
161
|
nodii-dev design entries [--kind KIND] [--group GROUP] [--q TEXT]
|
|
158
162
|
nodii-dev design entry KEY
|
|
@@ -369,7 +373,7 @@ nodii-dev rulebook diff CODE [--from V] [--to V]
|
|
|
369
373
|
nodii-dev docs check PATH... # local M-05 checks only
|
|
370
374
|
nodii-dev docs validate PATH... --class CLASS # Dev's dry run of the upload
|
|
371
375
|
nodii-dev docs upload PATH... --class ruling|conformance|editorial
|
|
372
|
-
[--base CODE=VERSION ...] [--decision DECISION.json]
|
|
376
|
+
[--base CODE=VERSION ...] [--decision DECISION.json]
|
|
373
377
|
[--conformance-ref PR|REPO@SHA] [--meaning-unchanged REASON]
|
|
374
378
|
[--wait [--wait-minutes N]]
|
|
375
379
|
nodii-dev docs ratify --domain KEY [--domain KEY ...] --decision DECISION.json [--wait]
|
|
@@ -404,7 +408,13 @@ changes, production-secret/test-auth bypasses, cleanup of Docker resources the
|
|
|
404
408
|
run did not create, and deploy/apply commands without an exact grant. Allowed
|
|
405
409
|
calls produce no output. Codex receives runtime-native `Bash` and `apply_patch`
|
|
406
410
|
matchers, JSON denials, and `additionalContext` nudges. A compact session start
|
|
407
|
-
prints the current lane Freeze again.
|
|
411
|
+
prints the current lane Freeze again, with how to fetch its full Clause map.
|
|
412
|
+
|
|
413
|
+
The Freeze pins only the ⚑ (counter-instinct) clauses, in full. Every other
|
|
414
|
+
Gather clause stays in the Clause map, which the Freeze references by Gather
|
|
415
|
+
id, listing one-line gists in rank order up to the 1,500-token cap ("+N more
|
|
416
|
+
in Clause map"). `lane gather show` prints the whole Clause map and
|
|
417
|
+
`rules show <ID>` prints one clause in full.
|
|
408
418
|
|
|
409
419
|
Hard blocks apply only after Dev proves the current agent, branch and worktree
|
|
410
420
|
belong to an active lane. Interactive or otherwise unproven sessions receive
|
|
@@ -612,10 +622,9 @@ Dev's error codes, and nothing is sent until there are none. Dev then runs the
|
|
|
612
622
|
same checks, plus the ones that need its data, in one transaction.
|
|
613
623
|
|
|
614
624
|
- `--class` is required on every write (M05-8). A `ruling` carries its
|
|
615
|
-
decision (`--decision`, with `amends`)
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
requests the staff-only immediate lock-and-amend action. An `editorial`
|
|
625
|
+
decision (`--decision`, with `amends`), and the decision locks as the change
|
|
626
|
+
lands (DEV-DEC-AS-COMMIT-1). `--pending` is still accepted but does nothing:
|
|
627
|
+
the CLI prints "decisions lock on upload" and doesn't send it. An `editorial`
|
|
619
628
|
write that changes a Rules clause is refused unless
|
|
620
629
|
`--meaning-unchanged REASON` is given (M05-10).
|
|
621
630
|
- A new document is based on nothing. For a document Dev already has, pass
|
|
@@ -783,6 +792,41 @@ their output may be swallowed; the next visible call prints and acknowledges
|
|
|
783
792
|
them. Unacknowledged amendments will join this preflight when the amendment API
|
|
784
793
|
from AGENT-HARNESS-14 is available.
|
|
785
794
|
|
|
795
|
+
### Result artifacts
|
|
796
|
+
|
|
797
|
+
A run that succeeds can attach one text artifact, such as a benchmark table as
|
|
798
|
+
JSON: `--artifact PATH`. It reaches the waiter whole, as the Result's
|
|
799
|
+
`artifact` evidence item. The note is the content, redacted like the log
|
|
800
|
+
tail. The ref is `NAME · BYTES bytes · sha256:HEX`. Dev keeps at most 10,000
|
|
801
|
+
characters in a note, so an artifact that is missing, empty or larger fails the
|
|
802
|
+
run (`Artifact not attached: …`). It never arrives cut.
|
|
803
|
+
|
|
804
|
+
### Remote runs over SSM
|
|
805
|
+
|
|
806
|
+
`nodii-dev run --remote-ssm INSTANCE SCRIPT` runs a local shell script on an EC2
|
|
807
|
+
instance through SSM (`AWS-RunShellScript`), using your own `aws` CLI
|
|
808
|
+
credentials (`--region` passes through). It is a watched run like a local one.
|
|
809
|
+
It registers with `NODII_DEV_RUN_ID` as its waiter, heartbeats on every poll,
|
|
810
|
+
and ends with the exit code, the remote log tail and, on success, the artifact
|
|
811
|
+
(`--artifact` is a path on the instance, relative to the run directory).
|
|
812
|
+
|
|
813
|
+
The script runs detached on the instance in its own session, from
|
|
814
|
+
`/var/tmp/nodii-dev-runs/RUN_ID`, writing a log and then an exit-code file
|
|
815
|
+
there. Every `--poll-seconds` (default 30), a short SSM command reads the log's
|
|
816
|
+
size and tail and the exit code, and checks whether the process is alive. SSM
|
|
817
|
+
keeps only the first 24,000 characters of a command's output, so the script's
|
|
818
|
+
own invocation can't show progress. The run fails on:
|
|
819
|
+
|
|
820
|
+
- a non-zero exit;
|
|
821
|
+
- a process that is gone with no exit code (killed, or the instance restarted);
|
|
822
|
+
- a missing run directory;
|
|
823
|
+
- no new output, or no answer from the instance, for `--quiet-minutes`
|
|
824
|
+
(default 10).
|
|
825
|
+
|
|
826
|
+
A quiet script is cancelled with its whole process group. A long job should
|
|
827
|
+
print progress. Scripts are limited to 32 KB; copy larger code to the instance
|
|
828
|
+
first.
|
|
829
|
+
|
|
786
830
|
## Build lanes and repository setup
|
|
787
831
|
|
|
788
832
|
`coordinator start --machine NAME` registers the machine's one watched
|
|
@@ -800,7 +844,10 @@ target agent and machine, fresh account-capacity telemetry, repository grants,
|
|
|
800
844
|
lane limit, open issues and (when `--figma` is present) the authenticated Figma
|
|
801
845
|
account. Only after that passes does the CLI create one worktree per repository,
|
|
802
846
|
atomically register the lane and watched run, and launch the runtime with the
|
|
803
|
-
single-line brief `You are lane KEY. Run nodii-dev lane gather.`.
|
|
847
|
+
single-line brief `You are lane KEY. Run nodii-dev lane gather.`. It
|
|
848
|
+
dispatches an agent only onto a started lane: if Dev registers the lane as
|
|
849
|
+
anything but `building` (its start recorded), the CLI writes no marker, starts
|
|
850
|
+
no runtime, records the launch failure, and exits `LANE_NOT_STARTED`. Ordinary
|
|
804
851
|
notes use `--notes`; a scope-narrowing note uses `--narrowing-note` and must
|
|
805
852
|
also name the remainder's destination with `--narrowing-remainder`.
|
|
806
853
|
The launched process uses the already-provisioned lowercase identity (for
|
|
@@ -838,6 +885,19 @@ acknowledge a changed Freeze before continuing, and compact SessionStart uses
|
|
|
838
885
|
the same backstop. `lane freeze add|drop|swap` makes a reasoned, version-checked
|
|
839
886
|
change; `show|history` reads the current contract or its append-only history.
|
|
840
887
|
|
|
888
|
+
A lane Gather warms the local picker (Gemma) as it starts, alongside Dev's
|
|
889
|
+
requests. Dev's requests share a 60 s deadline. The deadline stops while the
|
|
890
|
+
pick runs: the pick waits for the warm-up (up to 180 s), then the first pick
|
|
891
|
+
has 120 s once the model is warm (`PICKER_TIMEOUT` past it, and the model is
|
|
892
|
+
unloaded). Each pick is logged on this Mac (`~/.cache/nodii-dev/gather-timings.jsonl`,
|
|
893
|
+
or `NODII_DEV_GATHER_TIMINGS`). Gather prints the pick's warm-up and pick time
|
|
894
|
+
with this Mac's p50/p95, and `gather timings` prints the spread.
|
|
895
|
+
If this Mac has no picker (the model isn't installed, or no Ollama answers),
|
|
896
|
+
Gather falls back to the agent picker on the same shortlist. It prints
|
|
897
|
+
`picker: agent (gemma4:12b not installed; run nodii-dev setup)` and the
|
|
898
|
+
shortlist, then the agent records its pick with `--picker agent --shortlist ID
|
|
899
|
+
--documents …`. A wrong model digest or a timeout still fails.
|
|
900
|
+
|
|
841
901
|
`lane start` creates and starts a lane. It infers the repository (by short
|
|
842
902
|
name, as Dev compares it), branch and worktree from git unless overridden, and resolves `--issue` keys to the UUIDs
|
|
843
903
|
required by Dev. Lane keys are passed directly to every lane and Built
|
package/dist/api.js
CHANGED
|
@@ -162,6 +162,12 @@ export const ALIASES = {
|
|
|
162
162
|
|
|
163
163
|
// Decisions a person makes in Dev (operator authority): nodii-dev never sends them.
|
|
164
164
|
export const PERSON_ONLY = new Set(["approveDesignGuidelineChangeSet", "rejectDesignGuidelineChangeSet", "mergeDesignRelease"]);
|
|
165
|
+
// Signed-in staff only: Dev answers an agent with OPERATOR_REQUIRED by design.
|
|
166
|
+
// nodii-dev still sends them, for a person signed in to the CLI.
|
|
167
|
+
export const STAFF_ONLY = new Map([
|
|
168
|
+
["ratifyAdDocument", "staff only: ratify on the document's Rules record page; an agent gets OPERATOR_REQUIRED"],
|
|
169
|
+
]);
|
|
170
|
+
|
|
165
171
|
export function refusePersonOnly(operationId) {
|
|
166
172
|
if (PERSON_ONLY.has(operationId))
|
|
167
173
|
throw new CliError("PERSON_ONLY", `${operationId} is a person's decision in Dev; nodii-dev does not send it.`, 2);
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
2
3
|
import { stdin, stdout } from "node:process";
|
|
3
4
|
import {
|
|
4
5
|
CliError,
|
|
@@ -53,7 +54,7 @@ import {
|
|
|
53
54
|
} from "./figma.js";
|
|
54
55
|
export { figmaLock, submitMode } from "./figma.js";
|
|
55
56
|
import { tuneCommand } from "./tune.js";
|
|
56
|
-
import { TUNING_MODELS, measurePickerLatency } from "./gather.js";
|
|
57
|
+
import { PICKER_MODEL, TUNING_MODELS, measurePickerLatency, pickTimingStats, pickTimingText, pickTimingsPath, readPickTimings } from "./gather.js";
|
|
57
58
|
import { docsCommand, rulebookCommand, rulesCommand } from "./upload.js";
|
|
58
59
|
import { changeSetCommand, guidelineCommand } from "./guidelines.js";
|
|
59
60
|
import { designCheck, designCheckText, designRoles, designRolesText } from "./design.js";
|
|
@@ -70,6 +71,7 @@ import {
|
|
|
70
71
|
operationsFrom,
|
|
71
72
|
parseParams,
|
|
72
73
|
readBody,
|
|
74
|
+
STAFF_ONLY,
|
|
73
75
|
} from "./api.js";
|
|
74
76
|
import {
|
|
75
77
|
agentWorkflowCommand,
|
|
@@ -91,6 +93,7 @@ import {
|
|
|
91
93
|
showWaitingResults,
|
|
92
94
|
superviseRun,
|
|
93
95
|
} from "./runs.js";
|
|
96
|
+
import { awsCli, superviseRemoteRun } from "./remote.js";
|
|
94
97
|
|
|
95
98
|
const HELP = `nodii-dev ${VERSION}
|
|
96
99
|
|
|
@@ -148,7 +151,7 @@ Usage: nodii-dev <command> [options] [--json]
|
|
|
148
151
|
watchdog install [--interval SECONDS] # install/update the per-Mac launchd liveness sweep (default 60s)
|
|
149
152
|
watchdog sweep # launchd entrypoint: report dead runs, stale sockets, unpushed worktrees
|
|
150
153
|
docs check|validate|upload <path...> --class ruling|conformance|editorial
|
|
151
|
-
[--base CODE=VERSION] [--decision FILE] [--
|
|
154
|
+
[--base CODE=VERSION] [--decision FILE] [--conformance-ref REF]
|
|
152
155
|
[--meaning-unchanged REASON] [--wait]
|
|
153
156
|
docs ratify --domain KEY [--domain KEY ...] --decision FILE [--wait]
|
|
154
157
|
docs parked [CODE] [--status pending|acknowledged]
|
|
@@ -156,6 +159,7 @@ Usage: nodii-dev <command> [options] [--json]
|
|
|
156
159
|
rules core # the generated core (M05-33); refused over the cap
|
|
157
160
|
rules report [--section S] [--lane KEY] # delivery totals per document; rules served per lane
|
|
158
161
|
rules find "QUESTION" [--limit N] # answer an ad-hoc rules question from the indexed sections
|
|
162
|
+
rules show CLAUSE_ID # one clause in full, from the current document version
|
|
159
163
|
rules cap TOKENS # operator: set the core token cap (default 3000)
|
|
160
164
|
gather tune cases|runs # Gather tuning (AH-11): frozen cases; runs with per-picker scores
|
|
161
165
|
gather tune replay <case-id> # blind replay + trigger shortlist, for the lane-agent picker
|
|
@@ -168,6 +172,8 @@ Usage: nodii-dev <command> [options] [--json]
|
|
|
168
172
|
gather tune finalize <run-id> # Dev scores the full 5-picker x 5-repeat matrix
|
|
169
173
|
gather picker-latency [--picker gemma-12b|gemma-e4b|gemma-26b]
|
|
170
174
|
# cold (model unloaded first) and warm pick latency, for the tuning record
|
|
175
|
+
gather timings [--model M] [--last N] # this Mac's lane Gather picks: warm-up and first-pick p50/p95
|
|
176
|
+
# (each lane gather logs one; the first pick has 120 s once warm)
|
|
171
177
|
|
|
172
178
|
coordinator start --machine NAME # register this machine's one watched coordinator; refuses a live second
|
|
173
179
|
lane launch <key> --done-check TEXT --kind KIND --side SIDE
|
|
@@ -187,9 +193,15 @@ Usage: nodii-dev <command> [options] [--json]
|
|
|
187
193
|
# the lane agent picks instead of local Gemma: alone it prints the
|
|
188
194
|
# recorded trigger shortlist; with --shortlist/--documents it records
|
|
189
195
|
# the pick (picker: agent) and the Clause map
|
|
190
|
-
|
|
196
|
+
lane gather show [<key>] [--gather ID] # the lane's Clause map (the Freeze references it, not its clauses)
|
|
197
|
+
run [--kind build|test_run|subagent|deploy] [--name TEXT] [--artifact PATH] -- <command> [args...]
|
|
191
198
|
# watched command: registers with NODII_DEV_RUN_ID,
|
|
192
|
-
# heartbeats, and records exit code + redacted log tail
|
|
199
|
+
# heartbeats, and records exit code + redacted log tail;
|
|
200
|
+
# --artifact attaches that file (text, <= 10,000 chars) to the Result
|
|
201
|
+
run --remote-ssm INSTANCE SCRIPT [--artifact PATH] [--quiet-minutes N] [--poll-seconds N] [--region R]
|
|
202
|
+
# SCRIPT runs detached on the EC2 instance through SSM (your aws CLI);
|
|
203
|
+
# fails on a non-zero exit, a vanished process, or no new output for
|
|
204
|
+
# N min (default 10, then cancelled); --artifact is a path there
|
|
193
205
|
|
|
194
206
|
lane start <key> --title TEXT --kind KIND --side SIDE [--repo REPO] [--issue ISSUE]
|
|
195
207
|
lane step <key> --side SIDE --start|--done|--block <step> [--reason TEXT]
|
|
@@ -218,7 +230,8 @@ Usage: nodii-dev <command> [options] [--json]
|
|
|
218
230
|
agent lane-limit|grant|revoke
|
|
219
231
|
people reveal <id> --reason TEXT | people refresh-names
|
|
220
232
|
|
|
221
|
-
api list [--tag TAG]
|
|
233
|
+
api list [--tag TAG] # staff-only operations are marked (ratifyAdDocument:
|
|
234
|
+
# agents get OPERATOR_REQUIRED by design)
|
|
222
235
|
api <operationId> [--param k=v] [--body @file|-|JSON]
|
|
223
236
|
<resource> <action> [ID ...] [--field VALUE]
|
|
224
237
|
|
|
@@ -477,6 +490,29 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
477
490
|
return console.log(VERSION);
|
|
478
491
|
if (argv.length === 1 && ["--help", "-h"].includes(argv[0]))
|
|
479
492
|
return console.log(HELP);
|
|
493
|
+
if (argv[0] === "run" && argv.some((x) => x === "--remote-ssm" || x.startsWith("--remote-ssm="))) {
|
|
494
|
+
const { args: scriptArgs, flags: remoteFlags } = parseArgs(argv.slice(1));
|
|
495
|
+
const single = (flag) => {
|
|
496
|
+
const value = remoteFlags[flag];
|
|
497
|
+
if (Array.isArray(value) || value === true) throw new CliError("USAGE", `run --${flag} needs one value.`, 2);
|
|
498
|
+
return value;
|
|
499
|
+
};
|
|
500
|
+
if (scriptArgs.length !== 1)
|
|
501
|
+
throw new CliError("USAGE", "run --remote-ssm INSTANCE SCRIPT [--artifact PATH] [--quiet-minutes N] [--poll-seconds N] [--region R] [--kind K] [--name TEXT]", 2);
|
|
502
|
+
const number = (flag) => (single(flag) === undefined ? undefined : Number(single(flag)));
|
|
503
|
+
const result = await superviseRemoteRun({
|
|
504
|
+
instance: single("remote-ssm"),
|
|
505
|
+
script: scriptArgs[0],
|
|
506
|
+
artifact: single("artifact"),
|
|
507
|
+
quietMinutes: number("quiet-minutes"),
|
|
508
|
+
pollSeconds: number("poll-seconds"),
|
|
509
|
+
kind: single("kind"),
|
|
510
|
+
name: single("name"),
|
|
511
|
+
aws: awsCli({ region: single("region") }),
|
|
512
|
+
});
|
|
513
|
+
process.exitCode = result.exitCode;
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
480
516
|
if (["run", "__run-supervisor"].includes(argv[0])) {
|
|
481
517
|
const boundary = argv.indexOf("--");
|
|
482
518
|
if (boundary === -1 || boundary === argv.length - 1)
|
|
@@ -492,6 +528,9 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
492
528
|
);
|
|
493
529
|
const kind = runFlags.kind;
|
|
494
530
|
const name = runFlags.name;
|
|
531
|
+
const artifact = runFlags.artifact;
|
|
532
|
+
if (Array.isArray(artifact) || artifact === true)
|
|
533
|
+
throw new CliError("USAGE", "run --artifact needs one path.", 2);
|
|
495
534
|
if (Array.isArray(kind) || kind === true)
|
|
496
535
|
throw new CliError("USAGE", "run --kind needs one value.", 2);
|
|
497
536
|
if (Array.isArray(name) || name === true)
|
|
@@ -504,7 +543,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
504
543
|
stdout.on("error", ignoreBrokenPipe);
|
|
505
544
|
process.stderr.on("error", ignoreBrokenPipe);
|
|
506
545
|
try {
|
|
507
|
-
const result = await superviseRun({ command, kind, name });
|
|
546
|
+
const result = await superviseRun({ command, kind, name, artifact });
|
|
508
547
|
process.exitCode = result.exitCode;
|
|
509
548
|
return;
|
|
510
549
|
} finally {
|
|
@@ -512,7 +551,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
512
551
|
process.stderr.off("error", ignoreBrokenPipe);
|
|
513
552
|
}
|
|
514
553
|
}
|
|
515
|
-
const exitCode = await launchRunSupervisor(command, { kind, name });
|
|
554
|
+
const exitCode = await launchRunSupervisor(command, { kind, name, artifact: artifact && resolve(artifact) });
|
|
516
555
|
process.exitCode = exitCode;
|
|
517
556
|
return;
|
|
518
557
|
}
|
|
@@ -526,8 +565,8 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
526
565
|
const selected = f.tag === undefined || f.tag === true
|
|
527
566
|
? operations
|
|
528
567
|
: operations.filter((x) => x.tags.some((t) => t.toLowerCase() === String(f.tag).toLowerCase()));
|
|
529
|
-
return emit(selected.map(({ operationId, method, path, tags }) => ({ operationId, method, path, tags })), json,
|
|
530
|
-
(rows) => rows.map((x) => `${x.operationId}\t${x.method}\t${x.path}\t${x.tags.join(",")}`).join("\n"));
|
|
568
|
+
return emit(selected.map(({ operationId, method, path, tags }) => ({ operationId, method, path, tags, ...(STAFF_ONLY.has(operationId) ? { staffOnly: true } : {}) })), json,
|
|
569
|
+
(rows) => rows.map((x) => `${x.operationId}\t${x.method}\t${x.path}\t${x.tags.join(",")}${x.staffOnly ? `\t# ${STAFF_ONLY.get(x.operationId)}` : ""}`).join("\n"));
|
|
531
570
|
}
|
|
532
571
|
if (!action) throw new CliError("USAGE", "api needs an operationId or list", 2);
|
|
533
572
|
const entry = operations.find((x) => x.operationId === action);
|
|
@@ -597,6 +636,15 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
597
636
|
const line = (label, x) => `${label} ${x.wallMs} ms (Ollama total ${x.totalMs ?? "?"} ms, model load ${x.loadMs ?? "?"} ms)`;
|
|
598
637
|
return emit(result, json, (r) => `${r.model}\n${line("cold", r.cold)}\n${line("warm", r.warm)}`);
|
|
599
638
|
}
|
|
639
|
+
if (command === "gather" && action === "timings") {
|
|
640
|
+
const last = f.last === undefined ? 50 : Number(f.last);
|
|
641
|
+
if (!Number.isInteger(last) || last < 1) throw new CliError("USAGE", "gather timings [--model M] [--last N]", 2);
|
|
642
|
+
const model = typeof f.model === "string" ? f.model : PICKER_MODEL;
|
|
643
|
+
const path = pickTimingsPath();
|
|
644
|
+
const entries = await readPickTimings({ path, model, last });
|
|
645
|
+
const stats = pickTimingStats(entries);
|
|
646
|
+
return emit({ model, path, ...stats, entries }, json, () => pickTimingText(stats, { model, path }));
|
|
647
|
+
}
|
|
600
648
|
if (command === "gather" && action === "tune") {
|
|
601
649
|
const result = await tuneCommand(rest[0], rest.slice(1), f);
|
|
602
650
|
emit(result.payload, json, result.human);
|
package/dist/core.js
CHANGED
|
@@ -4,7 +4,7 @@ import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
|
4
4
|
import { homedir, platform } from "node:os";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
|
|
7
|
-
export const VERSION = "0.6.
|
|
7
|
+
export const VERSION = "0.6.36";
|
|
8
8
|
export const configPath = () =>
|
|
9
9
|
process.env.NODII_DEV_CONFIG_PATH ??
|
|
10
10
|
join(homedir(), ".config/nodii-dev/config.json");
|