@dosu/cli 0.39.0 → 0.40.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.
- package/bin/dosu.js +78 -25
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4759,7 +4759,7 @@ var init_dist4 = __esm(() => {
|
|
|
4759
4759
|
function getVersionString() {
|
|
4760
4760
|
return `v${VERSION}`;
|
|
4761
4761
|
}
|
|
4762
|
-
var VERSION = "0.
|
|
4762
|
+
var VERSION = "0.40.0", INSTALL_CHANNEL = "npm";
|
|
4763
4763
|
|
|
4764
4764
|
// src/debug/logger.ts
|
|
4765
4765
|
import {
|
|
@@ -8178,7 +8178,8 @@ __export(exports_prompts, {
|
|
|
8178
8178
|
buildReadyEnvelope: () => buildReadyEnvelope,
|
|
8179
8179
|
STOP_PREFIX: () => STOP_PREFIX,
|
|
8180
8180
|
SAVE_NUDGE: () => SAVE_NUDGE,
|
|
8181
|
-
LOOKUP_STARTED_NOTE: () => LOOKUP_STARTED_NOTE
|
|
8181
|
+
LOOKUP_STARTED_NOTE: () => LOOKUP_STARTED_NOTE,
|
|
8182
|
+
LATE_RESULT_NOTE: () => LATE_RESULT_NOTE
|
|
8182
8183
|
});
|
|
8183
8184
|
function buildReadyEnvelope(context, saveRecommended = false) {
|
|
8184
8185
|
const trimmed = context.trim();
|
|
@@ -8204,9 +8205,10 @@ function buildReadyEnvelope(context, saveRecommended = false) {
|
|
|
8204
8205
|
|
|
8205
8206
|
`);
|
|
8206
8207
|
}
|
|
8207
|
-
var LOOKUP_STARTED_NOTE, STOP_PREFIX, SAVE_NUDGE;
|
|
8208
|
+
var LOOKUP_STARTED_NOTE, LATE_RESULT_NOTE, STOP_PREFIX, SAVE_NUDGE;
|
|
8208
8209
|
var init_prompts = __esm(() => {
|
|
8209
8210
|
LOOKUP_STARTED_NOTE = "Dosu started a background knowledge lookup for this request. Keep working normally — " + "do not wait or pause for it. If Dosu context arrives during this session, fold it in " + "quietly to work faster and avoid wrong assumptions. Mention Dosu when its context " + "helps you.";
|
|
8211
|
+
LATE_RESULT_NOTE = "Heads-up: the context below answers your PREVIOUS prompt — its lookup finished after " + "that turn had already ended. Apply it only where it is still relevant to the current " + "work; do not treat it as a response to the new prompt.";
|
|
8210
8212
|
STOP_PREFIX = "Dosu knowledge finished after your last action. Re-check your current conclusion against " + "it, then continue or finish — do not redo work it merely confirms.";
|
|
8211
8213
|
SAVE_NUDGE = "Dosu has little or no existing knowledge on this topic. If you uncover something durable — " + "a non-obvious mechanism, a gotcha, or a route through the code — save it with the Dosu " + "`save_topic` tool when you finish, so future sessions start ahead. Only save genuinely " + "reusable knowledge; skip trivial or one-off details.";
|
|
8212
8214
|
});
|
|
@@ -15039,7 +15041,7 @@ import { basename } from "node:path";
|
|
|
15039
15041
|
|
|
15040
15042
|
// src/hooks/state.ts
|
|
15041
15043
|
init_config();
|
|
15042
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
15044
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
15043
15045
|
import { dirname as dirname2, join as join5 } from "node:path";
|
|
15044
15046
|
function getStateDir() {
|
|
15045
15047
|
return process.env.DOSU_HOOK_STATE_DIR ?? join5(getConfigDir(), "hooks");
|
|
@@ -15067,9 +15069,24 @@ function saveState(state) {
|
|
|
15067
15069
|
writeFileSync5(file, JSON.stringify(state, null, 2), { mode: 384 });
|
|
15068
15070
|
} catch {}
|
|
15069
15071
|
}
|
|
15070
|
-
function
|
|
15072
|
+
function claimState(sessionId) {
|
|
15073
|
+
const file = stateFile(sessionId);
|
|
15071
15074
|
try {
|
|
15072
|
-
|
|
15075
|
+
renameSync2(file, `${file}.claim`);
|
|
15076
|
+
return JSON.parse(readFileSync6(`${file}.claim`, "utf8"));
|
|
15077
|
+
} catch {
|
|
15078
|
+
return null;
|
|
15079
|
+
}
|
|
15080
|
+
}
|
|
15081
|
+
function releaseState(sessionId, state) {
|
|
15082
|
+
const file = stateFile(sessionId);
|
|
15083
|
+
if (state) {
|
|
15084
|
+
try {
|
|
15085
|
+
writeFileSync5(file, JSON.stringify(state, null, 2), { flag: "wx", mode: 384 });
|
|
15086
|
+
} catch {}
|
|
15087
|
+
}
|
|
15088
|
+
try {
|
|
15089
|
+
rmSync2(`${file}.claim`, { force: true });
|
|
15073
15090
|
} catch {}
|
|
15074
15091
|
}
|
|
15075
15092
|
|
|
@@ -15150,15 +15167,31 @@ async function runUserPromptSubmit(input, now = Date.now(), agent = DEFAULT_AGEN
|
|
|
15150
15167
|
logger.debug("hooks", `submit sid=${sid8(sessionId)} reuse tid=${existing.ticketId}`);
|
|
15151
15168
|
return;
|
|
15152
15169
|
}
|
|
15153
|
-
|
|
15154
|
-
clearState(sessionId);
|
|
15170
|
+
const claimed = existing ? claimState(sessionId) : null;
|
|
15155
15171
|
const cfg = loadConfig();
|
|
15156
15172
|
if (!cfg.active_account?.target?.api_key || !cfg.active_account?.target?.deployment_id) {
|
|
15173
|
+
if (claimed)
|
|
15174
|
+
releaseState(sessionId, null);
|
|
15157
15175
|
logger.debug("hooks", "submit skipped reason=not-configured");
|
|
15158
15176
|
return;
|
|
15159
15177
|
}
|
|
15160
15178
|
const git = gitContext(input.cwd);
|
|
15161
15179
|
const tc = await Promise.resolve().then(() => (init_ticket_client(), exports_ticket_client));
|
|
15180
|
+
let lateBlock;
|
|
15181
|
+
if (claimed && claimed.status === "pending" && now <= claimed.expiresAt) {
|
|
15182
|
+
try {
|
|
15183
|
+
const old = await tc.requestGetTicket(cfg, claimed.ticketId);
|
|
15184
|
+
if (old.status === "ready" && old.result?.context.trim()) {
|
|
15185
|
+
const { buildReadyEnvelope: buildReadyEnvelope2, LATE_RESULT_NOTE: LATE_RESULT_NOTE2 } = await Promise.resolve().then(() => (init_prompts(), exports_prompts));
|
|
15186
|
+
lateBlock = `${LATE_RESULT_NOTE2}
|
|
15187
|
+
|
|
15188
|
+
${buildReadyEnvelope2(old.result.context, old.result.save_recommended ?? false)}`;
|
|
15189
|
+
logger.info("hooks", `harvest tid=${claimed.ticketId} delivered=late`);
|
|
15190
|
+
}
|
|
15191
|
+
} catch {}
|
|
15192
|
+
}
|
|
15193
|
+
if (claimed)
|
|
15194
|
+
releaseState(sessionId, null);
|
|
15162
15195
|
const startedAt = Date.now();
|
|
15163
15196
|
let resp;
|
|
15164
15197
|
try {
|
|
@@ -15185,7 +15218,9 @@ async function runUserPromptSubmit(input, now = Date.now(), agent = DEFAULT_AGEN
|
|
|
15185
15218
|
});
|
|
15186
15219
|
logger.info("hooks", `create sid=${sid8(sessionId)} tid=${resp.ticket_id} latency=${Date.now() - startedAt}ms`);
|
|
15187
15220
|
const { LOOKUP_STARTED_NOTE: LOOKUP_STARTED_NOTE2 } = await Promise.resolve().then(() => (init_prompts(), exports_prompts));
|
|
15188
|
-
printHookContext("UserPromptSubmit",
|
|
15221
|
+
printHookContext("UserPromptSubmit", lateBlock ? `${lateBlock}
|
|
15222
|
+
|
|
15223
|
+
${LOOKUP_STARTED_NOTE2}` : LOOKUP_STARTED_NOTE2);
|
|
15189
15224
|
}
|
|
15190
15225
|
async function runPostToolUse(input, now = Date.now()) {
|
|
15191
15226
|
const sessionId = input.session_id;
|
|
@@ -15213,35 +15248,45 @@ async function runPostToolUse(input, now = Date.now()) {
|
|
|
15213
15248
|
saveState({ ...state, lastCheckedAt: now });
|
|
15214
15249
|
return;
|
|
15215
15250
|
}
|
|
15251
|
+
const claimed = claimState(sessionId);
|
|
15252
|
+
if (!claimed) {
|
|
15253
|
+
logger.debug("hooks", `poll tid=${state.ticketId} skipped=contended`);
|
|
15254
|
+
return;
|
|
15255
|
+
}
|
|
15216
15256
|
const tc = await Promise.resolve().then(() => (init_ticket_client(), exports_ticket_client));
|
|
15217
15257
|
const startedAt = Date.now();
|
|
15218
15258
|
let resp;
|
|
15219
15259
|
try {
|
|
15220
|
-
resp = await tc.requestGetTicket(cfg,
|
|
15260
|
+
resp = await tc.requestGetTicket(cfg, claimed.ticketId);
|
|
15221
15261
|
} catch (err) {
|
|
15222
15262
|
if (tc.isDefinitiveError(err)) {
|
|
15223
|
-
|
|
15263
|
+
releaseState(sessionId, { ...claimed, status: "failed", lastCheckedAt: now });
|
|
15224
15264
|
logger.warn("hooks", `error event=post-tool-use reason=${errMsg(err)} definitive`);
|
|
15225
15265
|
} else {
|
|
15226
|
-
|
|
15227
|
-
logger.debug("hooks", `poll tid=${
|
|
15266
|
+
releaseState(sessionId, { ...claimed, lastCheckedAt: now });
|
|
15267
|
+
logger.debug("hooks", `poll tid=${claimed.ticketId} transient-error`);
|
|
15228
15268
|
}
|
|
15229
15269
|
return;
|
|
15230
15270
|
}
|
|
15231
15271
|
if (resp.status === "pending") {
|
|
15232
|
-
|
|
15233
|
-
logger.debug("hooks", `poll tid=${
|
|
15272
|
+
releaseState(sessionId, { ...claimed, lastCheckedAt: now });
|
|
15273
|
+
logger.debug("hooks", `poll tid=${claimed.ticketId} status=pending`);
|
|
15234
15274
|
return;
|
|
15235
15275
|
}
|
|
15236
15276
|
if (resp.status === "failed" || resp.status === "expired") {
|
|
15237
|
-
|
|
15277
|
+
releaseState(sessionId, { ...claimed, status: resp.status, lastCheckedAt: now });
|
|
15238
15278
|
return;
|
|
15239
15279
|
}
|
|
15240
15280
|
if (!resp.result) {
|
|
15241
|
-
|
|
15281
|
+
releaseState(sessionId, { ...claimed, status: "failed", lastCheckedAt: now });
|
|
15242
15282
|
return;
|
|
15243
15283
|
}
|
|
15244
|
-
|
|
15284
|
+
releaseState(sessionId, {
|
|
15285
|
+
...claimed,
|
|
15286
|
+
status: "delivered",
|
|
15287
|
+
deliveredAt: now,
|
|
15288
|
+
lastCheckedAt: now
|
|
15289
|
+
});
|
|
15245
15290
|
const { buildReadyEnvelope: buildReadyEnvelope2 } = await Promise.resolve().then(() => (init_prompts(), exports_prompts));
|
|
15246
15291
|
const context = buildReadyEnvelope2(resp.result.context, resp.result.save_recommended ?? false);
|
|
15247
15292
|
if (context) {
|
|
@@ -15263,37 +15308,45 @@ async function runStop(input, now = Date.now()) {
|
|
|
15263
15308
|
const cfg = loadConfig();
|
|
15264
15309
|
if (!cfg.active_account?.target?.api_key || !cfg.active_account?.target?.deployment_id)
|
|
15265
15310
|
return printContinue();
|
|
15311
|
+
const claimed = claimState(sessionId);
|
|
15312
|
+
if (!claimed)
|
|
15313
|
+
return printContinue();
|
|
15266
15314
|
const tc = await Promise.resolve().then(() => (init_ticket_client(), exports_ticket_client));
|
|
15267
15315
|
const pollMs = stopPollMs();
|
|
15268
15316
|
const maxWaits = pollMs > 0 ? Math.floor(stopWaitMs() / pollMs) : 0;
|
|
15269
15317
|
for (let waited = 0;; waited++) {
|
|
15270
15318
|
let resp;
|
|
15271
15319
|
try {
|
|
15272
|
-
resp = await tc.requestGetTicket(cfg,
|
|
15320
|
+
resp = await tc.requestGetTicket(cfg, claimed.ticketId);
|
|
15273
15321
|
} catch {
|
|
15274
|
-
|
|
15322
|
+
releaseState(sessionId, { ...claimed, lastCheckedAt: now });
|
|
15275
15323
|
return printContinue();
|
|
15276
15324
|
}
|
|
15277
15325
|
if (resp.status === "ready" && resp.result) {
|
|
15278
|
-
|
|
15326
|
+
releaseState(sessionId, {
|
|
15327
|
+
...claimed,
|
|
15328
|
+
status: "delivered",
|
|
15329
|
+
deliveredAt: now,
|
|
15330
|
+
lastCheckedAt: now
|
|
15331
|
+
});
|
|
15279
15332
|
if (resp.result.context.trim()) {
|
|
15280
15333
|
const { buildReadyEnvelope: buildReadyEnvelope2, STOP_PREFIX: STOP_PREFIX2 } = await Promise.resolve().then(() => (init_prompts(), exports_prompts));
|
|
15281
15334
|
const envelope = buildReadyEnvelope2(resp.result.context, resp.result.save_recommended ?? false);
|
|
15282
15335
|
console.log(JSON.stringify({ decision: "block", reason: `${STOP_PREFIX2}
|
|
15283
15336
|
|
|
15284
15337
|
${envelope}` }));
|
|
15285
|
-
logger.info("hooks", `stop tid=${
|
|
15338
|
+
logger.info("hooks", `stop tid=${claimed.ticketId} delivered=true`);
|
|
15286
15339
|
return;
|
|
15287
15340
|
}
|
|
15288
|
-
logger.debug("hooks", `stop tid=${
|
|
15341
|
+
logger.debug("hooks", `stop tid=${claimed.ticketId} delivered=true gap-no-block`);
|
|
15289
15342
|
return printContinue();
|
|
15290
15343
|
}
|
|
15291
15344
|
if (resp.status !== "pending" || waited >= maxWaits)
|
|
15292
15345
|
break;
|
|
15293
15346
|
await sleep4(pollMs);
|
|
15294
15347
|
}
|
|
15295
|
-
|
|
15296
|
-
logger.debug("hooks", `stop tid=${
|
|
15348
|
+
releaseState(sessionId, { ...claimed, lastCheckedAt: now });
|
|
15349
|
+
logger.debug("hooks", `stop tid=${claimed.ticketId} delivered=false`);
|
|
15297
15350
|
printContinue();
|
|
15298
15351
|
}
|
|
15299
15352
|
function runStatus(input, opts, now = Date.now()) {
|