@dosu/cli 0.56.0 → 0.57.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/README.md +3 -2
- package/bin/dosu.js +625 -253
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -636,7 +636,18 @@ function numberValue(value) {
|
|
|
636
636
|
var init_config_v1_migration = () => {};
|
|
637
637
|
|
|
638
638
|
// src/config/config.ts
|
|
639
|
-
import {
|
|
639
|
+
import {
|
|
640
|
+
closeSync,
|
|
641
|
+
constants,
|
|
642
|
+
existsSync as existsSync2,
|
|
643
|
+
fstatSync,
|
|
644
|
+
mkdirSync,
|
|
645
|
+
openSync,
|
|
646
|
+
readFileSync,
|
|
647
|
+
readSync,
|
|
648
|
+
renameSync,
|
|
649
|
+
writeFileSync
|
|
650
|
+
} from "node:fs";
|
|
640
651
|
import { homedir as homedir2 } from "node:os";
|
|
641
652
|
import { join as join2 } from "node:path";
|
|
642
653
|
function getConfigUserID(cfg) {
|
|
@@ -701,6 +712,26 @@ function loadConfig() {
|
|
|
701
712
|
} catch {}
|
|
702
713
|
return parsed;
|
|
703
714
|
}
|
|
715
|
+
function loadConfigNonBlocking() {
|
|
716
|
+
let fd;
|
|
717
|
+
try {
|
|
718
|
+
fd = openSync(getConfigPath(), constants.O_RDONLY | constants.O_NONBLOCK);
|
|
719
|
+
const file = fstatSync(fd);
|
|
720
|
+
if (!file.isFile() || file.size > MAX_BACKGROUND_CONFIG_BYTES)
|
|
721
|
+
return;
|
|
722
|
+
const content = Buffer.alloc(MAX_BACKGROUND_CONFIG_BYTES);
|
|
723
|
+
const bytesRead = readSync(fd, content, 0, content.byteLength, 0);
|
|
724
|
+
return parseConfig(JSON.parse(content.subarray(0, bytesRead).toString("utf8")));
|
|
725
|
+
} catch {
|
|
726
|
+
return;
|
|
727
|
+
} finally {
|
|
728
|
+
if (fd !== undefined) {
|
|
729
|
+
try {
|
|
730
|
+
closeSync(fd);
|
|
731
|
+
} catch {}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
704
735
|
function parseConfig(raw) {
|
|
705
736
|
if (isConfigV2(raw))
|
|
706
737
|
return normalizeV2(raw);
|
|
@@ -796,8 +827,10 @@ function stringValue2(value) {
|
|
|
796
827
|
function numberValue2(value) {
|
|
797
828
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
798
829
|
}
|
|
830
|
+
var MAX_BACKGROUND_CONFIG_BYTES;
|
|
799
831
|
var init_config = __esm(() => {
|
|
800
832
|
init_config_v1_migration();
|
|
833
|
+
MAX_BACKGROUND_CONFIG_BYTES = 64 * 1024;
|
|
801
834
|
});
|
|
802
835
|
|
|
803
836
|
// src/mcp/config-helpers.ts
|
|
@@ -1050,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
1050
1083
|
function getVersionString() {
|
|
1051
1084
|
return `v${VERSION}`;
|
|
1052
1085
|
}
|
|
1053
|
-
var VERSION = "0.
|
|
1086
|
+
var VERSION = "0.57.0", INSTALL_CHANNEL = "npm";
|
|
1054
1087
|
|
|
1055
1088
|
// src/debug/logger.ts
|
|
1056
1089
|
import {
|
|
@@ -1829,21 +1862,21 @@ var init_read = __esm(() => {
|
|
|
1829
1862
|
});
|
|
1830
1863
|
|
|
1831
1864
|
// src/sync/incognito.ts
|
|
1832
|
-
import { closeSync, fstatSync, openSync, readSync } from "node:fs";
|
|
1865
|
+
import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2 } from "node:fs";
|
|
1833
1866
|
function textHasIncognitoMarker(text) {
|
|
1834
1867
|
return text.includes(INCOGNITO_MARKER) || text.includes(COMMAND_NAME_MARKER);
|
|
1835
1868
|
}
|
|
1836
1869
|
function transcriptHasIncognitoMarker(path, maxBytes = MAX_SCAN_BYTES) {
|
|
1837
1870
|
let fd;
|
|
1838
1871
|
try {
|
|
1839
|
-
fd =
|
|
1840
|
-
const size = Math.min(
|
|
1872
|
+
fd = openSync2(path, "r");
|
|
1873
|
+
const size = Math.min(fstatSync2(fd).size, maxBytes);
|
|
1841
1874
|
if (size === 0)
|
|
1842
1875
|
return false;
|
|
1843
1876
|
const buffer = Buffer.allocUnsafe(size);
|
|
1844
1877
|
let offset = 0;
|
|
1845
1878
|
while (offset < size) {
|
|
1846
|
-
const read =
|
|
1879
|
+
const read = readSync2(fd, buffer, offset, size - offset, offset);
|
|
1847
1880
|
if (read === 0)
|
|
1848
1881
|
break;
|
|
1849
1882
|
offset += read;
|
|
@@ -1854,7 +1887,7 @@ function transcriptHasIncognitoMarker(path, maxBytes = MAX_SCAN_BYTES) {
|
|
|
1854
1887
|
} finally {
|
|
1855
1888
|
if (fd !== undefined) {
|
|
1856
1889
|
try {
|
|
1857
|
-
|
|
1890
|
+
closeSync2(fd);
|
|
1858
1891
|
} catch {}
|
|
1859
1892
|
}
|
|
1860
1893
|
}
|
|
@@ -1902,6 +1935,7 @@ function loadSyncState(configDir = getConfigDir()) {
|
|
|
1902
1935
|
const studiedSessions = Array.isArray(raw.mined_sessions) ? raw.mined_sessions.filter((record) => typeof record === "object" && record !== null && typeof record.at === "string" && typeof record.session === "string").map((record) => ({
|
|
1903
1936
|
at: record.at,
|
|
1904
1937
|
session: record.session,
|
|
1938
|
+
...typeof record.updated === "string" ? { updated: record.updated } : {},
|
|
1905
1939
|
...typeof record.project === "string" ? { project: record.project } : {}
|
|
1906
1940
|
})) : [];
|
|
1907
1941
|
const rawRefusal = raw.last_refusal;
|
|
@@ -4204,11 +4238,11 @@ var init_session_errors = __esm(() => {
|
|
|
4204
4238
|
// src/config/config-lock.ts
|
|
4205
4239
|
import { randomUUID } from "node:crypto";
|
|
4206
4240
|
import {
|
|
4207
|
-
closeSync as
|
|
4241
|
+
closeSync as closeSync3,
|
|
4208
4242
|
existsSync as existsSync8,
|
|
4209
4243
|
linkSync,
|
|
4210
4244
|
mkdirSync as mkdirSync5,
|
|
4211
|
-
openSync as
|
|
4245
|
+
openSync as openSync3,
|
|
4212
4246
|
readFileSync as readFileSync7,
|
|
4213
4247
|
statSync as statSync3,
|
|
4214
4248
|
unlinkSync,
|
|
@@ -4261,12 +4295,12 @@ async function acquireConfigRefreshLock(options) {
|
|
|
4261
4295
|
}
|
|
4262
4296
|
}
|
|
4263
4297
|
function createLockFile(lockPath, metadata) {
|
|
4264
|
-
const fd =
|
|
4298
|
+
const fd = openSync3(lockPath, "wx", 384);
|
|
4265
4299
|
try {
|
|
4266
4300
|
writeFileSync4(fd, JSON.stringify(metadata));
|
|
4267
4301
|
} catch (cause) {
|
|
4268
4302
|
try {
|
|
4269
|
-
|
|
4303
|
+
closeSync3(fd);
|
|
4270
4304
|
} catch {}
|
|
4271
4305
|
try {
|
|
4272
4306
|
unlinkSync(lockPath);
|
|
@@ -4274,7 +4308,7 @@ function createLockFile(lockPath, metadata) {
|
|
|
4274
4308
|
throw cause;
|
|
4275
4309
|
}
|
|
4276
4310
|
try {
|
|
4277
|
-
|
|
4311
|
+
closeSync3(fd);
|
|
4278
4312
|
} catch (cause) {
|
|
4279
4313
|
try {
|
|
4280
4314
|
unlinkSync(lockPath);
|
|
@@ -11820,12 +11854,12 @@ var init_integrations = __esm(() => {
|
|
|
11820
11854
|
|
|
11821
11855
|
// src/sessions/project-dir.ts
|
|
11822
11856
|
import {
|
|
11823
|
-
closeSync as
|
|
11857
|
+
closeSync as closeSync4,
|
|
11824
11858
|
existsSync as existsSync11,
|
|
11825
11859
|
mkdirSync as mkdirSync7,
|
|
11826
|
-
openSync as
|
|
11860
|
+
openSync as openSync4,
|
|
11827
11861
|
readFileSync as readFileSync11,
|
|
11828
|
-
readSync as
|
|
11862
|
+
readSync as readSync3,
|
|
11829
11863
|
renameSync as renameSync3,
|
|
11830
11864
|
statSync as statSync4,
|
|
11831
11865
|
writeFileSync as writeFileSync7
|
|
@@ -11858,18 +11892,18 @@ function saveCacheFile(configDir, entries) {
|
|
|
11858
11892
|
function readHead(path, bytes = HEAD_BYTES) {
|
|
11859
11893
|
let fd;
|
|
11860
11894
|
try {
|
|
11861
|
-
fd =
|
|
11895
|
+
fd = openSync4(path, "r");
|
|
11862
11896
|
} catch {
|
|
11863
11897
|
return null;
|
|
11864
11898
|
}
|
|
11865
11899
|
try {
|
|
11866
11900
|
const buf = Buffer.alloc(bytes);
|
|
11867
|
-
const read =
|
|
11901
|
+
const read = readSync3(fd, buf, 0, bytes, 0);
|
|
11868
11902
|
return buf.subarray(0, read).toString("utf-8");
|
|
11869
11903
|
} catch {
|
|
11870
11904
|
return null;
|
|
11871
11905
|
} finally {
|
|
11872
|
-
|
|
11906
|
+
closeSync4(fd);
|
|
11873
11907
|
}
|
|
11874
11908
|
}
|
|
11875
11909
|
function cwdFromJsonlHead(text) {
|
|
@@ -13429,6 +13463,27 @@ function batchWatermark(batch) {
|
|
|
13429
13463
|
}
|
|
13430
13464
|
return newest;
|
|
13431
13465
|
}
|
|
13466
|
+
function sessionKey(session) {
|
|
13467
|
+
return `${session.harness}/${session.id}`;
|
|
13468
|
+
}
|
|
13469
|
+
function studiedRecords(sessions, at) {
|
|
13470
|
+
return sessions.map((s) => ({
|
|
13471
|
+
at,
|
|
13472
|
+
session: sessionKey(s),
|
|
13473
|
+
updated: s.updated,
|
|
13474
|
+
...s.project ? { project: s.project } : {}
|
|
13475
|
+
}));
|
|
13476
|
+
}
|
|
13477
|
+
function lastStudiedSnapshot(history) {
|
|
13478
|
+
const latest = new Map;
|
|
13479
|
+
for (const record of history ?? []) {
|
|
13480
|
+
const updated = record.updated ? Date.parse(record.updated) : Number.NaN;
|
|
13481
|
+
if (!Number.isNaN(updated) && updated > (latest.get(record.session) ?? Number.NEGATIVE_INFINITY)) {
|
|
13482
|
+
latest.set(record.session, updated);
|
|
13483
|
+
}
|
|
13484
|
+
}
|
|
13485
|
+
return latest;
|
|
13486
|
+
}
|
|
13432
13487
|
async function runKnowledgeSync(options = {}) {
|
|
13433
13488
|
const deps = options.deps ?? {};
|
|
13434
13489
|
const loadState = deps.loadState ?? loadSyncState;
|
|
@@ -13511,14 +13566,20 @@ async function runKnowledgeSync(options = {}) {
|
|
|
13511
13566
|
}
|
|
13512
13567
|
const worthStudying = deps.worthStudying ?? isWorthStudying;
|
|
13513
13568
|
const isIncognito = deps.isIncognito ?? isIncognitoSession;
|
|
13569
|
+
const studiedSnapshot = lastStudiedSnapshot(state.mined_sessions);
|
|
13514
13570
|
const examined = [];
|
|
13515
13571
|
const batch = [];
|
|
13516
13572
|
let trivial = 0;
|
|
13517
13573
|
let incognito = 0;
|
|
13574
|
+
let alreadyStudied = 0;
|
|
13518
13575
|
for (let i = ready.length - 1;i >= 0 && batch.length < MINE_BATCH_LIMIT; i--) {
|
|
13519
13576
|
const candidate = ready[i];
|
|
13520
13577
|
examined.push(candidate);
|
|
13521
|
-
|
|
13578
|
+
const key = sessionKey(candidate);
|
|
13579
|
+
if (Date.parse(candidate.updated) <= (studiedSnapshot.get(key) ?? Number.NEGATIVE_INFINITY)) {
|
|
13580
|
+
alreadyStudied += 1;
|
|
13581
|
+
logger.debug("sync", `skipping already-studied session ${key}`);
|
|
13582
|
+
} else if (isIncognito(candidate)) {
|
|
13522
13583
|
incognito += 1;
|
|
13523
13584
|
logger.debug("sync", `skipping incognito session ${candidate.harness}/${candidate.id}`);
|
|
13524
13585
|
} else if (worthStudying(candidate)) {
|
|
@@ -13527,7 +13588,7 @@ async function runKnowledgeSync(options = {}) {
|
|
|
13527
13588
|
trivial += 1;
|
|
13528
13589
|
}
|
|
13529
13590
|
}
|
|
13530
|
-
const skippedNote = `${trivial} trivial, ${incognito} incognito skipped`;
|
|
13591
|
+
const skippedNote = `${trivial} trivial, ${incognito} incognito${alreadyStudied > 0 ? `, ${alreadyStudied} already studied` : ""} skipped`;
|
|
13531
13592
|
if (batch.length === 0) {
|
|
13532
13593
|
saveState({
|
|
13533
13594
|
...state,
|
|
@@ -13546,29 +13607,41 @@ async function runKnowledgeSync(options = {}) {
|
|
|
13546
13607
|
}
|
|
13547
13608
|
logger.debug("sync", `studying ${batch.length} of ${ready.length} ready sessions (${skippedNote})`);
|
|
13548
13609
|
const learner = await deps.mine(batch);
|
|
13610
|
+
const sessionTokens = deps.sessionTokens ?? estimateSessionTokens;
|
|
13611
|
+
const noted = new Set(learner.notedSessions ?? []);
|
|
13612
|
+
const notedBatch = batch.filter((s) => noted.has(sessionKey(s)));
|
|
13613
|
+
const partialProgress = (at) => {
|
|
13614
|
+
if (notedBatch.length === 0)
|
|
13615
|
+
return {};
|
|
13616
|
+
let tokens = 0;
|
|
13617
|
+
for (const s of notedBatch)
|
|
13618
|
+
tokens += sessionTokens(s);
|
|
13619
|
+
logger.debug("sync", `recorded ${notedBatch.length} noted sessions from the ${learner.outcome} run`);
|
|
13620
|
+
return {
|
|
13621
|
+
mined_sessions: [...state.mined_sessions ?? [], ...studiedRecords(notedBatch, at)].slice(-STUDIED_HISTORY_LIMIT),
|
|
13622
|
+
total_mined: (state.total_mined ?? 0) + notedBatch.length,
|
|
13623
|
+
total_notes: (state.total_notes ?? 0) + learner.notesWritten,
|
|
13624
|
+
total_learning_tokens: (state.total_learning_tokens ?? 0) + tokens
|
|
13625
|
+
};
|
|
13626
|
+
};
|
|
13549
13627
|
switch (learner.outcome) {
|
|
13550
13628
|
case "completed": {
|
|
13551
13629
|
for (const s of batch) {
|
|
13552
13630
|
logger.debug("sync", `studied session ${s.harness}/${s.id}`);
|
|
13553
13631
|
}
|
|
13554
|
-
const
|
|
13632
|
+
const completedAt = now().toISOString();
|
|
13555
13633
|
const history = [
|
|
13556
13634
|
...state.mined_sessions ?? [],
|
|
13557
|
-
...batch
|
|
13558
|
-
at: studiedAt,
|
|
13559
|
-
session: `${s.harness}/${s.id}`,
|
|
13560
|
-
...s.project ? { project: s.project } : {}
|
|
13561
|
-
}))
|
|
13635
|
+
...studiedRecords(batch, completedAt)
|
|
13562
13636
|
].slice(-STUDIED_HISTORY_LIMIT);
|
|
13563
13637
|
const watermark = batchWatermark(examined);
|
|
13564
|
-
const sessionTokens = deps.sessionTokens ?? estimateSessionTokens;
|
|
13565
13638
|
let batchTokens = 0;
|
|
13566
13639
|
for (const s of batch)
|
|
13567
13640
|
batchTokens += sessionTokens(s);
|
|
13568
13641
|
saveState({
|
|
13569
13642
|
...state,
|
|
13570
13643
|
watermark,
|
|
13571
|
-
last_attempt_at:
|
|
13644
|
+
last_attempt_at: completedAt,
|
|
13572
13645
|
consecutive_failures: 0,
|
|
13573
13646
|
mined_sessions: history,
|
|
13574
13647
|
total_mined: (state.total_mined ?? 0) + batch.length,
|
|
@@ -13588,10 +13661,12 @@ async function runKnowledgeSync(options = {}) {
|
|
|
13588
13661
|
}
|
|
13589
13662
|
case "consent_off":
|
|
13590
13663
|
case "credit_limit":
|
|
13591
|
-
case "quota_exceeded":
|
|
13664
|
+
case "quota_exceeded":
|
|
13665
|
+
case "claude_code_missing": {
|
|
13592
13666
|
const at = now().toISOString();
|
|
13593
13667
|
saveState({
|
|
13594
13668
|
...state,
|
|
13669
|
+
...partialProgress(at),
|
|
13595
13670
|
last_attempt_at: at,
|
|
13596
13671
|
consecutive_failures: 0,
|
|
13597
13672
|
last_refusal: {
|
|
@@ -13600,13 +13675,14 @@ async function runKnowledgeSync(options = {}) {
|
|
|
13600
13675
|
message: learner.message ?? "Studying unavailable right now."
|
|
13601
13676
|
}
|
|
13602
13677
|
});
|
|
13603
|
-
logger.debug("sync", `studying skipped
|
|
13678
|
+
logger.debug("sync", `studying skipped: ${learner.outcome}`);
|
|
13604
13679
|
return { status: "skipped-gateway", ...base, studiedSessions: 0, learner };
|
|
13605
13680
|
}
|
|
13606
13681
|
default: {
|
|
13607
13682
|
const at = now().toISOString();
|
|
13608
13683
|
saveState({
|
|
13609
13684
|
...state,
|
|
13685
|
+
...partialProgress(at),
|
|
13610
13686
|
last_attempt_at: at,
|
|
13611
13687
|
consecutive_failures: state.consecutive_failures + 1,
|
|
13612
13688
|
...learner.outcome === "gateway_rejected" && learner.message ? { last_refusal: { at, outcome: learner.outcome, message: learner.message } } : {}
|
|
@@ -13637,7 +13713,7 @@ var init_sync = __esm(() => {
|
|
|
13637
13713
|
});
|
|
13638
13714
|
|
|
13639
13715
|
// src/telemetry/debug-id.ts
|
|
13640
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
13716
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "6712b11a-8117-30cb-6475-6e2164756e21";
|
|
13641
13717
|
|
|
13642
13718
|
// src/telemetry/telemetry.ts
|
|
13643
13719
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -13862,12 +13938,19 @@ function consumeCommandFacets() {
|
|
|
13862
13938
|
function allowlisted(value, allowed) {
|
|
13863
13939
|
return typeof value === "string" && allowed.has(value) ? value : undefined;
|
|
13864
13940
|
}
|
|
13941
|
+
function matching(value, pattern) {
|
|
13942
|
+
return typeof value === "string" && pattern.test(value) ? value : undefined;
|
|
13943
|
+
}
|
|
13865
13944
|
function sanitizeFacets(facets) {
|
|
13866
13945
|
if (!facets || typeof facets !== "object")
|
|
13867
13946
|
return {};
|
|
13868
13947
|
const trigger = allowlisted(facets.sync_trigger, SYNC_TRIGGERS);
|
|
13869
13948
|
const status = allowlisted(facets.sync_status, SYNC_STATUSES);
|
|
13870
13949
|
const learner = allowlisted(facets.learner_outcome, LEARNER_OUTCOMES);
|
|
13950
|
+
const gatewayReason = allowlisted(facets.gateway_reason, GATEWAY_REASONS);
|
|
13951
|
+
const claudeSource = allowlisted(facets.claude_code_source, CLAUDE_CODE_SOURCES);
|
|
13952
|
+
const claudeVersion = matching(facets.claude_code_version, CLAUDE_CODE_VERSION_PATTERN);
|
|
13953
|
+
const model = matching(facets.learner_model, LEARNER_MODEL_PATTERN);
|
|
13871
13954
|
const backfill = allowlisted(facets.backfill_offer, BACKFILL_OFFERS);
|
|
13872
13955
|
return {
|
|
13873
13956
|
...trigger ? { sync_trigger: trigger } : {},
|
|
@@ -13875,6 +13958,10 @@ function sanitizeFacets(facets) {
|
|
|
13875
13958
|
...facets.sessions_studied !== undefined ? { sessions_studied: countBucket(facets.sessions_studied) } : {},
|
|
13876
13959
|
...facets.notes_written !== undefined ? { notes_written: countBucket(facets.notes_written) } : {},
|
|
13877
13960
|
...learner ? { learner_outcome: learner } : {},
|
|
13961
|
+
...gatewayReason ? { gateway_reason: gatewayReason } : {},
|
|
13962
|
+
...claudeSource ? { claude_code_source: claudeSource } : {},
|
|
13963
|
+
...claudeVersion ? { claude_code_version: claudeVersion } : {},
|
|
13964
|
+
...model ? { learner_model: model } : {},
|
|
13878
13965
|
...backfill ? { backfill_offer: backfill } : {}
|
|
13879
13966
|
};
|
|
13880
13967
|
}
|
|
@@ -13964,7 +14051,13 @@ function parseSentryDsn(value) {
|
|
|
13964
14051
|
return null;
|
|
13965
14052
|
}
|
|
13966
14053
|
}
|
|
13967
|
-
function sentryTags(command, context, runtime, error) {
|
|
14054
|
+
function sentryTags(command, context, runtime, error, facets) {
|
|
14055
|
+
const facetTags = {};
|
|
14056
|
+
for (const key of SENTRY_FACET_TAGS) {
|
|
14057
|
+
const value = facets[key];
|
|
14058
|
+
if (value)
|
|
14059
|
+
facetTags[key] = value;
|
|
14060
|
+
}
|
|
13968
14061
|
return {
|
|
13969
14062
|
schema_version: "1",
|
|
13970
14063
|
command,
|
|
@@ -13980,9 +14073,21 @@ function sentryTags(command, context, runtime, error) {
|
|
|
13980
14073
|
is_authenticated: String(context.isAuthenticated),
|
|
13981
14074
|
...error.code ? { error_code: error.code } : {},
|
|
13982
14075
|
...error.status ? { http_status: String(error.status) } : {},
|
|
13983
|
-
...error.exitCode === undefined ? {} : { exit_code: String(error.exitCode) }
|
|
14076
|
+
...error.exitCode === undefined ? {} : { exit_code: String(error.exitCode) },
|
|
14077
|
+
...facetTags
|
|
13984
14078
|
};
|
|
13985
14079
|
}
|
|
14080
|
+
function failedLearnerOutcome(facets) {
|
|
14081
|
+
return facets.learner_outcome === "completed" ? undefined : facets.learner_outcome;
|
|
14082
|
+
}
|
|
14083
|
+
function exceptionSummary(command, error, facets) {
|
|
14084
|
+
if (facets.learner_outcome === "completed")
|
|
14085
|
+
return error.code ?? error.type;
|
|
14086
|
+
const outcome = facets.learner_outcome ?? facets.sync_status;
|
|
14087
|
+
if (!outcome)
|
|
14088
|
+
return error.code ?? error.type;
|
|
14089
|
+
return `${command}: ${outcome}${facets.gateway_reason ? ` (${facets.gateway_reason})` : ""}`;
|
|
14090
|
+
}
|
|
13986
14091
|
function buildSentryEnvelope(input) {
|
|
13987
14092
|
const parsedDsn = parseSentryDsn(input.dsn);
|
|
13988
14093
|
if (!parsedDsn || !validEventId(input.eventId))
|
|
@@ -13990,6 +14095,7 @@ function buildSentryEnvelope(input) {
|
|
|
13990
14095
|
const context = normalizeContext(input.context);
|
|
13991
14096
|
const runtime = normalizeRuntime(input.runtime);
|
|
13992
14097
|
const command = canonicalCommand(input.command);
|
|
14098
|
+
const facets = sanitizeFacets(input.facets);
|
|
13993
14099
|
const debugId = validDebugId(input.debugId) ? input.debugId.toLowerCase() : undefined;
|
|
13994
14100
|
const error = {
|
|
13995
14101
|
type: validErrorType(input.error.type) ? input.error.type : "Error",
|
|
@@ -14009,7 +14115,7 @@ function buildSentryEnvelope(input) {
|
|
|
14009
14115
|
};
|
|
14010
14116
|
const exceptionValue = {
|
|
14011
14117
|
type: error.type,
|
|
14012
|
-
value:
|
|
14118
|
+
value: exceptionSummary(command, error, facets),
|
|
14013
14119
|
...error.frames.length > 0 ? { stacktrace: { frames: error.frames } } : {}
|
|
14014
14120
|
};
|
|
14015
14121
|
const newestFrame = error.frames.at(-1);
|
|
@@ -14022,7 +14128,7 @@ function buildSentryEnvelope(input) {
|
|
|
14022
14128
|
platform: "node",
|
|
14023
14129
|
level: "error",
|
|
14024
14130
|
release: `dosu-cli@${runtime.version}`,
|
|
14025
|
-
tags: sentryTags(command, context, runtime, error),
|
|
14131
|
+
tags: sentryTags(command, context, runtime, error, facets),
|
|
14026
14132
|
...context.user ? {
|
|
14027
14133
|
user: {
|
|
14028
14134
|
id: context.user.id,
|
|
@@ -14034,7 +14140,15 @@ function buildSentryEnvelope(input) {
|
|
|
14034
14140
|
images: [{ type: "sourcemap", code_file: BUNDLE_CODE_FILE, debug_id: debugId }]
|
|
14035
14141
|
}
|
|
14036
14142
|
} : {},
|
|
14037
|
-
fingerprint: [
|
|
14143
|
+
fingerprint: [
|
|
14144
|
+
"dosu-cli",
|
|
14145
|
+
command,
|
|
14146
|
+
error.type,
|
|
14147
|
+
error.code ?? "unknown",
|
|
14148
|
+
safeCallsite,
|
|
14149
|
+
...failedLearnerOutcome(facets) ? [facets.learner_outcome] : [],
|
|
14150
|
+
...facets.gateway_reason ? [facets.gateway_reason] : []
|
|
14151
|
+
],
|
|
14038
14152
|
exception: { values: [exceptionValue] }
|
|
14039
14153
|
};
|
|
14040
14154
|
const envelopeHeader = {
|
|
@@ -14275,15 +14389,17 @@ function createCommandTelemetry(settings, dependencies = {}) {
|
|
|
14275
14389
|
async function dispatch(result, exitCode, error) {
|
|
14276
14390
|
try {
|
|
14277
14391
|
const tasks = [];
|
|
14392
|
+
let facets;
|
|
14393
|
+
if (!disabled) {
|
|
14394
|
+
try {
|
|
14395
|
+
facets = resolveFacets();
|
|
14396
|
+
} catch {
|
|
14397
|
+
facets = undefined;
|
|
14398
|
+
}
|
|
14399
|
+
}
|
|
14278
14400
|
if (!disabled && analyticsToken) {
|
|
14279
14401
|
const id = context.user?.id ?? installId();
|
|
14280
14402
|
if (id) {
|
|
14281
|
-
let facets;
|
|
14282
|
-
try {
|
|
14283
|
-
facets = resolveFacets();
|
|
14284
|
-
} catch {
|
|
14285
|
-
facets = undefined;
|
|
14286
|
-
}
|
|
14287
14403
|
const payload = buildPostHogPayload({
|
|
14288
14404
|
apiKey: analyticsToken,
|
|
14289
14405
|
...context.user ? {} : { installId: id },
|
|
@@ -14311,14 +14427,16 @@ function createCommandTelemetry(settings, dependencies = {}) {
|
|
|
14311
14427
|
}
|
|
14312
14428
|
}
|
|
14313
14429
|
}
|
|
14314
|
-
|
|
14430
|
+
const sentryError = result === "failure" && error && shouldSendToSentry(error) ? error : result === "success" && sanitizeFacets(facets).sync_status === "mine-failed" ? { type: "LearnerRunFailed", frames: [] } : undefined;
|
|
14431
|
+
if (!disabled && sentryError && sentryDsn) {
|
|
14315
14432
|
const id = eventId(generateUuid);
|
|
14316
14433
|
const envelope = id ? buildSentryEnvelope({
|
|
14317
14434
|
dsn: sentryDsn,
|
|
14318
14435
|
command,
|
|
14319
14436
|
context,
|
|
14320
14437
|
runtime,
|
|
14321
|
-
error,
|
|
14438
|
+
error: sentryError,
|
|
14439
|
+
...facets ? { facets } : {},
|
|
14322
14440
|
eventId: id,
|
|
14323
14441
|
timestampMs: safeNow(now),
|
|
14324
14442
|
debugId: BUNDLE_DEBUG_ID_PLACEHOLDER
|
|
@@ -14370,7 +14488,7 @@ function createCommandTelemetry(settings, dependencies = {}) {
|
|
|
14370
14488
|
function shouldSendToSentry(error) {
|
|
14371
14489
|
return !["SESSION_EXPIRED", "SESSION_PERSISTENCE_ERROR"].includes(error.code ?? "");
|
|
14372
14490
|
}
|
|
14373
|
-
var REQUEST_TIMEOUT_MS = 500, MAX_RESPONSE_BYTES, MAX_STACK_FRAMES = 20, UNKNOWN_COMMAND = "unknown", FALLBACK_INSTALL_ID = "00000000-0000-4000-8000-000000000000", BUNDLE_CODE_FILE = "app:///bin/dosu.js", CLI_PACKAGE_ROOT, SAFE_ERROR_TYPES, SAFE_ERROR_CODES, SYNC_TRIGGERS, SYNC_STATUSES, LEARNER_OUTCOMES, BACKFILL_OFFERS, pendingFacets;
|
|
14491
|
+
var REQUEST_TIMEOUT_MS = 500, MAX_RESPONSE_BYTES, MAX_STACK_FRAMES = 20, UNKNOWN_COMMAND = "unknown", FALLBACK_INSTALL_ID = "00000000-0000-4000-8000-000000000000", BUNDLE_CODE_FILE = "app:///bin/dosu.js", CLI_PACKAGE_ROOT, SAFE_ERROR_TYPES, SAFE_ERROR_CODES, SYNC_TRIGGERS, SYNC_STATUSES, LEARNER_OUTCOMES, GATEWAY_REASONS, CLAUDE_CODE_SOURCES, CLAUDE_CODE_VERSION_PATTERN, LEARNER_MODEL_PATTERN, BACKFILL_OFFERS, SENTRY_FACET_TAGS, pendingFacets;
|
|
14374
14492
|
var init_telemetry = __esm(() => {
|
|
14375
14493
|
MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
14376
14494
|
CLI_PACKAGE_ROOT = detectCliPackageRoot();
|
|
@@ -14381,6 +14499,7 @@ var init_telemetry = __esm(() => {
|
|
|
14381
14499
|
"CliUsageError",
|
|
14382
14500
|
"CommandExitError",
|
|
14383
14501
|
"Error",
|
|
14502
|
+
"LearnerRunFailed",
|
|
14384
14503
|
"OAuthCallbackError",
|
|
14385
14504
|
"RangeError",
|
|
14386
14505
|
"ReferenceError",
|
|
@@ -14474,8 +14593,21 @@ var init_telemetry = __esm(() => {
|
|
|
14474
14593
|
"credit_limit",
|
|
14475
14594
|
"quota_exceeded",
|
|
14476
14595
|
"gateway_rejected",
|
|
14596
|
+
"claude_code_missing",
|
|
14477
14597
|
"error"
|
|
14478
14598
|
]);
|
|
14599
|
+
GATEWAY_REASONS = new Set([
|
|
14600
|
+
"system_role_unsupported",
|
|
14601
|
+
"adaptive_thinking_unsupported",
|
|
14602
|
+
"effort_unsupported",
|
|
14603
|
+
"unsupported_request",
|
|
14604
|
+
"max_tokens",
|
|
14605
|
+
"context_length",
|
|
14606
|
+
"other"
|
|
14607
|
+
]);
|
|
14608
|
+
CLAUDE_CODE_SOURCES = new Set(["sdk", "system", "missing"]);
|
|
14609
|
+
CLAUDE_CODE_VERSION_PATTERN = /^\d{1,4}\.\d{1,4}\.\d{1,6}(?:-[0-9A-Za-z]{1,16}(?:\.[0-9A-Za-z]{1,16}){0,3})?$/;
|
|
14610
|
+
LEARNER_MODEL_PATTERN = /^claude-[a-z0-9.-]{1,56}$/;
|
|
14479
14611
|
BACKFILL_OFFERS = new Set([
|
|
14480
14612
|
"not-offered",
|
|
14481
14613
|
"accepted",
|
|
@@ -14483,6 +14615,15 @@ var init_telemetry = __esm(() => {
|
|
|
14483
14615
|
"cancelled",
|
|
14484
14616
|
"spawn-failed"
|
|
14485
14617
|
]);
|
|
14618
|
+
SENTRY_FACET_TAGS = [
|
|
14619
|
+
"sync_trigger",
|
|
14620
|
+
"sync_status",
|
|
14621
|
+
"learner_outcome",
|
|
14622
|
+
"gateway_reason",
|
|
14623
|
+
"claude_code_source",
|
|
14624
|
+
"claude_code_version",
|
|
14625
|
+
"learner_model"
|
|
14626
|
+
];
|
|
14486
14627
|
});
|
|
14487
14628
|
|
|
14488
14629
|
// src/commands/agent-select.ts
|
|
@@ -15073,12 +15214,14 @@ function buildLearnerEnv(options) {
|
|
|
15073
15214
|
const headers = [
|
|
15074
15215
|
`x-dosu-run-id: ${options.runID}`,
|
|
15075
15216
|
`x-dosu-trigger: ${options.trigger}`,
|
|
15076
|
-
`x-dosu-cli-version: ${options.cliVersion}
|
|
15217
|
+
`x-dosu-cli-version: ${options.cliVersion}`,
|
|
15218
|
+
`x-dosu-expected-model: ${options.model}`
|
|
15077
15219
|
];
|
|
15078
15220
|
if (options.deploymentID)
|
|
15079
15221
|
headers.push(`x-dosu-deployment-id: ${options.deploymentID}`);
|
|
15080
15222
|
env.ANTHROPIC_BASE_URL = options.gatewayURL;
|
|
15081
15223
|
env.ANTHROPIC_AUTH_TOKEN = options.apiKey;
|
|
15224
|
+
env.ANTHROPIC_MODEL = options.model;
|
|
15082
15225
|
env.ANTHROPIC_CUSTOM_HEADERS = headers.join(`
|
|
15083
15226
|
`);
|
|
15084
15227
|
env.CLAUDE_CONFIG_DIR = options.configDir;
|
|
@@ -15095,7 +15238,7 @@ var init_env = __esm(() => {
|
|
|
15095
15238
|
});
|
|
15096
15239
|
|
|
15097
15240
|
// src/learner/executable.ts
|
|
15098
|
-
import { accessSync, constants, existsSync as existsSync16 } from "node:fs";
|
|
15241
|
+
import { accessSync, constants as constants2, existsSync as existsSync16 } from "node:fs";
|
|
15099
15242
|
import { createRequire as createRequire3 } from "node:module";
|
|
15100
15243
|
import { homedir as homedir6 } from "node:os";
|
|
15101
15244
|
import { delimiter as delimiter2, dirname as dirname6, join as join16 } from "node:path";
|
|
@@ -15114,7 +15257,7 @@ function sdkNativeBinaryExists() {
|
|
|
15114
15257
|
}
|
|
15115
15258
|
function isExecutable(path) {
|
|
15116
15259
|
try {
|
|
15117
|
-
accessSync(path,
|
|
15260
|
+
accessSync(path, constants2.X_OK);
|
|
15118
15261
|
return true;
|
|
15119
15262
|
} catch {
|
|
15120
15263
|
return false;
|
|
@@ -15136,11 +15279,44 @@ function findSystemClaude(env = process.env, homeDir = homedir6()) {
|
|
|
15136
15279
|
function resolveClaudeExecutable(options = {}) {
|
|
15137
15280
|
const hasSdkBinary = options.sdkBinaryExists ?? sdkNativeBinaryExists;
|
|
15138
15281
|
if (hasSdkBinary())
|
|
15139
|
-
return;
|
|
15140
|
-
|
|
15282
|
+
return { kind: "sdk" };
|
|
15283
|
+
const path = findSystemClaude(options.env, options.homeDir);
|
|
15284
|
+
return path ? { kind: "system", path } : { kind: "missing" };
|
|
15141
15285
|
}
|
|
15142
15286
|
var init_executable = () => {};
|
|
15143
15287
|
|
|
15288
|
+
// src/learner/model.ts
|
|
15289
|
+
async function resolveServedModel(options) {
|
|
15290
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
15291
|
+
try {
|
|
15292
|
+
const base = options.gatewayURL.replace(/\/+$/, "");
|
|
15293
|
+
const resp = await fetchImpl(`${base}/capabilities`, {
|
|
15294
|
+
method: "GET",
|
|
15295
|
+
headers: { Authorization: `Bearer ${options.apiKey}` },
|
|
15296
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? CAPABILITIES_TIMEOUT_MS)
|
|
15297
|
+
});
|
|
15298
|
+
if (!resp.ok) {
|
|
15299
|
+
logger.debug("learner", `gateway capabilities returned ${resp.status}; using default model`);
|
|
15300
|
+
return DEFAULT_LEARNER_MODEL;
|
|
15301
|
+
}
|
|
15302
|
+
const body = await resp.json();
|
|
15303
|
+
const model = body?.model;
|
|
15304
|
+
if (typeof model === "string" && CLAUDE_MODEL_PATTERN.test(model))
|
|
15305
|
+
return model;
|
|
15306
|
+
logger.debug("learner", "gateway capabilities named no usable model; using default model");
|
|
15307
|
+
return DEFAULT_LEARNER_MODEL;
|
|
15308
|
+
} catch (error) {
|
|
15309
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
15310
|
+
logger.debug("learner", `gateway capabilities failed (${text}); using default model`);
|
|
15311
|
+
return DEFAULT_LEARNER_MODEL;
|
|
15312
|
+
}
|
|
15313
|
+
}
|
|
15314
|
+
var DEFAULT_LEARNER_MODEL = "claude-haiku-4-5", CAPABILITIES_TIMEOUT_MS = 5000, CLAUDE_MODEL_PATTERN;
|
|
15315
|
+
var init_model = __esm(() => {
|
|
15316
|
+
init_logger();
|
|
15317
|
+
CLAUDE_MODEL_PATTERN = /^claude-[a-z0-9.-]+$/;
|
|
15318
|
+
});
|
|
15319
|
+
|
|
15144
15320
|
// src/learner/prompt.ts
|
|
15145
15321
|
function buildLearnerSystemPrompt(coreRules) {
|
|
15146
15322
|
return `You are Dosu's knowledge learner. You read a developer's recent coding-agent sessions and save the durable, non-obvious findings to the team's shared knowledge base so future teammates and agents do not have to rediscover them.
|
|
@@ -58104,6 +58280,13 @@ function snippet(value) {
|
|
|
58104
58280
|
const flat = (text ?? "").replace(/\s+/g, " ").trim();
|
|
58105
58281
|
return flat.length > TRACE_SNIPPET_LIMIT ? `${flat.slice(0, TRACE_SNIPPET_LIMIT)}…` : flat;
|
|
58106
58282
|
}
|
|
58283
|
+
function classifyRejectionReason(detail) {
|
|
58284
|
+
for (const [pattern, reason] of REJECTION_REASONS) {
|
|
58285
|
+
if (pattern.test(detail))
|
|
58286
|
+
return reason;
|
|
58287
|
+
}
|
|
58288
|
+
return "other";
|
|
58289
|
+
}
|
|
58107
58290
|
function classifyGatewayRejection(text) {
|
|
58108
58291
|
const match = API_400_PATTERN.exec(text);
|
|
58109
58292
|
if (!match)
|
|
@@ -58116,7 +58299,8 @@ function classifyGatewayRejection(text) {
|
|
|
58116
58299
|
} catch {}
|
|
58117
58300
|
return {
|
|
58118
58301
|
outcome: "gateway_rejected",
|
|
58119
|
-
message: `LLM gateway rejected the study run: ${snippet(detail)}
|
|
58302
|
+
message: `LLM gateway rejected the study run: ${snippet(detail)}`,
|
|
58303
|
+
reason: classifyRejectionReason(detail.trim())
|
|
58120
58304
|
};
|
|
58121
58305
|
}
|
|
58122
58306
|
function traceAgentMessage(message) {
|
|
@@ -58164,11 +58348,26 @@ async function runLearner(options) {
|
|
|
58164
58348
|
message: "LLM gateway URL is not set. From source, use `bun run dev` (production endpoints) or `bun run dev:local` (local stack)."
|
|
58165
58349
|
};
|
|
58166
58350
|
}
|
|
58167
|
-
await Promise.resolve().then(() => init_sdk());
|
|
58168
58351
|
const claudeExecutable = resolveClaudeExecutable();
|
|
58169
|
-
if (claudeExecutable) {
|
|
58170
|
-
|
|
58352
|
+
if (claudeExecutable.kind === "missing") {
|
|
58353
|
+
return {
|
|
58354
|
+
outcome: "claude_code_missing",
|
|
58355
|
+
notesWritten: 0,
|
|
58356
|
+
turns: 0,
|
|
58357
|
+
claudeCodeSource: "missing",
|
|
58358
|
+
message: "Studying runs on Claude Code, which isn't installed here. Install Claude Code, then run `dosu knowledge sync`."
|
|
58359
|
+
};
|
|
58171
58360
|
}
|
|
58361
|
+
if (claudeExecutable.kind === "system") {
|
|
58362
|
+
logger.debug("learner", `using system Claude Code executable: ${claudeExecutable.path}`);
|
|
58363
|
+
}
|
|
58364
|
+
const model = await resolveServedModel({ gatewayURL, apiKey: options.apiKey });
|
|
58365
|
+
logger.debug("learner", `study run model: ${model}`);
|
|
58366
|
+
const diagnostics = {
|
|
58367
|
+
claudeCodeSource: claudeExecutable.kind,
|
|
58368
|
+
model
|
|
58369
|
+
};
|
|
58370
|
+
await Promise.resolve().then(() => init_sdk());
|
|
58172
58371
|
const configDir = createRunConfigDir();
|
|
58173
58372
|
const runID = options.runID ?? crypto.randomUUID();
|
|
58174
58373
|
const sessionStartedAt = options.sessions.map((s) => s.updated).sort()[0];
|
|
@@ -58179,7 +58378,19 @@ async function runLearner(options) {
|
|
|
58179
58378
|
let notesWritten = 0;
|
|
58180
58379
|
let currentSession;
|
|
58181
58380
|
const readsSinceWrite = new Set;
|
|
58381
|
+
const sessionKeys = new Map(options.sessions.map((s) => [s.id, `${s.harness}/${s.id}`]));
|
|
58382
|
+
const notedSessions = new Set;
|
|
58383
|
+
const pendingNotes = new Map;
|
|
58182
58384
|
let turns = 0;
|
|
58385
|
+
const finish = (outcome, message, gatewayReason) => ({
|
|
58386
|
+
outcome,
|
|
58387
|
+
notesWritten,
|
|
58388
|
+
notedSessions: [...notedSessions],
|
|
58389
|
+
turns,
|
|
58390
|
+
...message === undefined ? {} : { message },
|
|
58391
|
+
...gatewayReason ? { gatewayReason } : {},
|
|
58392
|
+
...diagnostics
|
|
58393
|
+
});
|
|
58183
58394
|
const env = buildLearnerEnv({
|
|
58184
58395
|
apiKey: options.apiKey,
|
|
58185
58396
|
gatewayURL,
|
|
@@ -58187,19 +58398,21 @@ async function runLearner(options) {
|
|
|
58187
58398
|
runID,
|
|
58188
58399
|
trigger: options.trigger,
|
|
58189
58400
|
cliVersion: getVersionString(),
|
|
58190
|
-
deploymentID: options.deploymentID
|
|
58401
|
+
deploymentID: options.deploymentID,
|
|
58402
|
+
model
|
|
58191
58403
|
});
|
|
58192
58404
|
try {
|
|
58193
58405
|
const run = PGt({
|
|
58194
58406
|
prompt: buildLearnerPrompt(options.sessions),
|
|
58195
58407
|
options: {
|
|
58196
58408
|
systemPrompt: buildLearnerSystemPrompt(LEARNER_CORE_RULES),
|
|
58409
|
+
model,
|
|
58197
58410
|
env,
|
|
58198
58411
|
abortController: abort,
|
|
58199
58412
|
maxTurns: options.maxTurns ?? DEFAULT_MAX_TURNS,
|
|
58200
58413
|
settingSources: [],
|
|
58201
58414
|
persistSession: false,
|
|
58202
|
-
...claudeExecutable ? { pathToClaudeCodeExecutable: claudeExecutable } : {},
|
|
58415
|
+
...claudeExecutable.kind === "system" ? { pathToClaudeCodeExecutable: claudeExecutable.path } : {},
|
|
58203
58416
|
sandbox: { enabled: true, failIfUnavailable: false },
|
|
58204
58417
|
mcpServers: {
|
|
58205
58418
|
[SESSIONS_SERVER_NAME]: createSessionToolsServer(options.sessions),
|
|
@@ -58215,7 +58428,7 @@ async function runLearner(options) {
|
|
|
58215
58428
|
}
|
|
58216
58429
|
},
|
|
58217
58430
|
stderr: (data) => logger.debug("learner", `[sdk] ${data}`),
|
|
58218
|
-
canUseTool: async (toolName, input) => {
|
|
58431
|
+
canUseTool: async (toolName, input, { toolUseID }) => {
|
|
58219
58432
|
if (!allowed.has(toolName)) {
|
|
58220
58433
|
return {
|
|
58221
58434
|
behavior: "deny",
|
|
@@ -58246,6 +58459,9 @@ async function runLearner(options) {
|
|
|
58246
58459
|
}
|
|
58247
58460
|
notesWritten += 1;
|
|
58248
58461
|
readsSinceWrite.clear();
|
|
58462
|
+
const noted = currentSession && sessionKeys.get(currentSession);
|
|
58463
|
+
if (noted)
|
|
58464
|
+
pendingNotes.set(toolUseID, noted);
|
|
58249
58465
|
const { transcript_id: _authoredByModel, ...clean } = input;
|
|
58250
58466
|
return {
|
|
58251
58467
|
behavior: "allow",
|
|
@@ -58258,56 +58474,46 @@ async function runLearner(options) {
|
|
|
58258
58474
|
});
|
|
58259
58475
|
for await (const message of run) {
|
|
58260
58476
|
traceAgentMessage(message);
|
|
58477
|
+
if (message.type === "user" && Array.isArray(message.message.content)) {
|
|
58478
|
+
for (const block of message.message.content) {
|
|
58479
|
+
const noted = block.type === "tool_result" && pendingNotes.get(block.tool_use_id);
|
|
58480
|
+
if (noted && block.is_error !== true)
|
|
58481
|
+
notedSessions.add(noted);
|
|
58482
|
+
}
|
|
58483
|
+
}
|
|
58484
|
+
if (message.type === "system" && message.subtype === "init" && typeof message.claude_code_version === "string") {
|
|
58485
|
+
diagnostics.claudeCodeVersion = message.claude_code_version;
|
|
58486
|
+
}
|
|
58261
58487
|
if (message.type === "result") {
|
|
58262
58488
|
turns = message.num_turns;
|
|
58263
58489
|
const text = message.subtype === "success" ? message.result : message.subtype;
|
|
58264
58490
|
const gatewayError = classifyGatewayError(text ?? "") ?? (message.is_error ? classifyGatewayRejection(text ?? "") : null);
|
|
58265
58491
|
if (gatewayError) {
|
|
58266
|
-
return
|
|
58267
|
-
outcome: gatewayError.outcome,
|
|
58268
|
-
notesWritten,
|
|
58269
|
-
turns,
|
|
58270
|
-
message: gatewayError.message
|
|
58271
|
-
};
|
|
58492
|
+
return finish(gatewayError.outcome, gatewayError.message, gatewayError.reason);
|
|
58272
58493
|
}
|
|
58273
58494
|
if (message.subtype !== "success" || message.is_error) {
|
|
58274
58495
|
logger.debug("learner", `run ${runID} failed: ${text}`);
|
|
58275
|
-
return
|
|
58276
|
-
outcome: "error",
|
|
58277
|
-
notesWritten,
|
|
58278
|
-
turns,
|
|
58279
|
-
message: "Study run failed; see debug log for details."
|
|
58280
|
-
};
|
|
58496
|
+
return finish("error", "Study run failed; see debug log for details.");
|
|
58281
58497
|
}
|
|
58282
58498
|
logger.debug("learner", `run ${runID} completed: ${turns} turns, ${notesWritten} suggested pages`);
|
|
58283
|
-
return
|
|
58499
|
+
return finish("completed", text);
|
|
58284
58500
|
}
|
|
58285
58501
|
}
|
|
58286
|
-
return
|
|
58287
|
-
outcome: "error",
|
|
58288
|
-
notesWritten,
|
|
58289
|
-
turns,
|
|
58290
|
-
message: "Study run ended without a result."
|
|
58291
|
-
};
|
|
58502
|
+
return finish("error", "Study run ended without a result.");
|
|
58292
58503
|
} catch (error) {
|
|
58293
58504
|
const text = error instanceof Error ? error.message : String(error);
|
|
58294
58505
|
const gatewayError = classifyGatewayError(text) ?? classifyGatewayRejection(text);
|
|
58295
58506
|
if (gatewayError) {
|
|
58296
|
-
return
|
|
58507
|
+
return finish(gatewayError.outcome, gatewayError.message, gatewayError.reason);
|
|
58297
58508
|
}
|
|
58298
58509
|
logger.debug("learner", `run ${runID} threw: ${text}`);
|
|
58299
|
-
return
|
|
58300
|
-
outcome: "error",
|
|
58301
|
-
notesWritten,
|
|
58302
|
-
turns,
|
|
58303
|
-
message: abort.signal.aborted ? "Study run timed out and was aborted." : "Study run failed; see debug log for details."
|
|
58304
|
-
};
|
|
58510
|
+
return finish("error", abort.signal.aborted ? "Study run timed out and was aborted." : "Study run failed; see debug log for details.");
|
|
58305
58511
|
} finally {
|
|
58306
58512
|
clearTimeout(timer);
|
|
58307
58513
|
configDir.cleanup();
|
|
58308
58514
|
}
|
|
58309
58515
|
}
|
|
58310
|
-
var DEFAULT_MAX_TURNS = 160, DEFAULT_MAX_NOTES = 80, DEFAULT_TIMEOUT_MS2, KNOWLEDGE_SERVER_NAME = "dosu", GATEWAY_ERRORS, TRACE_SNIPPET_LIMIT = 400, API_400_PATTERN;
|
|
58516
|
+
var DEFAULT_MAX_TURNS = 160, DEFAULT_MAX_NOTES = 80, DEFAULT_TIMEOUT_MS2, KNOWLEDGE_SERVER_NAME = "dosu", GATEWAY_ERRORS, TRACE_SNIPPET_LIMIT = 400, REJECTION_REASONS, API_400_PATTERN;
|
|
58311
58517
|
var init_runner = __esm(() => {
|
|
58312
58518
|
init_logger();
|
|
58313
58519
|
init_config_helpers();
|
|
@@ -58316,6 +58522,7 @@ var init_runner = __esm(() => {
|
|
|
58316
58522
|
init_conflicts();
|
|
58317
58523
|
init_env();
|
|
58318
58524
|
init_executable();
|
|
58525
|
+
init_model();
|
|
58319
58526
|
init_tools();
|
|
58320
58527
|
DEFAULT_TIMEOUT_MS2 = 30 * 60 * 1000;
|
|
58321
58528
|
GATEWAY_ERRORS = {
|
|
@@ -58332,6 +58539,14 @@ var init_runner = __esm(() => {
|
|
|
58332
58539
|
message: "Daily Dosu Remote Sessions budget reached; runs resume tomorrow."
|
|
58333
58540
|
}
|
|
58334
58541
|
};
|
|
58542
|
+
REJECTION_REASONS = [
|
|
58543
|
+
[/^dosu_unsupported_request:/, "unsupported_request"],
|
|
58544
|
+
[/\beffort\b|output_config/i, "effort_unsupported"],
|
|
58545
|
+
[/\brole\b.*\bsystem\b|\bsystem\b.*\brole\b|messages\.\d+\.role/i, "system_role_unsupported"],
|
|
58546
|
+
[/\badaptive\b/i, "adaptive_thinking_unsupported"],
|
|
58547
|
+
[/prompt is too long|context (?:limit|length|window)/i, "context_length"],
|
|
58548
|
+
[/max_tokens/i, "max_tokens"]
|
|
58549
|
+
];
|
|
58335
58550
|
API_400_PATTERN = /API Error: 400\b\s*(.*)/s;
|
|
58336
58551
|
});
|
|
58337
58552
|
|
|
@@ -58495,7 +58710,7 @@ ${results.length - opts.limit} more results not shown.`));
|
|
|
58495
58710
|
sync_status: outcome.status,
|
|
58496
58711
|
sessions_studied: sessionsStudied,
|
|
58497
58712
|
notes_written: notesWritten,
|
|
58498
|
-
...outcome.learner ?
|
|
58713
|
+
...outcome.learner ? learnerFacets(outcome.learner) : {}
|
|
58499
58714
|
});
|
|
58500
58715
|
if (opts.quiet)
|
|
58501
58716
|
return;
|
|
@@ -58555,6 +58770,15 @@ ${results.length - opts.limit} more results not shown.`));
|
|
|
58555
58770
|
cmd.addCommand(statuslineCommand2());
|
|
58556
58771
|
return cmd;
|
|
58557
58772
|
}
|
|
58773
|
+
function learnerFacets(learner) {
|
|
58774
|
+
return {
|
|
58775
|
+
learner_outcome: learner.outcome,
|
|
58776
|
+
...learner.gatewayReason ? { gateway_reason: learner.gatewayReason } : {},
|
|
58777
|
+
...learner.claudeCodeSource ? { claude_code_source: learner.claudeCodeSource } : {},
|
|
58778
|
+
...learner.claudeCodeVersion ? { claude_code_version: learner.claudeCodeVersion } : {},
|
|
58779
|
+
...learner.model ? { learner_model: learner.model } : {}
|
|
58780
|
+
};
|
|
58781
|
+
}
|
|
58558
58782
|
function buildLearner(trigger) {
|
|
58559
58783
|
const cfg = loadConfig();
|
|
58560
58784
|
if (cfg.mode === "oss")
|
|
@@ -60533,6 +60757,10 @@ function runUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
|
60533
60757
|
}
|
|
60534
60758
|
manager = owningPackageManager(options.entrypoint ?? process.argv[1], platform, options.comSpec, env, cwd);
|
|
60535
60759
|
if (!manager) {
|
|
60760
|
+
if (env.DOSU_DEV === "true") {
|
|
60761
|
+
console.log("DOSU_DEV=true and this copy is not a global package: skipping the package install.");
|
|
60762
|
+
return 0;
|
|
60763
|
+
}
|
|
60536
60764
|
printNonGlobalPackageGuidance();
|
|
60537
60765
|
return 1;
|
|
60538
60766
|
}
|
|
@@ -60565,6 +60793,41 @@ Could not update Dosu automatically.`);
|
|
|
60565
60793
|
console.log('Run "dosu --version" to verify.');
|
|
60566
60794
|
return 0;
|
|
60567
60795
|
}
|
|
60796
|
+
function postUpgradeArgs(interactive) {
|
|
60797
|
+
return interactive ? ["setup"] : ["mcp", "refresh"];
|
|
60798
|
+
}
|
|
60799
|
+
function newBinaryInvocation(channel, args, entrypoint = process.argv[1], execPath = process.execPath) {
|
|
60800
|
+
if (channel === "npm") {
|
|
60801
|
+
return entrypoint ? { command: execPath, args: [entrypoint, ...args] } : null;
|
|
60802
|
+
}
|
|
60803
|
+
if (channel === "homebrew") {
|
|
60804
|
+
return { command: "dosu", args };
|
|
60805
|
+
}
|
|
60806
|
+
return null;
|
|
60807
|
+
}
|
|
60808
|
+
function isInteractiveTerminal() {
|
|
60809
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
60810
|
+
}
|
|
60811
|
+
function setupAgentsWithNewBinary(channel, options) {
|
|
60812
|
+
const interactive = options.interactive ?? isInteractiveTerminal();
|
|
60813
|
+
const invocation = newBinaryInvocation(channel, postUpgradeArgs(interactive), options.entrypoint ?? process.argv[1]);
|
|
60814
|
+
if (!invocation) {
|
|
60815
|
+
console.error(SETUP_FALLBACK);
|
|
60816
|
+
return;
|
|
60817
|
+
}
|
|
60818
|
+
console.log(interactive ? `
|
|
60819
|
+
Running setup with the new version to update your AI agents...
|
|
60820
|
+
` : `
|
|
60821
|
+
Refreshing agent MCP configs with the new version...`);
|
|
60822
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
60823
|
+
cwd: options.cwd ?? homedir9(),
|
|
60824
|
+
shell: false,
|
|
60825
|
+
stdio: "inherit"
|
|
60826
|
+
});
|
|
60827
|
+
if (result.error || result.status !== 0) {
|
|
60828
|
+
console.error(SETUP_FALLBACK);
|
|
60829
|
+
}
|
|
60830
|
+
}
|
|
60568
60831
|
async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
60569
60832
|
const status = runUpgrade(channel, options);
|
|
60570
60833
|
if (status !== 0)
|
|
@@ -60580,16 +60843,17 @@ async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
|
60580
60843
|
} catch {
|
|
60581
60844
|
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
60582
60845
|
}
|
|
60846
|
+
setupAgentsWithNewBinary(channel, options);
|
|
60583
60847
|
return 0;
|
|
60584
60848
|
}
|
|
60585
60849
|
function upgradeCommand() {
|
|
60586
|
-
return new Command("upgrade").description("Update Dosu to the latest version
|
|
60850
|
+
return new Command("upgrade").description("Update Dosu to the latest version, then re-run setup to update your AI agents").action(async () => {
|
|
60587
60851
|
const status = await completeUpgrade();
|
|
60588
60852
|
if (status !== 0)
|
|
60589
60853
|
process.exitCode = status;
|
|
60590
60854
|
});
|
|
60591
60855
|
}
|
|
60592
|
-
var import_picocolors31, PACKAGE_NAME = "@dosu/cli", LATEST_PACKAGE, BREW_MANUAL_COMMAND = "brew upgrade dosu-ai/dosu/dosu", NPX_COMMAND = "npx -y @dosu/cli@latest", PROBE_TIMEOUT_MS = 5000, RELEASES_URL = "https://github.com/dosu-ai/dosu-cli/releases/latest", PACKAGE_MANAGERS;
|
|
60856
|
+
var import_picocolors31, PACKAGE_NAME = "@dosu/cli", LATEST_PACKAGE, BREW_MANUAL_COMMAND = "brew upgrade dosu-ai/dosu/dosu", NPX_COMMAND = "npx -y @dosu/cli@latest", PROBE_TIMEOUT_MS = 5000, RELEASES_URL = "https://github.com/dosu-ai/dosu-cli/releases/latest", PACKAGE_MANAGERS, SETUP_FALLBACK = 'Run "dosu setup" to finish updating your AI agents.';
|
|
60593
60857
|
var init_upgrade = __esm(() => {
|
|
60594
60858
|
init_commander();
|
|
60595
60859
|
init_skill();
|
|
@@ -60615,7 +60879,7 @@ var init_upgrade = __esm(() => {
|
|
|
60615
60879
|
});
|
|
60616
60880
|
|
|
60617
60881
|
// src/debug/follow.ts
|
|
60618
|
-
import { closeSync as
|
|
60882
|
+
import { closeSync as closeSync6, openSync as openSync6, readSync as readSync5, statSync as statSync8 } from "node:fs";
|
|
60619
60883
|
function createLogFollower(path, emit) {
|
|
60620
60884
|
const sizeOf = () => {
|
|
60621
60885
|
try {
|
|
@@ -60633,15 +60897,15 @@ function createLogFollower(path, emit) {
|
|
|
60633
60897
|
if (size === offset)
|
|
60634
60898
|
return;
|
|
60635
60899
|
try {
|
|
60636
|
-
const fd =
|
|
60900
|
+
const fd = openSync6(path, "r");
|
|
60637
60901
|
try {
|
|
60638
60902
|
const buf = Buffer.alloc(size - offset);
|
|
60639
|
-
const read =
|
|
60903
|
+
const read = readSync5(fd, buf, 0, buf.length, offset);
|
|
60640
60904
|
offset += read;
|
|
60641
60905
|
if (read > 0)
|
|
60642
60906
|
emit(buf.toString("utf-8", 0, read));
|
|
60643
60907
|
} finally {
|
|
60644
|
-
|
|
60908
|
+
closeSync6(fd);
|
|
60645
60909
|
}
|
|
60646
60910
|
} catch {}
|
|
60647
60911
|
}
|
|
@@ -61319,6 +61583,36 @@ var init_providers = __esm(() => {
|
|
|
61319
61583
|
init_zed();
|
|
61320
61584
|
});
|
|
61321
61585
|
|
|
61586
|
+
// src/mcp/refresh.ts
|
|
61587
|
+
function configuredProviders() {
|
|
61588
|
+
return allSetupProviders().filter((provider) => {
|
|
61589
|
+
try {
|
|
61590
|
+
return provider.isInstalled() && provider.isConfigured();
|
|
61591
|
+
} catch {
|
|
61592
|
+
return false;
|
|
61593
|
+
}
|
|
61594
|
+
});
|
|
61595
|
+
}
|
|
61596
|
+
function refreshConfiguredProviders(cfg) {
|
|
61597
|
+
const result = { updated: [], failed: [] };
|
|
61598
|
+
for (const provider of configuredProviders()) {
|
|
61599
|
+
try {
|
|
61600
|
+
provider.install(cfg, true);
|
|
61601
|
+
logger.info("mcp", `Refreshed ${provider.name()} MCP entry`);
|
|
61602
|
+
result.updated.push(provider);
|
|
61603
|
+
} catch (err) {
|
|
61604
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
61605
|
+
logger.error("mcp", `Refresh failed for ${provider.name()}: ${error.message}`);
|
|
61606
|
+
result.failed.push({ provider, error });
|
|
61607
|
+
}
|
|
61608
|
+
}
|
|
61609
|
+
return result;
|
|
61610
|
+
}
|
|
61611
|
+
var init_refresh = __esm(() => {
|
|
61612
|
+
init_logger();
|
|
61613
|
+
init_providers();
|
|
61614
|
+
});
|
|
61615
|
+
|
|
61322
61616
|
// src/version/update-check.ts
|
|
61323
61617
|
import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
|
|
61324
61618
|
import { join as join39 } from "node:path";
|
|
@@ -61474,15 +61768,98 @@ var init_update_check = __esm(() => {
|
|
|
61474
61768
|
SEMVER_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
61475
61769
|
});
|
|
61476
61770
|
|
|
61771
|
+
// src/version/mcp-refresh-check.ts
|
|
61772
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
|
|
61773
|
+
import { join as join40 } from "node:path";
|
|
61774
|
+
function needsMcpRefresh(previous, current) {
|
|
61775
|
+
if (previous === null)
|
|
61776
|
+
return true;
|
|
61777
|
+
if (previous === current)
|
|
61778
|
+
return false;
|
|
61779
|
+
const [older, newer] = isNewerVersion(current, previous) ? [previous, current] : [current, previous];
|
|
61780
|
+
return MCP_FORMAT_CHANGES.some((change) => isNewerVersion(change, older) && !isNewerVersion(change, newer));
|
|
61781
|
+
}
|
|
61782
|
+
function getCachePath4() {
|
|
61783
|
+
return join40(getConfigDir(), CACHE_FILENAME5);
|
|
61784
|
+
}
|
|
61785
|
+
function readMcpRefreshCache() {
|
|
61786
|
+
try {
|
|
61787
|
+
const path = getCachePath4();
|
|
61788
|
+
if (!existsSync24(path))
|
|
61789
|
+
return null;
|
|
61790
|
+
const data = JSON.parse(readFileSync23(path, "utf-8"));
|
|
61791
|
+
if (typeof data?.version === "string")
|
|
61792
|
+
return { version: data.version };
|
|
61793
|
+
return null;
|
|
61794
|
+
} catch {
|
|
61795
|
+
return null;
|
|
61796
|
+
}
|
|
61797
|
+
}
|
|
61798
|
+
function writeMcpRefreshCache(cache) {
|
|
61799
|
+
try {
|
|
61800
|
+
const dir = getConfigDir();
|
|
61801
|
+
if (!existsSync24(dir)) {
|
|
61802
|
+
mkdirSync14(dir, { recursive: true, mode: 448 });
|
|
61803
|
+
}
|
|
61804
|
+
writeFileSync15(getCachePath4(), JSON.stringify(cache), { mode: 384 });
|
|
61805
|
+
} catch {}
|
|
61806
|
+
}
|
|
61807
|
+
function canRefreshMcp(cfg) {
|
|
61808
|
+
const target = cfg.active_account?.target;
|
|
61809
|
+
if (!target?.api_key)
|
|
61810
|
+
return false;
|
|
61811
|
+
return cfg.mode === MODE_OSS || Boolean(target.deployment_id);
|
|
61812
|
+
}
|
|
61813
|
+
function displayNotice3(names) {
|
|
61814
|
+
console.error(`
|
|
61815
|
+
${import_picocolors33.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
|
|
61816
|
+
` + `${import_picocolors33.default.dim(` Run ${import_picocolors33.default.cyan('"dosu setup"')} to also update skills, hooks, and rules, then restart your AI agents.`)}
|
|
61817
|
+
`);
|
|
61818
|
+
}
|
|
61819
|
+
function checkForMcpRefresh(options = {}) {
|
|
61820
|
+
const notify = options.notify ?? true;
|
|
61821
|
+
try {
|
|
61822
|
+
const previous = readMcpRefreshCache()?.version ?? null;
|
|
61823
|
+
if (previous === VERSION)
|
|
61824
|
+
return;
|
|
61825
|
+
if (!needsMcpRefresh(previous, VERSION)) {
|
|
61826
|
+
writeMcpRefreshCache({ version: VERSION });
|
|
61827
|
+
return;
|
|
61828
|
+
}
|
|
61829
|
+
const cfg = loadConfigNonBlocking();
|
|
61830
|
+
if (!cfg || !canRefreshMcp(cfg)) {
|
|
61831
|
+
logger.debug("mcp-refresh", "Skipping MCP refresh: no API key or deployment configured");
|
|
61832
|
+
return;
|
|
61833
|
+
}
|
|
61834
|
+
const result = refreshConfiguredProviders(cfg);
|
|
61835
|
+
writeMcpRefreshCache({ version: VERSION });
|
|
61836
|
+
logger.info("mcp-refresh", `Version ${VERSION}: refreshed ${result.updated.length}, failed ${result.failed.length}`);
|
|
61837
|
+
if (notify && result.updated.length > 0) {
|
|
61838
|
+
displayNotice3(result.updated.map((provider) => provider.name()));
|
|
61839
|
+
}
|
|
61840
|
+
} catch (err) {
|
|
61841
|
+
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
61842
|
+
}
|
|
61843
|
+
}
|
|
61844
|
+
var import_picocolors33, CACHE_FILENAME5 = "mcp-refresh.json", MCP_FORMAT_CHANGES;
|
|
61845
|
+
var init_mcp_refresh_check = __esm(() => {
|
|
61846
|
+
init_config();
|
|
61847
|
+
init_logger();
|
|
61848
|
+
init_refresh();
|
|
61849
|
+
init_update_check();
|
|
61850
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
61851
|
+
MCP_FORMAT_CHANGES = ["0.53.0"];
|
|
61852
|
+
});
|
|
61853
|
+
|
|
61477
61854
|
// src/rules/installer.ts
|
|
61478
|
-
import { existsSync as
|
|
61855
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "node:fs";
|
|
61479
61856
|
import { homedir as homedir12 } from "node:os";
|
|
61480
|
-
import { dirname as dirname11, join as
|
|
61857
|
+
import { dirname as dirname11, join as join41 } from "node:path";
|
|
61481
61858
|
function claudeConfigDir4() {
|
|
61482
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
61859
|
+
return process.env.CLAUDE_CONFIG_DIR || join41(homedir12(), ".claude");
|
|
61483
61860
|
}
|
|
61484
61861
|
function codexHome4() {
|
|
61485
|
-
return process.env.CODEX_HOME ||
|
|
61862
|
+
return process.env.CODEX_HOME || join41(homedir12(), ".codex");
|
|
61486
61863
|
}
|
|
61487
61864
|
function isRuleAgent(agent) {
|
|
61488
61865
|
return Object.hasOwn(RULE_TARGETS, agent);
|
|
@@ -61508,17 +61885,17 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
61508
61885
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
61509
61886
|
}
|
|
61510
61887
|
function ensureParent(path) {
|
|
61511
|
-
|
|
61888
|
+
mkdirSync15(dirname11(path), { recursive: true });
|
|
61512
61889
|
}
|
|
61513
61890
|
function writeIfChanged(path, content) {
|
|
61514
|
-
if (!
|
|
61891
|
+
if (!existsSync25(path)) {
|
|
61515
61892
|
ensureParent(path);
|
|
61516
|
-
|
|
61893
|
+
writeFileSync16(path, content, "utf-8");
|
|
61517
61894
|
return "created";
|
|
61518
61895
|
}
|
|
61519
|
-
if (
|
|
61896
|
+
if (readFileSync24(path, "utf-8") === content)
|
|
61520
61897
|
return "unchanged";
|
|
61521
|
-
|
|
61898
|
+
writeFileSync16(path, content, "utf-8");
|
|
61522
61899
|
return "updated";
|
|
61523
61900
|
}
|
|
61524
61901
|
function findSection(content) {
|
|
@@ -61544,14 +61921,14 @@ function buildSection(content, lineEnding = `
|
|
|
61544
61921
|
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
61545
61922
|
}
|
|
61546
61923
|
function upsertSection(path, content) {
|
|
61547
|
-
if (!
|
|
61924
|
+
if (!existsSync25(path)) {
|
|
61548
61925
|
const section = buildSection(content);
|
|
61549
61926
|
ensureParent(path);
|
|
61550
|
-
|
|
61927
|
+
writeFileSync16(path, `${section}
|
|
61551
61928
|
`, "utf-8");
|
|
61552
61929
|
return "created";
|
|
61553
61930
|
}
|
|
61554
|
-
const existing =
|
|
61931
|
+
const existing = readFileSync24(path, "utf-8");
|
|
61555
61932
|
const lineEnding = lineEndingFor(existing);
|
|
61556
61933
|
const section = buildSection(content, lineEnding);
|
|
61557
61934
|
const location = findSection(existing);
|
|
@@ -61564,7 +61941,7 @@ function upsertSection(path, content) {
|
|
|
61564
61941
|
}
|
|
61565
61942
|
if (next === existing)
|
|
61566
61943
|
return "unchanged";
|
|
61567
|
-
|
|
61944
|
+
writeFileSync16(path, next, "utf-8");
|
|
61568
61945
|
return "updated";
|
|
61569
61946
|
}
|
|
61570
61947
|
function installRuleForAgent(agent, content) {
|
|
@@ -61581,13 +61958,13 @@ function removeRuleForAgent(agent) {
|
|
|
61581
61958
|
return null;
|
|
61582
61959
|
const target = RULE_TARGETS[agent];
|
|
61583
61960
|
const path = target.path();
|
|
61584
|
-
if (!
|
|
61961
|
+
if (!existsSync25(path))
|
|
61585
61962
|
return { agent, path, action: "not_found" };
|
|
61586
61963
|
if (target.kind === "file") {
|
|
61587
61964
|
unlinkSync5(path);
|
|
61588
61965
|
return { agent, path, action: "removed" };
|
|
61589
61966
|
}
|
|
61590
|
-
const existing =
|
|
61967
|
+
const existing = readFileSync24(path, "utf-8");
|
|
61591
61968
|
const lineEnding = lineEndingFor(existing);
|
|
61592
61969
|
const location = findSection(existing);
|
|
61593
61970
|
if (!location)
|
|
@@ -61596,7 +61973,7 @@ function removeRuleForAgent(agent) {
|
|
|
61596
61973
|
if (!next) {
|
|
61597
61974
|
unlinkSync5(path);
|
|
61598
61975
|
} else {
|
|
61599
|
-
|
|
61976
|
+
writeFileSync16(path, `${next}${lineEnding}`, "utf-8");
|
|
61600
61977
|
}
|
|
61601
61978
|
return { agent, path, action: "removed" };
|
|
61602
61979
|
}
|
|
@@ -61624,36 +62001,36 @@ var init_installer = __esm(() => {
|
|
|
61624
62001
|
RULE_TARGETS = {
|
|
61625
62002
|
claude: {
|
|
61626
62003
|
kind: "file",
|
|
61627
|
-
path: () =>
|
|
62004
|
+
path: () => join41(claudeConfigDir4(), "rules", "dosu.md")
|
|
61628
62005
|
},
|
|
61629
62006
|
cursor: {
|
|
61630
62007
|
kind: "file",
|
|
61631
|
-
path: () =>
|
|
62008
|
+
path: () => join41(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
61632
62009
|
cursorFrontmatter: true
|
|
61633
62010
|
},
|
|
61634
62011
|
codex: {
|
|
61635
62012
|
kind: "section",
|
|
61636
|
-
path: () =>
|
|
62013
|
+
path: () => join41(codexHome4(), "AGENTS.md")
|
|
61637
62014
|
},
|
|
61638
62015
|
opencode: {
|
|
61639
62016
|
kind: "section",
|
|
61640
|
-
path: () =>
|
|
62017
|
+
path: () => join41(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
61641
62018
|
},
|
|
61642
62019
|
gemini: {
|
|
61643
62020
|
kind: "section",
|
|
61644
|
-
path: () =>
|
|
62021
|
+
path: () => join41(homedir12(), ".gemini", "GEMINI.md")
|
|
61645
62022
|
},
|
|
61646
62023
|
antigravity: {
|
|
61647
62024
|
kind: "section",
|
|
61648
|
-
path: () =>
|
|
62025
|
+
path: () => join41(homedir12(), ".gemini", "GEMINI.md")
|
|
61649
62026
|
}
|
|
61650
62027
|
};
|
|
61651
62028
|
});
|
|
61652
62029
|
|
|
61653
62030
|
// src/setup/agents-md-step.ts
|
|
61654
62031
|
import { execSync as execSync3 } from "node:child_process";
|
|
61655
|
-
import { existsSync as
|
|
61656
|
-
import { join as
|
|
62032
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
62033
|
+
import { join as join42 } from "node:path";
|
|
61657
62034
|
function inGitWorkTree(cwd = process.cwd()) {
|
|
61658
62035
|
try {
|
|
61659
62036
|
const stdout = execSync3("git rev-parse --is-inside-work-tree", {
|
|
@@ -61667,10 +62044,10 @@ function inGitWorkTree(cwd = process.cwd()) {
|
|
|
61667
62044
|
}
|
|
61668
62045
|
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
61669
62046
|
try {
|
|
61670
|
-
const path =
|
|
61671
|
-
if (!
|
|
62047
|
+
const path = join42(cwd, "AGENTS.md");
|
|
62048
|
+
if (!existsSync26(path))
|
|
61672
62049
|
return "missing";
|
|
61673
|
-
const content =
|
|
62050
|
+
const content = readFileSync25(path, "utf-8");
|
|
61674
62051
|
const startMatch = content.match(SECTION_START_RE);
|
|
61675
62052
|
if (!startMatch || !content.includes(DOSU_SECTION_END))
|
|
61676
62053
|
return "missing";
|
|
@@ -61705,14 +62082,14 @@ function findSection2(content) {
|
|
|
61705
62082
|
return { start, end };
|
|
61706
62083
|
}
|
|
61707
62084
|
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
61708
|
-
const path =
|
|
61709
|
-
if (!
|
|
62085
|
+
const path = join42(cwd, "AGENTS.md");
|
|
62086
|
+
if (!existsSync26(path)) {
|
|
61710
62087
|
const section = buildDosuAgentsSection(content);
|
|
61711
|
-
|
|
62088
|
+
writeFileSync17(path, `${section}
|
|
61712
62089
|
`);
|
|
61713
62090
|
return { path, action: "created" };
|
|
61714
62091
|
}
|
|
61715
|
-
const existing =
|
|
62092
|
+
const existing = readFileSync25(path, "utf-8");
|
|
61716
62093
|
const lineEnding = lineEndingFor2(existing);
|
|
61717
62094
|
const section = renderDosuAgentsSection(content, lineEnding);
|
|
61718
62095
|
const location = findSection2(existing);
|
|
@@ -61724,7 +62101,7 @@ function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RU
|
|
|
61724
62101
|
}
|
|
61725
62102
|
if (next === existing)
|
|
61726
62103
|
return { path, action: "unchanged" };
|
|
61727
|
-
|
|
62104
|
+
writeFileSync17(path, next);
|
|
61728
62105
|
return { path, action: "updated" };
|
|
61729
62106
|
}
|
|
61730
62107
|
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
@@ -61780,15 +62157,15 @@ var init_errors3 = __esm(() => {
|
|
|
61780
62157
|
var MCP_PROVIDER_SLUG2 = "dosu_mcp";
|
|
61781
62158
|
|
|
61782
62159
|
// src/sessions/session-title.ts
|
|
61783
|
-
import { existsSync as
|
|
62160
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync18 } from "node:fs";
|
|
61784
62161
|
import { homedir as homedir13 } from "node:os";
|
|
61785
|
-
import { join as
|
|
62162
|
+
import { join as join43 } from "node:path";
|
|
61786
62163
|
function cachePath2(configDir) {
|
|
61787
|
-
return
|
|
62164
|
+
return join43(configDir, CACHE_FILENAME6);
|
|
61788
62165
|
}
|
|
61789
62166
|
function loadCacheFile2(configDir) {
|
|
61790
62167
|
try {
|
|
61791
|
-
const raw = JSON.parse(
|
|
62168
|
+
const raw = JSON.parse(readFileSync26(cachePath2(configDir), "utf-8"));
|
|
61792
62169
|
if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
|
|
61793
62170
|
return {};
|
|
61794
62171
|
return raw.entries;
|
|
@@ -61798,12 +62175,12 @@ function loadCacheFile2(configDir) {
|
|
|
61798
62175
|
}
|
|
61799
62176
|
function saveCacheFile2(configDir, entries) {
|
|
61800
62177
|
try {
|
|
61801
|
-
if (!
|
|
61802
|
-
|
|
62178
|
+
if (!existsSync27(configDir))
|
|
62179
|
+
mkdirSync16(configDir, { recursive: true, mode: 448 });
|
|
61803
62180
|
const path = cachePath2(configDir);
|
|
61804
62181
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
61805
62182
|
const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
|
|
61806
|
-
|
|
62183
|
+
writeFileSync18(tmp, JSON.stringify(file), { mode: 384 });
|
|
61807
62184
|
renameSync6(tmp, path);
|
|
61808
62185
|
} catch {}
|
|
61809
62186
|
}
|
|
@@ -61836,15 +62213,15 @@ function claudeSummaryFromHead(text) {
|
|
|
61836
62213
|
}
|
|
61837
62214
|
return null;
|
|
61838
62215
|
}
|
|
61839
|
-
function reconstructSession(harness, id, slug, home = homedir13(), exists =
|
|
62216
|
+
function reconstructSession(harness, id, slug, home = homedir13(), exists = existsSync27) {
|
|
61840
62217
|
if (!slug)
|
|
61841
62218
|
return null;
|
|
61842
62219
|
const candidates = [];
|
|
61843
62220
|
if (harness === "claude") {
|
|
61844
|
-
candidates.push(
|
|
62221
|
+
candidates.push(join43(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
61845
62222
|
} else if (harness === "cursor") {
|
|
61846
|
-
const project =
|
|
61847
|
-
candidates.push(
|
|
62223
|
+
const project = join43(home, ".cursor", "projects", slug);
|
|
62224
|
+
candidates.push(join43(project, "agent-transcripts", id, `${id}.jsonl`), join43(project, "agent-transcripts", `${id}.jsonl`));
|
|
61848
62225
|
} else {
|
|
61849
62226
|
return null;
|
|
61850
62227
|
}
|
|
@@ -61856,7 +62233,7 @@ function reconstructSession(harness, id, slug, home = homedir13(), exists = exis
|
|
|
61856
62233
|
}
|
|
61857
62234
|
function readHead2(path) {
|
|
61858
62235
|
try {
|
|
61859
|
-
return
|
|
62236
|
+
return readFileSync26(path, "utf-8").slice(0, 128 * 1024);
|
|
61860
62237
|
} catch {
|
|
61861
62238
|
return null;
|
|
61862
62239
|
}
|
|
@@ -61907,7 +62284,7 @@ function createSessionTitleResolver(configDir = getConfigDir(), deps = {}) {
|
|
|
61907
62284
|
}
|
|
61908
62285
|
};
|
|
61909
62286
|
}
|
|
61910
|
-
var
|
|
62287
|
+
var CACHE_FILENAME6 = "session-titles.json", CACHE_SCHEMA_VERSION2 = 3, HEAD_LINES2 = 50, SESSION_NAME_MAX = 80;
|
|
61911
62288
|
var init_session_title = __esm(() => {
|
|
61912
62289
|
init_config();
|
|
61913
62290
|
init_read();
|
|
@@ -61936,7 +62313,7 @@ var init_alt_screen = __esm(() => {
|
|
|
61936
62313
|
});
|
|
61937
62314
|
|
|
61938
62315
|
// src/tui/activity-view.ts
|
|
61939
|
-
import { existsSync as
|
|
62316
|
+
import { existsSync as existsSync28, readFileSync as readFileSync27 } from "node:fs";
|
|
61940
62317
|
import { basename as basename5 } from "node:path";
|
|
61941
62318
|
function reduceActivityViewKey(key) {
|
|
61942
62319
|
if (key === "q" || key === ESC7 || key === CTRL_C4)
|
|
@@ -62077,15 +62454,15 @@ function statusLine(status) {
|
|
|
62077
62454
|
if (status.running) {
|
|
62078
62455
|
const since = status.startedAt ? ` · since ${localTime(status.startedAt)}` : "";
|
|
62079
62456
|
const pid = status.pid !== undefined ? ` (pid ${status.pid})` : "";
|
|
62080
|
-
return `\uD83D\uDCDA ${
|
|
62457
|
+
return `\uD83D\uDCDA ${import_picocolors34.default.bold(brand("Studying sessions..."))}${import_picocolors34.default.dim(`${pid}${since}`)}`;
|
|
62081
62458
|
}
|
|
62082
62459
|
if (status.state.paused) {
|
|
62083
|
-
return `${
|
|
62460
|
+
return `${import_picocolors34.default.yellow("○")} ${import_picocolors34.default.bold("Paused")} ${import_picocolors34.default.dim("· studying stays off until you resume")}`;
|
|
62084
62461
|
}
|
|
62085
62462
|
if (status.staleLock) {
|
|
62086
|
-
return `${
|
|
62463
|
+
return `${import_picocolors34.default.yellow("○")} ${import_picocolors34.default.bold("Not running")} ${import_picocolors34.default.dim("· a previous run exited without cleaning up")}`;
|
|
62087
62464
|
}
|
|
62088
|
-
return `${
|
|
62465
|
+
return `${import_picocolors34.default.dim("○")} ${import_picocolors34.default.bold("Idle")} ${import_picocolors34.default.dim("· hooks study new sessions automatically")}`;
|
|
62089
62466
|
}
|
|
62090
62467
|
function progressLine(done, ready, width, notes = 0) {
|
|
62091
62468
|
const total = done + ready;
|
|
@@ -62094,7 +62471,7 @@ function progressLine(done, ready, width, notes = 0) {
|
|
|
62094
62471
|
const cells = Math.max(10, Math.min(30, width - 44));
|
|
62095
62472
|
const ratio = Math.max(0, Math.min(1, done / total));
|
|
62096
62473
|
const filled = Math.min(cells, Math.round(ratio * cells));
|
|
62097
|
-
const bar = brand("█".repeat(filled)) +
|
|
62474
|
+
const bar = brand("█".repeat(filled)) + import_picocolors34.default.dim("░".repeat(cells - filled));
|
|
62098
62475
|
const pct = Math.floor(ratio * 100);
|
|
62099
62476
|
const suffix = notes > 0 ? ` · ${notes} suggested page${notes === 1 ? "" : "s"}` : "";
|
|
62100
62477
|
return `${bar} ${done}/${total} studied · ${pct}%${suffix}`;
|
|
@@ -62133,17 +62510,17 @@ function confirmBox(queuedCount, backlog, width, mode = "start") {
|
|
|
62133
62510
|
const verb = mode === "clear" ? "clear" : mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
|
|
62134
62511
|
const maxInner = Math.max(20, Math.min(width, contentWidth()) - 4);
|
|
62135
62512
|
const rows = [
|
|
62136
|
-
|
|
62137
|
-
...wrapLine(scope, maxInner, "").map((line) =>
|
|
62513
|
+
import_picocolors34.default.bold(brand(title)),
|
|
62514
|
+
...wrapLine(scope, maxInner, "").map((line) => import_picocolors34.default.dim(line)),
|
|
62138
62515
|
"",
|
|
62139
|
-
`${
|
|
62516
|
+
`${import_picocolors34.default.bold("enter")} ${verb} · ${import_picocolors34.default.bold("esc")} cancel`
|
|
62140
62517
|
];
|
|
62141
62518
|
const inner = Math.min(maxInner, Math.max(...rows.map(visibleWidth2)));
|
|
62142
62519
|
const pad = (row) => row + " ".repeat(Math.max(0, inner - visibleWidth2(row)));
|
|
62143
62520
|
return [
|
|
62144
|
-
|
|
62145
|
-
...rows.map((row) => `${
|
|
62146
|
-
|
|
62521
|
+
import_picocolors34.default.dim(`╭${"─".repeat(inner + 2)}╮`),
|
|
62522
|
+
...rows.map((row) => `${import_picocolors34.default.dim("│")} ${pad(row)} ${import_picocolors34.default.dim("│")}`),
|
|
62523
|
+
import_picocolors34.default.dim(`╰${"─".repeat(inner + 2)}╯`)
|
|
62147
62524
|
];
|
|
62148
62525
|
}
|
|
62149
62526
|
function renderActivityFrame(status, activity, width, backlog = null, pane = DEFAULT_PANE, queued = [], studiedBeforeRun = 0, open = [], runProgress = null, projectNames = {}, sessionNames = {}) {
|
|
@@ -62159,7 +62536,7 @@ function renderActivityFrame(status, activity, width, backlog = null, pane = DEF
|
|
|
62159
62536
|
progress = progressLine(studiedDelta + stepDone, Math.max(0, backlog.ready - stepDone), width, runProgress?.notes ?? 0);
|
|
62160
62537
|
}
|
|
62161
62538
|
const refusal = !status.running && status.state.last_refusal;
|
|
62162
|
-
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) =>
|
|
62539
|
+
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) => import_picocolors34.default.yellow(line)) : [];
|
|
62163
62540
|
const fullRows = Boolean(pane.fullRows);
|
|
62164
62541
|
const withName = (item, key) => projectNames[key] ? { ...item, project: projectNames[key] } : item;
|
|
62165
62542
|
const latestPass = new Map;
|
|
@@ -62184,7 +62561,7 @@ function renderActivityFrame(status, activity, width, backlog = null, pane = DEF
|
|
|
62184
62561
|
const height = fullRows ? ACTIVITY_VIEW_FULL_LIST_ROWS : ACTIVITY_VIEW_LIST_LINES;
|
|
62185
62562
|
const { visible, above, below } = windowList(source, pane.scroll, height);
|
|
62186
62563
|
const display = fullRows ? visible.flatMap((row) => wrapRow(row, width)) : visible;
|
|
62187
|
-
const listRows = display.length > 0 ? display.map((row) =>
|
|
62564
|
+
const listRows = display.length > 0 ? display.map((row) => import_picocolors34.default.dim(row)) : [import_picocolors34.default.dim(empty)];
|
|
62188
62565
|
const scrollParts = [];
|
|
62189
62566
|
if (above > 0)
|
|
62190
62567
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -62194,14 +62571,14 @@ function renderActivityFrame(status, activity, width, backlog = null, pane = DEF
|
|
|
62194
62571
|
breadcrumb(["home", "activity"], width),
|
|
62195
62572
|
"",
|
|
62196
62573
|
statusLine(status),
|
|
62197
|
-
|
|
62198
|
-
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) =>
|
|
62574
|
+
import_picocolors34.default.dim(studied),
|
|
62575
|
+
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) => import_picocolors34.default.dim(line)) : [],
|
|
62199
62576
|
...progress ? [progress] : [],
|
|
62200
62577
|
...refusalLines,
|
|
62201
62578
|
"",
|
|
62202
62579
|
...tabBar(pane.tab, queued.length, open.length, latestPass.size, width),
|
|
62203
62580
|
...listRows,
|
|
62204
|
-
...scrollParts.length > 0 ? [
|
|
62581
|
+
...scrollParts.length > 0 ? [import_picocolors34.default.dim(clip(scrollParts.join(" · "), width))] : [],
|
|
62205
62582
|
"",
|
|
62206
62583
|
...pane.confirm ? centerBlock(confirmBox(queued.length, backlog, width, pane.confirm), width) : [
|
|
62207
62584
|
...wrapLine([
|
|
@@ -62211,7 +62588,7 @@ function renderActivityFrame(status, activity, width, backlog = null, pane = DEF
|
|
|
62211
62588
|
status.running ? "s stop" : status.state.paused ? "s resume" : "s sync now",
|
|
62212
62589
|
...!status.running && status.state.watermark ? ["c clear"] : [],
|
|
62213
62590
|
"esc back"
|
|
62214
|
-
].join(" · "), width, "").map((line) =>
|
|
62591
|
+
].join(" · "), width, "").map((line) => import_picocolors34.default.dim(line))
|
|
62215
62592
|
]
|
|
62216
62593
|
];
|
|
62217
62594
|
return lines.join(`
|
|
@@ -62245,7 +62622,7 @@ function createRowNamer() {
|
|
|
62245
62622
|
names.titles[key] = t;
|
|
62246
62623
|
};
|
|
62247
62624
|
for (const s of [...backlog.queued, ...backlog.open]) {
|
|
62248
|
-
if (!
|
|
62625
|
+
if (!existsSync28(s.path))
|
|
62249
62626
|
continue;
|
|
62250
62627
|
const key = `${s.harness}/${s.id}`;
|
|
62251
62628
|
const dir = dirs.resolve(s);
|
|
@@ -62282,7 +62659,7 @@ function createRowNamer() {
|
|
|
62282
62659
|
}
|
|
62283
62660
|
function defaultReadLog2() {
|
|
62284
62661
|
try {
|
|
62285
|
-
return
|
|
62662
|
+
return readFileSync27(logger.getLogPath(), "utf-8");
|
|
62286
62663
|
} catch {
|
|
62287
62664
|
return "";
|
|
62288
62665
|
}
|
|
@@ -62463,7 +62840,7 @@ ${CLEAR_BELOW}`);
|
|
|
62463
62840
|
input.on("data", onData);
|
|
62464
62841
|
});
|
|
62465
62842
|
}
|
|
62466
|
-
var
|
|
62843
|
+
var import_picocolors34, ESC7, HIDE_CURSOR3, SHOW_CURSOR3, CTRL_C4, KEY_UP4, KEY_DOWN4, KEY_RIGHT3, KEY_LEFT3, CURSOR_HOME, CLEAR_BELOW, CLEAR_EOL, ACTIVITY_VIEW_POLL_MS = 500, ACTIVITY_VIEW_LIST_LINES = 10, ACTIVITY_VIEW_FULL_LIST_ROWS = 5, ACTIVITY_VIEW_BUFFER_LINES = 200, ACTIVITY_VIEW_TABS, DEFAULT_PANE, TITLE_READS_PER_DRAW = 25;
|
|
62467
62844
|
var init_activity_view = __esm(() => {
|
|
62468
62845
|
init_follow();
|
|
62469
62846
|
init_logger();
|
|
@@ -62478,7 +62855,7 @@ var init_activity_view = __esm(() => {
|
|
|
62478
62855
|
init_alt_screen();
|
|
62479
62856
|
init_layout();
|
|
62480
62857
|
init_menu();
|
|
62481
|
-
|
|
62858
|
+
import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
62482
62859
|
ESC7 = String.fromCharCode(27);
|
|
62483
62860
|
HIDE_CURSOR3 = `${ESC7}[?25l`;
|
|
62484
62861
|
SHOW_CURSOR3 = `${ESC7}[?25h`;
|
|
@@ -63259,6 +63636,7 @@ async function runSetupFlow(opts = {}) {
|
|
|
63259
63636
|
}));
|
|
63260
63637
|
return;
|
|
63261
63638
|
}
|
|
63639
|
+
writeMcpRefreshCache({ version: VERSION });
|
|
63262
63640
|
const configuredProviders = configured.filter((result) => (result.action === "install" || result.action === "skip") && !result.error);
|
|
63263
63641
|
const mcpCompleted = configuredProviders.length > 0;
|
|
63264
63642
|
if (mcpCompleted) {
|
|
@@ -63703,25 +64081,14 @@ async function runSwitchTarget(scope = "org") {
|
|
|
63703
64081
|
return;
|
|
63704
64082
|
updateTarget(cfg, { api_key: apiKey });
|
|
63705
64083
|
saveConfig(cfg);
|
|
63706
|
-
const
|
|
63707
|
-
|
|
63708
|
-
|
|
63709
|
-
|
|
63710
|
-
|
|
63711
|
-
}
|
|
63712
|
-
});
|
|
63713
|
-
for (const provider of configured) {
|
|
63714
|
-
try {
|
|
63715
|
-
provider.install(cfg, true);
|
|
63716
|
-
logger.info("setup", `Switch: updated ${provider.name()}`);
|
|
63717
|
-
log2.success(`${provider.name()} ${dim("· updated")}`);
|
|
63718
|
-
} catch (err) {
|
|
63719
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
63720
|
-
logger.error("setup", `Switch: update failed for ${provider.name()}: ${error.message}`);
|
|
63721
|
-
log2.error(`Failed to update ${provider.name()}: ${error.message}`);
|
|
63722
|
-
}
|
|
64084
|
+
const refreshed = refreshConfiguredProviders(cfg);
|
|
64085
|
+
for (const provider of refreshed.updated) {
|
|
64086
|
+
log2.success(`${provider.name()} ${dim("· updated")}`);
|
|
64087
|
+
}
|
|
64088
|
+
for (const { provider, error } of refreshed.failed) {
|
|
64089
|
+
log2.error(`Failed to update ${provider.name()}: ${error.message}`);
|
|
63723
64090
|
}
|
|
63724
|
-
if (
|
|
64091
|
+
if (refreshed.updated.length + refreshed.failed.length > 0) {
|
|
63725
64092
|
log2.info("Restart your AI agents so they pick up the new MCP target.");
|
|
63726
64093
|
}
|
|
63727
64094
|
}
|
|
@@ -63971,7 +64338,7 @@ async function stepSelectTools(detected) {
|
|
|
63971
64338
|
initialValues: preselected,
|
|
63972
64339
|
statusFor: (id, picked) => {
|
|
63973
64340
|
if (configuredMap.get(id))
|
|
63974
|
-
return picked ? dim("configured") :
|
|
64341
|
+
return picked ? dim("configured") : import_picocolors35.default.yellow("will remove");
|
|
63975
64342
|
return picked ? brand("will configure") : undefined;
|
|
63976
64343
|
},
|
|
63977
64344
|
summary: (picked) => {
|
|
@@ -64146,7 +64513,7 @@ ${dim(wrapLog("Run it inside a session to keep that session out of studying. Rem
|
|
|
64146
64513
|
log2.success("All agents already configured. No changes needed.");
|
|
64147
64514
|
}
|
|
64148
64515
|
}
|
|
64149
|
-
var
|
|
64516
|
+
var import_picocolors35, OAUTH_ANALYTICS_REASONS, SETUP_HANDSHAKE_TIMEOUT_MS = 1800000, LIBRARY_SELECT_CANCELLED;
|
|
64150
64517
|
var init_flow2 = __esm(() => {
|
|
64151
64518
|
init_dist();
|
|
64152
64519
|
init_errors3();
|
|
@@ -64157,6 +64524,7 @@ var init_flow2 = __esm(() => {
|
|
|
64157
64524
|
init_agents();
|
|
64158
64525
|
init_agents3();
|
|
64159
64526
|
init_providers();
|
|
64527
|
+
init_refresh();
|
|
64160
64528
|
init_agents4();
|
|
64161
64529
|
init_detach();
|
|
64162
64530
|
init_sync();
|
|
@@ -64164,12 +64532,13 @@ var init_flow2 = __esm(() => {
|
|
|
64164
64532
|
init_activity_view();
|
|
64165
64533
|
init_layout();
|
|
64166
64534
|
init_prompts();
|
|
64535
|
+
init_mcp_refresh_check();
|
|
64167
64536
|
init_agents_md_step();
|
|
64168
64537
|
init_analytics2();
|
|
64169
64538
|
init_github_step();
|
|
64170
64539
|
init_rules_step();
|
|
64171
64540
|
init_styles();
|
|
64172
|
-
|
|
64541
|
+
import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
64173
64542
|
OAUTH_ANALYTICS_REASONS = new Set([
|
|
64174
64543
|
"access_denied",
|
|
64175
64544
|
"bad_oauth_state",
|
|
@@ -64297,7 +64666,7 @@ function renderAnalyticsFrame(state, tab, scroll, pageStats = null, pagesPending
|
|
|
64297
64666
|
const rows = analyticsTabRows(tab, state, pageStats);
|
|
64298
64667
|
const { visible, above, below } = windowReport(rows, scroll);
|
|
64299
64668
|
const empty = tab === "overview" ? "No analytics yet. They appear after the first study run." : tab === "projects" ? "No per-project history yet. It fills in as sessions are studied." : pagesPending ? "Loading page analytics..." : "No page analytics yet.";
|
|
64300
|
-
const listRows = visible.length > 0 ? visible.map((row) =>
|
|
64669
|
+
const listRows = visible.length > 0 ? visible.map((row) => import_picocolors36.default.dim(row)) : [import_picocolors36.default.dim(empty)];
|
|
64301
64670
|
const scrollParts = [];
|
|
64302
64671
|
if (above > 0)
|
|
64303
64672
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -64313,9 +64682,9 @@ function renderAnalyticsFrame(state, tab, scroll, pageStats = null, pagesPending
|
|
|
64313
64682
|
], tab, width, { spread: false }),
|
|
64314
64683
|
"",
|
|
64315
64684
|
...listRows,
|
|
64316
|
-
...scrollParts.length > 0 ? [
|
|
64685
|
+
...scrollParts.length > 0 ? [import_picocolors36.default.dim(scrollParts.join(" · "))] : [],
|
|
64317
64686
|
"",
|
|
64318
|
-
|
|
64687
|
+
import_picocolors36.default.dim("tab switch · ↑↓ scroll · esc back")
|
|
64319
64688
|
];
|
|
64320
64689
|
return lines.join(`
|
|
64321
64690
|
`);
|
|
@@ -64410,7 +64779,7 @@ ${CLEAR_BELOW2}`);
|
|
|
64410
64779
|
input.on("data", onData);
|
|
64411
64780
|
});
|
|
64412
64781
|
}
|
|
64413
|
-
var
|
|
64782
|
+
var import_picocolors36, ESC8, HIDE_CURSOR4, SHOW_CURSOR4, CTRL_C5, KEY_UP5, KEY_DOWN5, KEY_RIGHT4, KEY_LEFT4, CURSOR_HOME2, CLEAR_BELOW2, CLEAR_EOL2, ANALYTICS_VIEW_POLL_MS = 1000, ANALYTICS_VIEW_LINES = 14, ANALYTICS_VIEW_TABS, TOP_PAGES_LIMIT = 5, TOP_CITED_DAYS = 30, label = (text) => text.padEnd(26);
|
|
64414
64783
|
var init_analytics_view = __esm(() => {
|
|
64415
64784
|
init_trpc();
|
|
64416
64785
|
init_config();
|
|
@@ -64418,7 +64787,7 @@ var init_analytics_view = __esm(() => {
|
|
|
64418
64787
|
init_alt_screen();
|
|
64419
64788
|
init_layout();
|
|
64420
64789
|
init_menu();
|
|
64421
|
-
|
|
64790
|
+
import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
64422
64791
|
ESC8 = String.fromCharCode(27);
|
|
64423
64792
|
HIDE_CURSOR4 = `${ESC8}[?25l`;
|
|
64424
64793
|
SHOW_CURSOR4 = `${ESC8}[?25h`;
|
|
@@ -64436,7 +64805,7 @@ var init_analytics_view = __esm(() => {
|
|
|
64436
64805
|
// src/tui/banner.ts
|
|
64437
64806
|
function paintLogoRow(row) {
|
|
64438
64807
|
return row.map(([tone, art]) => {
|
|
64439
|
-
if (!
|
|
64808
|
+
if (!import_picocolors37.default.isColorSupported)
|
|
64440
64809
|
return art;
|
|
64441
64810
|
const { fg, fallback } = LOGO_TONES[tone];
|
|
64442
64811
|
return hasTruecolor() ? `${fg}${art}\x1B[39m` : fallback(art);
|
|
@@ -64444,14 +64813,14 @@ function paintLogoRow(row) {
|
|
|
64444
64813
|
}
|
|
64445
64814
|
function checklistRows(ctx) {
|
|
64446
64815
|
const on = brand(CHECK2);
|
|
64447
|
-
const off =
|
|
64816
|
+
const off = import_picocolors37.default.dim(CIRCLE);
|
|
64448
64817
|
const rows = [["workspace", ctx.directory]];
|
|
64449
64818
|
rows.push([
|
|
64450
64819
|
"account",
|
|
64451
|
-
ctx.sessionExpired ? `${off} ${
|
|
64820
|
+
ctx.sessionExpired ? `${off} ${import_picocolors37.default.yellow("session expired")} ${import_picocolors37.default.dim(`${DOT3} run Log in`)}` : ctx.signedIn ? `${on} signed in` : `${off} ${import_picocolors37.default.dim(`not signed in ${DOT3} run Setup`)}`
|
|
64452
64821
|
]);
|
|
64453
64822
|
const missing = new Set(ctx.setupMissing ?? []);
|
|
64454
|
-
const warnRow = `${off} ${
|
|
64823
|
+
const warnRow = `${off} ${import_picocolors37.default.yellow("not configured")} ${import_picocolors37.default.dim(`${DOT3} run Setup`)}`;
|
|
64455
64824
|
if (missing.has("MCP"))
|
|
64456
64825
|
rows.push(["mcp", warnRow]);
|
|
64457
64826
|
else if (ctx.deploymentName)
|
|
@@ -64463,7 +64832,7 @@ function checklistRows(ctx) {
|
|
|
64463
64832
|
if (ctx.repoAgentsMd) {
|
|
64464
64833
|
rows.push([
|
|
64465
64834
|
"repo",
|
|
64466
|
-
ctx.repoAgentsMd === "current" ? `${on} AGENTS.md has the Dosu section` : `${off} ${
|
|
64835
|
+
ctx.repoAgentsMd === "current" ? `${on} AGENTS.md has the Dosu section` : `${off} ${import_picocolors37.default.yellow(ctx.repoAgentsMd === "outdated" ? "AGENTS.md Dosu section outdated" : "AGENTS.md missing the Dosu section")} ${import_picocolors37.default.dim(`${DOT3} run Setup`)}`
|
|
64467
64836
|
]);
|
|
64468
64837
|
}
|
|
64469
64838
|
if (missing.has("agents"))
|
|
@@ -64475,24 +64844,24 @@ function checklistRows(ctx) {
|
|
|
64475
64844
|
if (ctx.studying) {
|
|
64476
64845
|
rows.push([
|
|
64477
64846
|
"sync",
|
|
64478
|
-
`\uD83D\uDCDA ${brand("studying sessions...")} ${
|
|
64847
|
+
`\uD83D\uDCDA ${brand("studying sessions...")} ${import_picocolors37.default.dim(`${DOT3} see activity`)}`
|
|
64479
64848
|
]);
|
|
64480
64849
|
}
|
|
64481
64850
|
if (ctx.update) {
|
|
64482
64851
|
rows.push([
|
|
64483
64852
|
"update",
|
|
64484
|
-
`${
|
|
64853
|
+
`${import_picocolors37.default.yellow(`↑ ${ctx.update.version} available`)} ${import_picocolors37.default.dim(`${DOT3} ${ctx.update.hint}`)}`
|
|
64485
64854
|
]);
|
|
64486
64855
|
}
|
|
64487
64856
|
const labelWidth = Math.max(...rows.map(([label]) => label.length));
|
|
64488
|
-
return rows.map(([label, value]) => `${
|
|
64857
|
+
return rows.map(([label, value]) => `${import_picocolors37.default.dim(label.padEnd(labelWidth))} ${value}`);
|
|
64489
64858
|
}
|
|
64490
64859
|
function renderBanner(ctx) {
|
|
64491
64860
|
const logo = LOGO_ROWS.map(paintLogoRow);
|
|
64492
64861
|
const text = [
|
|
64493
64862
|
...checklistRows(ctx),
|
|
64494
64863
|
"",
|
|
64495
|
-
`${brandBadge("dosu-cli")} ${
|
|
64864
|
+
`${brandBadge("dosu-cli")} ${import_picocolors37.default.dim(`${ctx.version} ${DOT3} ${ctx.webAppHost}`)}`
|
|
64496
64865
|
];
|
|
64497
64866
|
const height = Math.max(logo.length, text.length);
|
|
64498
64867
|
const combined = [];
|
|
@@ -64505,10 +64874,10 @@ function renderBanner(ctx) {
|
|
|
64505
64874
|
return ["", ...combined, ""].join(`
|
|
64506
64875
|
`);
|
|
64507
64876
|
}
|
|
64508
|
-
var
|
|
64877
|
+
var import_picocolors37, CHECK2 = "✔", CIRCLE = "○", DOT3 = "·", LOGO_ROWS, LOGO_MARK, LOGO_WIDTH, LOGO_TONES, COLUMN_GAP = " ";
|
|
64509
64878
|
var init_banner = __esm(() => {
|
|
64510
64879
|
init_styles();
|
|
64511
|
-
|
|
64880
|
+
import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
64512
64881
|
LOGO_ROWS = [
|
|
64513
64882
|
[["sage", "▄▄▄▄▄▄"]],
|
|
64514
64883
|
[["sage", "██ ▀▄"]],
|
|
@@ -64519,8 +64888,8 @@ var init_banner = __esm(() => {
|
|
|
64519
64888
|
LOGO_MARK = LOGO_ROWS.map((row) => row.map(([, art]) => art).join(""));
|
|
64520
64889
|
LOGO_WIDTH = Math.max(...LOGO_MARK.map((row) => row.length));
|
|
64521
64890
|
LOGO_TONES = {
|
|
64522
|
-
sage: { fg: "\x1B[38;2;180;187;145m", fallback:
|
|
64523
|
-
moss: { fg: "\x1B[38;2;119;133;97m", fallback: (art) =>
|
|
64891
|
+
sage: { fg: "\x1B[38;2;180;187;145m", fallback: import_picocolors37.default.green },
|
|
64892
|
+
moss: { fg: "\x1B[38;2;119;133;97m", fallback: (art) => import_picocolors37.default.dim(import_picocolors37.default.green(art)) }
|
|
64524
64893
|
};
|
|
64525
64894
|
});
|
|
64526
64895
|
|
|
@@ -64632,16 +65001,16 @@ function renderPagesFrame(model, width, selected) {
|
|
|
64632
65001
|
const body = [];
|
|
64633
65002
|
let scrollHint = "";
|
|
64634
65003
|
if (model.phase === "loading") {
|
|
64635
|
-
body.push(
|
|
65004
|
+
body.push(import_picocolors38.default.dim("Loading pages…"));
|
|
64636
65005
|
} else if (model.phase === "error") {
|
|
64637
|
-
body.push(
|
|
65006
|
+
body.push(import_picocolors38.default.yellow(clip3(model.message, width)));
|
|
64638
65007
|
} else if (model.pages.length === 0) {
|
|
64639
|
-
body.push(
|
|
65008
|
+
body.push(import_picocolors38.default.dim("No pages in this Library yet."));
|
|
64640
65009
|
} else {
|
|
64641
65010
|
const rows = pageRows2(model.pages, width - 2);
|
|
64642
65011
|
const { start, above } = windowSelection(rows.length, selected);
|
|
64643
65012
|
const visible = rows.slice(start, start + PAGES_VIEW_LINES);
|
|
64644
|
-
body.push(...visible.map((row, i) => start + i === selected ? `${brand("▸")} ${
|
|
65013
|
+
body.push(...visible.map((row, i) => start + i === selected ? `${brand("▸")} ${import_picocolors38.default.bold(row)}` : ` ${import_picocolors38.default.dim(row)}`));
|
|
64645
65014
|
const below = Math.max(0, Math.max(model.total, rows.length) - start - PAGES_VIEW_LINES);
|
|
64646
65015
|
const parts = [];
|
|
64647
65016
|
if (above > 0)
|
|
@@ -64650,14 +65019,14 @@ function renderPagesFrame(model, width, selected) {
|
|
|
64650
65019
|
parts.push(`↓ ${below} more`);
|
|
64651
65020
|
scrollHint = parts.join(" · ");
|
|
64652
65021
|
}
|
|
64653
|
-
const count = model.phase === "ready" ? ` ${
|
|
65022
|
+
const count = model.phase === "ready" ? ` ${import_picocolors38.default.dim(model.pages.length < model.total ? `(${model.pages.length} of ${model.total})` : `(${model.pages.length})`)}` : "";
|
|
64654
65023
|
const lines = [
|
|
64655
65024
|
`${breadcrumb(["home", "pages"], width)}${count}`,
|
|
64656
65025
|
"",
|
|
64657
65026
|
...body,
|
|
64658
|
-
...scrollHint ? [
|
|
65027
|
+
...scrollHint ? [import_picocolors38.default.dim(scrollHint)] : [],
|
|
64659
65028
|
"",
|
|
64660
|
-
|
|
65029
|
+
import_picocolors38.default.dim("↑↓ move · enter open · esc back")
|
|
64661
65030
|
];
|
|
64662
65031
|
return lines.join(`
|
|
64663
65032
|
`);
|
|
@@ -64666,9 +65035,9 @@ function renderPageFrame(page, content, width, scroll) {
|
|
|
64666
65035
|
const body = [];
|
|
64667
65036
|
let scrollHint = "";
|
|
64668
65037
|
if (content.phase === "loading") {
|
|
64669
|
-
body.push(
|
|
65038
|
+
body.push(import_picocolors38.default.dim("Loading page…"));
|
|
64670
65039
|
} else if (content.phase === "error") {
|
|
64671
|
-
body.push(
|
|
65040
|
+
body.push(import_picocolors38.default.yellow(clip3(content.message, width)));
|
|
64672
65041
|
} else {
|
|
64673
65042
|
const rows = wrapBody(content.body, width);
|
|
64674
65043
|
const { visible, above, below } = windowReport(rows, scroll, PAGE_BODY_LINES);
|
|
@@ -64683,12 +65052,12 @@ function renderPageFrame(page, content, width, scroll) {
|
|
|
64683
65052
|
const meta = `${page.type} · ${page.published ? "published" : "draft"} · updated ${page.updated_at.slice(0, 10)}`;
|
|
64684
65053
|
const lines = [
|
|
64685
65054
|
breadcrumb(["home", "pages", page.title], width),
|
|
64686
|
-
|
|
65055
|
+
import_picocolors38.default.dim(clip3(meta, width)),
|
|
64687
65056
|
"",
|
|
64688
65057
|
...body,
|
|
64689
|
-
...scrollHint ? [
|
|
65058
|
+
...scrollHint ? [import_picocolors38.default.dim(scrollHint)] : [],
|
|
64690
65059
|
"",
|
|
64691
|
-
|
|
65060
|
+
import_picocolors38.default.dim("↑↓ scroll · esc back to pages")
|
|
64692
65061
|
];
|
|
64693
65062
|
return lines.join(`
|
|
64694
65063
|
`);
|
|
@@ -64837,7 +65206,7 @@ ${CLEAR_BELOW3}`);
|
|
|
64837
65206
|
input.on("data", onData);
|
|
64838
65207
|
});
|
|
64839
65208
|
}
|
|
64840
|
-
var
|
|
65209
|
+
var import_picocolors38, ESC9, HIDE_CURSOR5, SHOW_CURSOR5, CTRL_C6, KEY_UP6, KEY_DOWN6, CURSOR_HOME3, CLEAR_BELOW3, CLEAR_EOL3, PAGES_VIEW_LINES = 12, PAGE_BODY_LINES = 14, PAGES_FETCH_BATCH = 100;
|
|
64841
65210
|
var init_pages_view = __esm(() => {
|
|
64842
65211
|
init_trpc();
|
|
64843
65212
|
init_config();
|
|
@@ -64847,7 +65216,7 @@ var init_pages_view = __esm(() => {
|
|
|
64847
65216
|
init_analytics_view();
|
|
64848
65217
|
init_layout();
|
|
64849
65218
|
init_menu();
|
|
64850
|
-
|
|
65219
|
+
import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
64851
65220
|
ESC9 = String.fromCharCode(27);
|
|
64852
65221
|
HIDE_CURSOR5 = `${ESC9}[?25l`;
|
|
64853
65222
|
SHOW_CURSOR5 = `${ESC9}[?25h`;
|
|
@@ -64961,7 +65330,7 @@ function isSetUp(cfg) {
|
|
|
64961
65330
|
}
|
|
64962
65331
|
function setupHint(cfg) {
|
|
64963
65332
|
const started = Boolean(cfg.active_account?.target);
|
|
64964
|
-
return
|
|
65333
|
+
return import_picocolors39.default.yellow(started ? `incomplete · missing ${missingSetupSteps(cfg).join(" + ")}` : "not set up yet");
|
|
64965
65334
|
}
|
|
64966
65335
|
function isStudying() {
|
|
64967
65336
|
try {
|
|
@@ -65207,7 +65576,7 @@ function handleLogout(cfg) {
|
|
|
65207
65576
|
saveConfig(cfg);
|
|
65208
65577
|
log2.success("Credentials cleared.");
|
|
65209
65578
|
}
|
|
65210
|
-
var
|
|
65579
|
+
var import_picocolors39, ESC10, CLEAR_SCREEN;
|
|
65211
65580
|
var init_tui = __esm(() => {
|
|
65212
65581
|
init_client();
|
|
65213
65582
|
init_config();
|
|
@@ -65230,7 +65599,7 @@ var init_tui = __esm(() => {
|
|
|
65230
65599
|
init_menu();
|
|
65231
65600
|
init_pages_view();
|
|
65232
65601
|
init_prompts();
|
|
65233
|
-
|
|
65602
|
+
import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
65234
65603
|
ESC10 = String.fromCharCode(27);
|
|
65235
65604
|
CLEAR_SCREEN = `${ESC10}[2J${ESC10}[H`;
|
|
65236
65605
|
});
|
|
@@ -65834,18 +66203,15 @@ var init_flow3 = __esm(() => {
|
|
|
65834
66203
|
});
|
|
65835
66204
|
|
|
65836
66205
|
// src/cli/cli.ts
|
|
65837
|
-
import {
|
|
65838
|
-
closeSync as closeSync6,
|
|
65839
|
-
constants as constants3,
|
|
65840
|
-
fstatSync as fstatSync2,
|
|
65841
|
-
openSync as openSync6,
|
|
65842
|
-
readFileSync as readFileSync27,
|
|
65843
|
-
readSync as readSync5,
|
|
65844
|
-
unlinkSync as unlinkSync6
|
|
65845
|
-
} from "node:fs";
|
|
66206
|
+
import { readFileSync as readFileSync28, unlinkSync as unlinkSync6 } from "node:fs";
|
|
65846
66207
|
function shouldRunBackgroundChecks(actionName) {
|
|
65847
66208
|
return actionName !== "upgrade";
|
|
65848
66209
|
}
|
|
66210
|
+
function shouldRunMcpRefreshCheck(actionCommand) {
|
|
66211
|
+
if (actionCommand.name() === "setup")
|
|
66212
|
+
return false;
|
|
66213
|
+
return !(actionCommand.name() === "refresh" && actionCommand.parent?.name() === "mcp");
|
|
66214
|
+
}
|
|
65849
66215
|
function commandTelemetryName(actionCommand) {
|
|
65850
66216
|
const segments = [];
|
|
65851
66217
|
let current = actionCommand;
|
|
@@ -65862,7 +66228,7 @@ function shouldTrackCommand(command) {
|
|
|
65862
66228
|
}
|
|
65863
66229
|
function commandTelemetryContext() {
|
|
65864
66230
|
try {
|
|
65865
|
-
const cfg =
|
|
66231
|
+
const cfg = loadConfigNonBlocking();
|
|
65866
66232
|
if (!cfg)
|
|
65867
66233
|
return { mode: "cloud", isAuthenticated: false };
|
|
65868
66234
|
const authenticated = isAuthenticated(cfg);
|
|
@@ -65882,29 +66248,6 @@ function commandTelemetryContext() {
|
|
|
65882
66248
|
return { mode: "cloud", isAuthenticated: false };
|
|
65883
66249
|
}
|
|
65884
66250
|
}
|
|
65885
|
-
function loadConfigForTelemetry() {
|
|
65886
|
-
let fd;
|
|
65887
|
-
try {
|
|
65888
|
-
const nonblocking = typeof constants3.O_NONBLOCK === "number" ? constants3.O_NONBLOCK : 0;
|
|
65889
|
-
fd = openSync6(getConfigPath(), constants3.O_RDONLY | nonblocking);
|
|
65890
|
-
const file = fstatSync2(fd);
|
|
65891
|
-
if (!file.isFile() || file.size > MAX_TELEMETRY_CONFIG_BYTES)
|
|
65892
|
-
return;
|
|
65893
|
-
const content = Buffer.alloc(MAX_TELEMETRY_CONFIG_BYTES + 1);
|
|
65894
|
-
const bytesRead = readSync5(fd, content, 0, content.byteLength, 0);
|
|
65895
|
-
if (bytesRead > MAX_TELEMETRY_CONFIG_BYTES)
|
|
65896
|
-
return;
|
|
65897
|
-
return parseConfig(JSON.parse(content.subarray(0, bytesRead).toString("utf8")));
|
|
65898
|
-
} catch {
|
|
65899
|
-
return;
|
|
65900
|
-
} finally {
|
|
65901
|
-
if (fd !== undefined) {
|
|
65902
|
-
try {
|
|
65903
|
-
closeSync6(fd);
|
|
65904
|
-
} catch {}
|
|
65905
|
-
}
|
|
65906
|
-
}
|
|
65907
|
-
}
|
|
65908
66251
|
function startTelemetry(telemetry, command, context) {
|
|
65909
66252
|
if (!telemetry)
|
|
65910
66253
|
return false;
|
|
@@ -65963,12 +66306,15 @@ function createProgram(options = {}) {
|
|
|
65963
66306
|
const opts = thisCommand.optsWithGlobals();
|
|
65964
66307
|
logger.init({ debug: opts.debug });
|
|
65965
66308
|
if (shouldRunBackgroundChecks(actionCommand.name())) {
|
|
66309
|
+
const launchesTUI = actionCommand.parent === null;
|
|
65966
66310
|
if (!process.env.CI) {
|
|
65967
|
-
const launchesTUI = actionCommand.parent === null;
|
|
65968
66311
|
await checkForUpdates({ notify: !launchesTUI });
|
|
65969
66312
|
}
|
|
65970
66313
|
checkForSkillUpdates();
|
|
65971
66314
|
checkForReadyTasks();
|
|
66315
|
+
if (shouldRunMcpRefreshCheck(actionCommand)) {
|
|
66316
|
+
checkForMcpRefresh({ notify: !launchesTUI });
|
|
66317
|
+
}
|
|
65972
66318
|
}
|
|
65973
66319
|
const command = commandTelemetryName(actionCommand);
|
|
65974
66320
|
if (options.telemetry && shouldTrackCommand(command)) {
|
|
@@ -66195,6 +66541,31 @@ Start ${provider.name()} in any project to use the Dosu MCP.`);
|
|
|
66195
66541
|
Start ${provider.name()} in this project directory to use the Dosu MCP.`);
|
|
66196
66542
|
}
|
|
66197
66543
|
});
|
|
66544
|
+
mcp.command("refresh").description("Rewrite the Dosu MCP entry in every configured AI tool from the current setup").action(() => {
|
|
66545
|
+
const cfg = loadConfig();
|
|
66546
|
+
if (!canRefreshMcp(cfg)) {
|
|
66547
|
+
throw new CliUsageError("Dosu is not set up yet. Run 'dosu setup' first");
|
|
66548
|
+
}
|
|
66549
|
+
const configured = configuredProviders();
|
|
66550
|
+
if (configured.length === 0) {
|
|
66551
|
+
console.log("No AI tools with Dosu configured. Run 'dosu setup' to add Dosu to a tool.");
|
|
66552
|
+
return;
|
|
66553
|
+
}
|
|
66554
|
+
console.log(`Refreshing Dosu MCP config for configured AI tools...
|
|
66555
|
+
`);
|
|
66556
|
+
const result = refreshConfiguredProviders(cfg);
|
|
66557
|
+
writeMcpRefreshCache({ version: VERSION });
|
|
66558
|
+
for (const provider of result.updated) {
|
|
66559
|
+
console.log(` ✓ ${provider.name()}`);
|
|
66560
|
+
}
|
|
66561
|
+
for (const { provider, error } of result.failed) {
|
|
66562
|
+
console.log(` ✗ ${provider.name()}: ${error.message}`);
|
|
66563
|
+
}
|
|
66564
|
+
console.log(`
|
|
66565
|
+
Restart your AI agents so they pick up the change.`);
|
|
66566
|
+
if (result.failed.length > 0)
|
|
66567
|
+
process.exitCode = 1;
|
|
66568
|
+
});
|
|
66198
66569
|
mcp.command("list").description("List available AI tools").action(() => {
|
|
66199
66570
|
console.log(`Available AI tools:
|
|
66200
66571
|
`);
|
|
@@ -66275,7 +66646,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
66275
66646
|
}
|
|
66276
66647
|
if (opts.follow) {
|
|
66277
66648
|
try {
|
|
66278
|
-
const lines =
|
|
66649
|
+
const lines = readFileSync28(logPath, "utf-8").split(`
|
|
66279
66650
|
`);
|
|
66280
66651
|
if (lines.at(-1) === "")
|
|
66281
66652
|
lines.pop();
|
|
@@ -66291,7 +66662,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
66291
66662
|
if (opts.tail !== undefined) {
|
|
66292
66663
|
const n = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
|
|
66293
66664
|
try {
|
|
66294
|
-
const content =
|
|
66665
|
+
const content = readFileSync28(logPath, "utf-8");
|
|
66295
66666
|
const lines = content.split(`
|
|
66296
66667
|
`);
|
|
66297
66668
|
console.log(lines.slice(-n).join(`
|
|
@@ -66343,7 +66714,7 @@ function processCommandTelemetry() {
|
|
|
66343
66714
|
return;
|
|
66344
66715
|
}
|
|
66345
66716
|
}
|
|
66346
|
-
var TELEMETRY_FLUSH_TIMEOUT_MS = 750,
|
|
66717
|
+
var TELEMETRY_FLUSH_TIMEOUT_MS = 750, CliUsageError, FOLLOW_POLL_MS = 500, DEFAULT_TAIL_LINES = 50;
|
|
66347
66718
|
var init_cli = __esm(() => {
|
|
66348
66719
|
init_commander();
|
|
66349
66720
|
init_client();
|
|
@@ -66369,13 +66740,14 @@ var init_cli = __esm(() => {
|
|
|
66369
66740
|
init_follow();
|
|
66370
66741
|
init_logger();
|
|
66371
66742
|
init_providers();
|
|
66743
|
+
init_refresh();
|
|
66372
66744
|
init_styles();
|
|
66373
66745
|
init_settings();
|
|
66374
66746
|
init_telemetry();
|
|
66747
|
+
init_mcp_refresh_check();
|
|
66375
66748
|
init_pending_tasks_check();
|
|
66376
66749
|
init_skill_update_check();
|
|
66377
66750
|
init_update_check();
|
|
66378
|
-
MAX_TELEMETRY_CONFIG_BYTES = 64 * 1024;
|
|
66379
66751
|
CliUsageError = class CliUsageError extends Error {
|
|
66380
66752
|
exitCode = 1;
|
|
66381
66753
|
constructor(message) {
|
|
@@ -66416,4 +66788,4 @@ main().catch((err) => {
|
|
|
66416
66788
|
process.exit(1);
|
|
66417
66789
|
});
|
|
66418
66790
|
|
|
66419
|
-
//# debugId=
|
|
66791
|
+
//# debugId=6712b11a-8117-30cb-6475-6e2164756e21
|