@dosu/cli 0.16.2 → 0.18.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 +46 -33
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4525,7 +4525,7 @@ var init_dist4 = __esm(() => {
|
|
|
4525
4525
|
function getVersionString() {
|
|
4526
4526
|
return `v${VERSION}`;
|
|
4527
4527
|
}
|
|
4528
|
-
var VERSION = "0.
|
|
4528
|
+
var VERSION = "0.18.0";
|
|
4529
4529
|
|
|
4530
4530
|
// src/debug/logger.ts
|
|
4531
4531
|
import {
|
|
@@ -5491,8 +5491,8 @@ function buildReadyEnvelope(context, saveRecommended = false) {
|
|
|
5491
5491
|
"How to use this:",
|
|
5492
5492
|
"- Use it quietly to answer faster and with fewer broad searches. Keep working normally.",
|
|
5493
5493
|
"- This is the known likely path, not the full boundary. Before finalizing, verify adjacent " + "public/API entrypoints and edge cases that this route map may not cover.",
|
|
5494
|
-
"- Attribution:
|
|
5495
|
-
"-
|
|
5494
|
+
"- Attribution: this context is your team's existing knowledge (docs, past PRs, discussions) " + "surfaced by Dosu — not the live code you're reading. For each main finding it speaks to, " + "add one brief cited note on how the team's knowledge relates: if it agrees, note it in a " + "line and cite the source; if it differs, flag it as worth confirming and reconcile before " + "finalizing; if it adds something the code alone wouldn't tell you (a rationale, a gotcha, " + "a past decision), surface it, cited.",
|
|
5495
|
+
"- Surface this at each main finding the context speaks to — but skip the ones it is " + "genuinely silent on, and never invent agreement or disagreement. Keep each note brief and " + 'next to the finding; do not open with "Dosu told me…", do not add a closing praise ' + "paragraph, and do not reference any ticket or lookup id."
|
|
5496
5496
|
].join(`
|
|
5497
5497
|
`));
|
|
5498
5498
|
}
|
|
@@ -5505,7 +5505,7 @@ function buildReadyEnvelope(context, saveRecommended = false) {
|
|
|
5505
5505
|
}
|
|
5506
5506
|
var LOOKUP_STARTED_NOTE, STOP_PREFIX, SAVE_NUDGE;
|
|
5507
5507
|
var init_prompts = __esm(() => {
|
|
5508
|
-
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
|
|
5508
|
+
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.";
|
|
5509
5509
|
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.";
|
|
5510
5510
|
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.";
|
|
5511
5511
|
});
|
|
@@ -9418,7 +9418,7 @@ function hasNewVisibleRepository(previousRepos, nextRepos) {
|
|
|
9418
9418
|
const previousRepoIds = new Set(previousRepos.map((repo) => repo.repository_id));
|
|
9419
9419
|
return nextRepos.some((repo) => !previousRepoIds.has(repo.repository_id));
|
|
9420
9420
|
}
|
|
9421
|
-
function
|
|
9421
|
+
function sleep3(ms) {
|
|
9422
9422
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
9423
9423
|
}
|
|
9424
9424
|
async function waitForRepositoryRefresh(trpc, orgID, previousRepos, opts) {
|
|
@@ -9432,7 +9432,7 @@ async function waitForRepositoryRefresh(trpc, orgID, previousRepos, opts) {
|
|
|
9432
9432
|
if (hasNewVisibleRepository(previousRepos, latestRepos)) {
|
|
9433
9433
|
return { repos: latestRepos, foundNew: true };
|
|
9434
9434
|
}
|
|
9435
|
-
await
|
|
9435
|
+
await sleep3(intervalMs);
|
|
9436
9436
|
}
|
|
9437
9437
|
return { repos: latestRepos, foundNew: false };
|
|
9438
9438
|
}
|
|
@@ -9565,7 +9565,7 @@ async function verifyDataSourcesPersist(trpc, orgID, expectedDataSourceIds, opts
|
|
|
9565
9565
|
return { alive, dropped };
|
|
9566
9566
|
if (timeoutMs === 0)
|
|
9567
9567
|
break;
|
|
9568
|
-
await
|
|
9568
|
+
await sleep3(intervalMs);
|
|
9569
9569
|
}
|
|
9570
9570
|
return { alive, dropped };
|
|
9571
9571
|
}
|
|
@@ -10165,7 +10165,7 @@ async function waitForImportTaskCompletion(trpc, taskID, spinner, expectedTotal)
|
|
|
10165
10165
|
return null;
|
|
10166
10166
|
}
|
|
10167
10167
|
}
|
|
10168
|
-
await
|
|
10168
|
+
await sleep4(IMPORT_STATUS_POLL_INTERVAL_MS);
|
|
10169
10169
|
}
|
|
10170
10170
|
}
|
|
10171
10171
|
function buildImportProgressMessage(status, expectedTotal) {
|
|
@@ -10216,7 +10216,7 @@ async function waitForImportableGithubFiles(trpc, orgID, spaceID, expectedDataSo
|
|
|
10216
10216
|
spinner.stop(latestFiles.length > 0 ? "Docs ready" : "No markdown docs found");
|
|
10217
10217
|
return latestFiles;
|
|
10218
10218
|
}
|
|
10219
|
-
await
|
|
10219
|
+
await sleep4(DOC_SCAN_POLL_INTERVAL_MS);
|
|
10220
10220
|
continue;
|
|
10221
10221
|
}
|
|
10222
10222
|
latestFiles = await fetchImportableGithubFiles(trpc, spaceID);
|
|
@@ -10228,7 +10228,7 @@ async function waitForImportableGithubFiles(trpc, orgID, spaceID, expectedDataSo
|
|
|
10228
10228
|
spinner.stop("No markdown docs found");
|
|
10229
10229
|
return [];
|
|
10230
10230
|
}
|
|
10231
|
-
await
|
|
10231
|
+
await sleep4(DOC_SCAN_POLL_INTERVAL_MS);
|
|
10232
10232
|
}
|
|
10233
10233
|
spinner.stop("Timed out");
|
|
10234
10234
|
const choice = await ve({
|
|
@@ -10322,7 +10322,7 @@ async function getKnowledgeStoreID(trpc, spaceID) {
|
|
|
10322
10322
|
return null;
|
|
10323
10323
|
}
|
|
10324
10324
|
}
|
|
10325
|
-
function
|
|
10325
|
+
function sleep4(ms) {
|
|
10326
10326
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10327
10327
|
}
|
|
10328
10328
|
var DOC_SCAN_POLL_INTERVAL_MS = 2000, DOC_SCAN_POLL_TIMEOUT_MS = 60000, IMPORT_STATUS_POLL_INTERVAL_MS = 2000, IMPORT_STATUS_MAX_ERRORS = 3;
|
|
@@ -12991,6 +12991,8 @@ function saveState(state) {
|
|
|
12991
12991
|
// src/commands/hooks.ts
|
|
12992
12992
|
var COOLDOWN_DEFAULT_MS = 3000;
|
|
12993
12993
|
var TTL_DEFAULT_MS = 10 * 60 * 1000;
|
|
12994
|
+
var STOP_WAIT_DEFAULT_MS = 8000;
|
|
12995
|
+
var STOP_POLL_DEFAULT_MS = 1000;
|
|
12994
12996
|
var SUPPORTED_AGENTS = ["claude-code"];
|
|
12995
12997
|
function cooldownMs() {
|
|
12996
12998
|
const n = Number.parseInt(process.env.DOSU_HOOK_CHECK_COOLDOWN_MS ?? "", 10);
|
|
@@ -13000,12 +13002,21 @@ function ttlMs() {
|
|
|
13000
13002
|
const n = Number.parseInt(process.env.DOSU_HOOK_TTL_MS ?? "", 10);
|
|
13001
13003
|
return Number.isFinite(n) && n > 0 ? n : TTL_DEFAULT_MS;
|
|
13002
13004
|
}
|
|
13005
|
+
function stopWaitMs() {
|
|
13006
|
+
const n = Number.parseInt(process.env.DOSU_HOOK_STOP_WAIT_MS ?? "", 10);
|
|
13007
|
+
return Number.isFinite(n) && n >= 0 ? n : STOP_WAIT_DEFAULT_MS;
|
|
13008
|
+
}
|
|
13009
|
+
function stopPollMs() {
|
|
13010
|
+
const n = Number.parseInt(process.env.DOSU_HOOK_STOP_POLL_MS ?? "", 10);
|
|
13011
|
+
return Number.isFinite(n) && n > 0 ? n : STOP_POLL_DEFAULT_MS;
|
|
13012
|
+
}
|
|
13003
13013
|
function printHookContext(event, additionalContext) {
|
|
13004
13014
|
console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: event, additionalContext } }));
|
|
13005
13015
|
}
|
|
13006
13016
|
function printContinue() {
|
|
13007
13017
|
console.log(JSON.stringify({ continue: true }));
|
|
13008
13018
|
}
|
|
13019
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
13009
13020
|
function sid8(sessionId) {
|
|
13010
13021
|
return sessionId.slice(0, 8);
|
|
13011
13022
|
}
|
|
@@ -13128,40 +13139,42 @@ async function runStop(input, now = Date.now()) {
|
|
|
13128
13139
|
const sessionId = input.session_id;
|
|
13129
13140
|
if (!sessionId)
|
|
13130
13141
|
return printContinue();
|
|
13131
|
-
if (input.stop_hook_active === true)
|
|
13132
|
-
return printContinue();
|
|
13133
13142
|
const state = loadState(sessionId);
|
|
13134
13143
|
if (!state)
|
|
13135
13144
|
return printContinue();
|
|
13136
13145
|
if (state.status !== "pending" || now > state.expiresAt)
|
|
13137
13146
|
return printContinue();
|
|
13138
|
-
if (state.lastCheckedAt !== undefined && now - state.lastCheckedAt < cooldownMs()) {
|
|
13139
|
-
return printContinue();
|
|
13140
|
-
}
|
|
13141
13147
|
const cfg = loadConfig();
|
|
13142
13148
|
if (!cfg.api_key || !cfg.deployment_id)
|
|
13143
13149
|
return printContinue();
|
|
13144
13150
|
const tc = await Promise.resolve().then(() => (init_ticket_client(), exports_ticket_client));
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
|
|
13149
|
-
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13151
|
+
const pollMs = stopPollMs();
|
|
13152
|
+
const maxWaits = pollMs > 0 ? Math.floor(stopWaitMs() / pollMs) : 0;
|
|
13153
|
+
for (let waited = 0;; waited++) {
|
|
13154
|
+
let resp;
|
|
13155
|
+
try {
|
|
13156
|
+
resp = await tc.requestGetTicket(cfg, state.ticketId);
|
|
13157
|
+
} catch {
|
|
13158
|
+
saveState({ ...state, lastCheckedAt: now });
|
|
13159
|
+
return printContinue();
|
|
13160
|
+
}
|
|
13161
|
+
if (resp.status === "ready" && resp.result) {
|
|
13162
|
+
saveState({ ...state, status: "delivered", deliveredAt: now, lastCheckedAt: now });
|
|
13163
|
+
if (resp.result.context.trim()) {
|
|
13164
|
+
const { buildReadyEnvelope: buildReadyEnvelope2, STOP_PREFIX: STOP_PREFIX2 } = await Promise.resolve().then(() => (init_prompts(), exports_prompts));
|
|
13165
|
+
const envelope = buildReadyEnvelope2(resp.result.context, resp.result.save_recommended ?? false);
|
|
13166
|
+
console.log(JSON.stringify({ decision: "block", reason: `${STOP_PREFIX2}
|
|
13158
13167
|
|
|
13159
13168
|
${envelope}` }));
|
|
13160
|
-
|
|
13161
|
-
|
|
13169
|
+
logger.info("hooks", `stop tid=${state.ticketId} delivered=true`);
|
|
13170
|
+
return;
|
|
13171
|
+
}
|
|
13172
|
+
logger.debug("hooks", `stop tid=${state.ticketId} delivered=true gap-no-block`);
|
|
13173
|
+
return printContinue();
|
|
13162
13174
|
}
|
|
13163
|
-
|
|
13164
|
-
|
|
13175
|
+
if (resp.status !== "pending" || waited >= maxWaits)
|
|
13176
|
+
break;
|
|
13177
|
+
await sleep2(pollMs);
|
|
13165
13178
|
}
|
|
13166
13179
|
saveState({ ...state, lastCheckedAt: now });
|
|
13167
13180
|
logger.debug("hooks", `stop tid=${state.ticketId} delivered=false`);
|