neuvikon 0.2.27 → 0.2.29
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/dist/index.mjs +65 -27
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -22,11 +22,21 @@ var NetworkError = class extends Error {
|
|
|
22
22
|
};
|
|
23
23
|
const TIMEOUT_MS = 15e3;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* A long-running ticket's `stop`/`report` calls matter more than a quick
|
|
26
|
+
* command's — losing one of those to a blip on a flaky connection is what
|
|
27
|
+
* leaves a session "active" server-side but silently stale on the board,
|
|
28
|
+
* since nothing else will ever tell the server this session ended. Three
|
|
29
|
+
* tries with a short, fixed backoff absorbs a transient blip (DNS hiccup,
|
|
30
|
+
* one dropped packet) without retrying forever: a genuinely dead connection
|
|
31
|
+
* still fails after three `TIMEOUT_MS` waits plus two short delays, same as
|
|
32
|
+
* it always would have, just with two extra chances to succeed first.
|
|
28
33
|
*/
|
|
29
|
-
|
|
34
|
+
const RETRY_ATTEMPTS = 3;
|
|
35
|
+
const RETRY_DELAY_MS = 1e3;
|
|
36
|
+
function sleep$1(ms) {
|
|
37
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
38
|
+
}
|
|
39
|
+
async function postOnce(url, path, body) {
|
|
30
40
|
let response;
|
|
31
41
|
try {
|
|
32
42
|
response = await fetch(`${url}${path}`, {
|
|
@@ -43,6 +53,24 @@ async function post(url, path, body) {
|
|
|
43
53
|
if (!response.ok) throw new ApiError(typeof error === "string" ? error : `Request failed with status ${response.status}`, response.status);
|
|
44
54
|
return payload;
|
|
45
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* The one place an HTTP failure becomes a typed error. Callers decide what a
|
|
58
|
+
* failure means — a hook wrapping the agent's turn wants to swallow it, `login`
|
|
59
|
+
* wants to shout about it.
|
|
60
|
+
*
|
|
61
|
+
* Retries only on `NetworkError` — the request never reached the server, so
|
|
62
|
+
* trying again can only help. An `ApiError` means the server answered (a bad
|
|
63
|
+
* token, an unknown ticket, a validation failure); retrying that gets the
|
|
64
|
+
* same answer every time, so it still fails on the first try.
|
|
65
|
+
*/
|
|
66
|
+
async function post(url, path, body) {
|
|
67
|
+
for (let attempt = 1;; attempt++) try {
|
|
68
|
+
return await postOnce(url, path, body);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (!(error instanceof NetworkError) || attempt >= RETRY_ATTEMPTS) throw error;
|
|
71
|
+
await sleep$1(RETRY_DELAY_MS);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
46
74
|
function normalizeUrl(url) {
|
|
47
75
|
return url.trim().replace(/\/+$/, "");
|
|
48
76
|
}
|
|
@@ -823,27 +851,30 @@ const START_MARKER = "<!-- neuvikon:start -->";
|
|
|
823
851
|
const END_MARKER = "<!-- neuvikon:end -->";
|
|
824
852
|
const INSTRUCTION_BODY = `## Neuvikon ticket tracking
|
|
825
853
|
|
|
826
|
-
|
|
827
|
-
\`EWWQ-1:\` —
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
to maximum for everything:
|
|
854
|
+
**The moment you receive a Neuvikon ticket — text beginning with a reference
|
|
855
|
+
like \`EWWQ-1:\` — before reading any file, before running \`start\`, before
|
|
856
|
+
anything else: judge its difficulty and act on it.** This is a real step, not
|
|
857
|
+
background bookkeeping — if your CLI supports switching model or reasoning
|
|
858
|
+
effort mid-session (Claude Code: \`/model\`, \`/effort\`; Codex: \`/model\`,
|
|
859
|
+
\`/reasoning\`), the command to do that is the literal first thing you send,
|
|
860
|
+
on its own, before you touch the ticket:
|
|
834
861
|
|
|
835
862
|
- Small, mechanical change — swapping button placement, a copy/label edit, a
|
|
836
|
-
trivial styling tweak, a one-line config change:
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
863
|
+
trivial styling tweak, a one-line config change: send \`/model haiku\` (or
|
|
864
|
+
your CLI's equivalent cheap/fast model) and \`/effort low\` (or
|
|
865
|
+
\`/reasoning low\`) right now, as their own messages, before doing anything
|
|
866
|
+
else. There's no reason to spend a frontier model thinking hard about
|
|
867
|
+
something this small, and downgrading after you've already started reading
|
|
868
|
+
code is too late to save anything.
|
|
841
869
|
- Needs real design judgment, touches multiple systems, or you're unsure:
|
|
842
870
|
stay on your current model and effort level — don't downgrade either just
|
|
843
871
|
to save cost on something that actually needs it.
|
|
872
|
+
- Your CLI doesn't expose a way to change model or effort mid-session: skip
|
|
873
|
+
this and go straight to the ticket.
|
|
844
874
|
|
|
845
|
-
|
|
846
|
-
|
|
875
|
+
Only after that's decided, run this before you start working on the ticket:
|
|
876
|
+
|
|
877
|
+
npx neuvikon start --ticket EWWQ-1
|
|
847
878
|
|
|
848
879
|
Before you start, and any time you need more context, read the ticket's
|
|
849
880
|
project pages — this is the project's accumulated knowledge, not just this
|
|
@@ -963,16 +994,23 @@ Then decide, based on what's actually true, not on finishing your turn:
|
|
|
963
994
|
npx neuvikon comment --ticket EWWQ-1 --text "Handing off — blocked on design"
|
|
964
995
|
|
|
965
996
|
A ticket that isn't actually finished should never land on a terminal column
|
|
966
|
-
just because you're done for now.
|
|
967
|
-
|
|
997
|
+
just because you're done for now.
|
|
998
|
+
|
|
999
|
+
**Whenever you stop working a ticket — finished or not — \`move\`/\`comment\`
|
|
1000
|
+
always comes first, \`stop\` always comes last.** \`stop\` only tells the team
|
|
1001
|
+
you're no longer working on it; it does not move the ticket, and running it
|
|
1002
|
+
before the move leaves the board showing stale status for a ticket nobody's
|
|
1003
|
+
touching anymore. So the last two things you do on a ticket, in this order,
|
|
1004
|
+
are:
|
|
968
1005
|
|
|
969
|
-
|
|
1006
|
+
1. \`npx neuvikon move ...\` (finished) or \`npx neuvikon comment ...\`
|
|
1007
|
+
(not finished) — reflect the real status first.
|
|
1008
|
+
2. \`npx neuvikon stop\` — only after step 1, whether you're done or just
|
|
1009
|
+
handing off.
|
|
970
1010
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
need to narrate these commands, and if one fails, carry on with the actual
|
|
975
|
-
work — never let it block you.`;
|
|
1011
|
+
This is bookkeeping that tells the user's team which ticket you are on. You
|
|
1012
|
+
do not need to narrate these commands, and if one fails, carry on with the
|
|
1013
|
+
actual work — never let it block you.`;
|
|
976
1014
|
function instructionBlock() {
|
|
977
1015
|
return `${START_MARKER}\n${INSTRUCTION_BODY}\n${END_MARKER}`;
|
|
978
1016
|
}
|