@dosu/cli 0.58.1 → 0.60.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 +14 -6
- package/bin/dosu.js +1310 -414
- package/package.json +2 -1
package/bin/dosu.js
CHANGED
|
@@ -1083,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
1083
1083
|
function getVersionString() {
|
|
1084
1084
|
return `v${VERSION}`;
|
|
1085
1085
|
}
|
|
1086
|
-
var VERSION = "0.
|
|
1086
|
+
var VERSION = "0.60.0", INSTALL_CHANNEL = "npm";
|
|
1087
1087
|
|
|
1088
1088
|
// src/debug/logger.ts
|
|
1089
1089
|
import {
|
|
@@ -13741,12 +13741,70 @@ var init_sync = __esm(() => {
|
|
|
13741
13741
|
init_watermark();
|
|
13742
13742
|
});
|
|
13743
13743
|
|
|
13744
|
+
// src/learner/conflicts.ts
|
|
13745
|
+
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "node:fs";
|
|
13746
|
+
function managedSettingsPaths(platform = process.platform) {
|
|
13747
|
+
switch (platform) {
|
|
13748
|
+
case "darwin":
|
|
13749
|
+
return ["/Library/Application Support/ClaudeCode/managed-settings.json"];
|
|
13750
|
+
case "win32":
|
|
13751
|
+
return ["C:\\ProgramData\\ClaudeCode\\managed-settings.json"];
|
|
13752
|
+
default:
|
|
13753
|
+
return ["/etc/claude-code/managed-settings.json"];
|
|
13754
|
+
}
|
|
13755
|
+
}
|
|
13756
|
+
function conflictingKeysIn(settings) {
|
|
13757
|
+
const keys = [];
|
|
13758
|
+
for (const key of CONFLICTING_KEYS) {
|
|
13759
|
+
if (key in settings)
|
|
13760
|
+
keys.push(key);
|
|
13761
|
+
}
|
|
13762
|
+
const env = settings.env;
|
|
13763
|
+
if (typeof env === "object" && env !== null && !Array.isArray(env)) {
|
|
13764
|
+
for (const name of Object.keys(env)) {
|
|
13765
|
+
if (CONFLICTING_ENV_PREFIXES.some((p) => name.startsWith(p)))
|
|
13766
|
+
keys.push(`env.${name}`);
|
|
13767
|
+
}
|
|
13768
|
+
}
|
|
13769
|
+
return keys;
|
|
13770
|
+
}
|
|
13771
|
+
function detectSettingsConflicts(paths = managedSettingsPaths()) {
|
|
13772
|
+
const conflicts = [];
|
|
13773
|
+
for (const file of paths) {
|
|
13774
|
+
if (!existsSync13(file))
|
|
13775
|
+
continue;
|
|
13776
|
+
let settings;
|
|
13777
|
+
try {
|
|
13778
|
+
settings = JSON.parse(readFileSync15(file, "utf8"));
|
|
13779
|
+
} catch {
|
|
13780
|
+
conflicts.push({ file, keys: [UNREADABLE_SETTINGS_KEY] });
|
|
13781
|
+
continue;
|
|
13782
|
+
}
|
|
13783
|
+
if (typeof settings !== "object" || settings === null)
|
|
13784
|
+
continue;
|
|
13785
|
+
const keys = conflictingKeysIn(settings);
|
|
13786
|
+
if (keys.length > 0)
|
|
13787
|
+
conflicts.push({ file, keys });
|
|
13788
|
+
}
|
|
13789
|
+
return conflicts;
|
|
13790
|
+
}
|
|
13791
|
+
var CONFLICTING_KEYS, CONFLICTING_ENV_PREFIXES, UNREADABLE_SETTINGS_KEY = "<unreadable or invalid JSON>";
|
|
13792
|
+
var init_conflicts = __esm(() => {
|
|
13793
|
+
CONFLICTING_KEYS = [
|
|
13794
|
+
"apiKeyHelper",
|
|
13795
|
+
"forceLoginMethod",
|
|
13796
|
+
"awsAuthRefresh",
|
|
13797
|
+
"awsCredentialExport"
|
|
13798
|
+
];
|
|
13799
|
+
CONFLICTING_ENV_PREFIXES = ["ANTHROPIC_", "CLAUDE_CODE_", "AWS_"];
|
|
13800
|
+
});
|
|
13801
|
+
|
|
13744
13802
|
// src/telemetry/debug-id.ts
|
|
13745
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
13803
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "bd089d5e-a4ab-0f80-6475-6e2164756e21";
|
|
13746
13804
|
|
|
13747
13805
|
// src/telemetry/telemetry.ts
|
|
13748
13806
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
13749
|
-
import { existsSync as
|
|
13807
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
13750
13808
|
import { request as httpRequest2 } from "node:http";
|
|
13751
13809
|
import { request as httpsRequest } from "node:https";
|
|
13752
13810
|
import { isAbsolute, relative, resolve as resolve2, sep } from "node:path";
|
|
@@ -13884,7 +13942,7 @@ function parseOwnedStackLine(originalLine, packageRoot) {
|
|
|
13884
13942
|
return;
|
|
13885
13943
|
}
|
|
13886
13944
|
try {
|
|
13887
|
-
if (!
|
|
13945
|
+
if (!existsSync14(resolvedPath))
|
|
13888
13946
|
return;
|
|
13889
13947
|
} catch {
|
|
13890
13948
|
return;
|
|
@@ -13970,6 +14028,29 @@ function allowlisted(value, allowed) {
|
|
|
13970
14028
|
function matching(value, pattern) {
|
|
13971
14029
|
return typeof value === "string" && pattern.test(value) ? value : undefined;
|
|
13972
14030
|
}
|
|
14031
|
+
function conflictKeysFacet(value) {
|
|
14032
|
+
if (!Array.isArray(value))
|
|
14033
|
+
return;
|
|
14034
|
+
const keys = new Set;
|
|
14035
|
+
for (const raw of value) {
|
|
14036
|
+
if (typeof raw !== "string")
|
|
14037
|
+
continue;
|
|
14038
|
+
if (SETTINGS_CONFLICT_KEYS.has(raw))
|
|
14039
|
+
keys.add(raw);
|
|
14040
|
+
else if (raw === UNREADABLE_SETTINGS_KEY)
|
|
14041
|
+
keys.add("unreadable");
|
|
14042
|
+
else
|
|
14043
|
+
keys.add(SETTINGS_CONFLICT_FAMILIES.find(([p]) => raw.startsWith(p))?.[1] ?? "other");
|
|
14044
|
+
}
|
|
14045
|
+
let joined = "";
|
|
14046
|
+
for (const key of [...keys].sort()) {
|
|
14047
|
+
const next = joined ? `${joined},${key}` : key;
|
|
14048
|
+
if (next.length > MAX_CONFLICT_KEYS_LENGTH)
|
|
14049
|
+
break;
|
|
14050
|
+
joined = next;
|
|
14051
|
+
}
|
|
14052
|
+
return joined || undefined;
|
|
14053
|
+
}
|
|
13973
14054
|
function sanitizeFacets(facets) {
|
|
13974
14055
|
if (!facets || typeof facets !== "object")
|
|
13975
14056
|
return {};
|
|
@@ -13977,6 +14058,7 @@ function sanitizeFacets(facets) {
|
|
|
13977
14058
|
const status = allowlisted(facets.sync_status, SYNC_STATUSES);
|
|
13978
14059
|
const learner = allowlisted(facets.learner_outcome, LEARNER_OUTCOMES);
|
|
13979
14060
|
const gatewayReason = allowlisted(facets.gateway_reason, GATEWAY_REASONS);
|
|
14061
|
+
const conflictKeys = conflictKeysFacet(facets.settings_conflict_keys);
|
|
13980
14062
|
const claudeSource = allowlisted(facets.claude_code_source, CLAUDE_CODE_SOURCES);
|
|
13981
14063
|
const claudeVersion = matching(facets.claude_code_version, CLAUDE_CODE_VERSION_PATTERN);
|
|
13982
14064
|
const model = matching(facets.learner_model, LEARNER_MODEL_PATTERN);
|
|
@@ -13988,6 +14070,7 @@ function sanitizeFacets(facets) {
|
|
|
13988
14070
|
...facets.notes_written !== undefined ? { notes_written: countBucket(facets.notes_written) } : {},
|
|
13989
14071
|
...learner ? { learner_outcome: learner } : {},
|
|
13990
14072
|
...gatewayReason ? { gateway_reason: gatewayReason } : {},
|
|
14073
|
+
...conflictKeys ? { settings_conflict_keys: conflictKeys } : {},
|
|
13991
14074
|
...claudeSource ? { claude_code_source: claudeSource } : {},
|
|
13992
14075
|
...claudeVersion ? { claude_code_version: claudeVersion } : {},
|
|
13993
14076
|
...model ? { learner_model: model } : {},
|
|
@@ -14115,7 +14198,8 @@ function exceptionSummary(command, error, facets) {
|
|
|
14115
14198
|
const outcome = facets.learner_outcome ?? facets.sync_status;
|
|
14116
14199
|
if (!outcome)
|
|
14117
14200
|
return error.code ?? error.type;
|
|
14118
|
-
|
|
14201
|
+
const detail = facets.gateway_reason ?? facets.settings_conflict_keys;
|
|
14202
|
+
return `${command}: ${outcome}${detail ? ` (${detail})` : ""}`;
|
|
14119
14203
|
}
|
|
14120
14204
|
function buildSentryEnvelope(input) {
|
|
14121
14205
|
const parsedDsn = parseSentryDsn(input.dsn);
|
|
@@ -14517,8 +14601,9 @@ function createCommandTelemetry(settings, dependencies = {}) {
|
|
|
14517
14601
|
function shouldSendToSentry(error) {
|
|
14518
14602
|
return !["SESSION_EXPIRED", "SESSION_PERSISTENCE_ERROR"].includes(error.code ?? "");
|
|
14519
14603
|
}
|
|
14520
|
-
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;
|
|
14604
|
+
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, SETTINGS_CONFLICT_KEYS, SETTINGS_CONFLICT_FAMILIES, MAX_CONFLICT_KEYS_LENGTH = 200, CLAUDE_CODE_VERSION_PATTERN, LEARNER_MODEL_PATTERN, BACKFILL_OFFERS, SENTRY_FACET_TAGS, pendingFacets;
|
|
14521
14605
|
var init_telemetry = __esm(() => {
|
|
14606
|
+
init_conflicts();
|
|
14522
14607
|
MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
14523
14608
|
CLI_PACKAGE_ROOT = detectCliPackageRoot();
|
|
14524
14609
|
SAFE_ERROR_TYPES = new Set([
|
|
@@ -14635,6 +14720,58 @@ var init_telemetry = __esm(() => {
|
|
|
14635
14720
|
"other"
|
|
14636
14721
|
]);
|
|
14637
14722
|
CLAUDE_CODE_SOURCES = new Set(["sdk", "system", "missing"]);
|
|
14723
|
+
SETTINGS_CONFLICT_KEYS = new Set([
|
|
14724
|
+
"apiKeyHelper",
|
|
14725
|
+
"forceLoginMethod",
|
|
14726
|
+
"awsAuthRefresh",
|
|
14727
|
+
"awsCredentialExport",
|
|
14728
|
+
"env.ANTHROPIC_API_KEY",
|
|
14729
|
+
"env.ANTHROPIC_AUTH_TOKEN",
|
|
14730
|
+
"env.ANTHROPIC_BASE_URL",
|
|
14731
|
+
"env.ANTHROPIC_CUSTOM_HEADERS",
|
|
14732
|
+
"env.ANTHROPIC_MODEL",
|
|
14733
|
+
"env.ANTHROPIC_SMALL_FAST_MODEL",
|
|
14734
|
+
"env.ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
14735
|
+
"env.ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
14736
|
+
"env.ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
14737
|
+
"env.ANTHROPIC_BEDROCK_BASE_URL",
|
|
14738
|
+
"env.ANTHROPIC_VERTEX_BASE_URL",
|
|
14739
|
+
"env.ANTHROPIC_VERTEX_PROJECT_ID",
|
|
14740
|
+
"env.ANTHROPIC_FOUNDRY_BASE_URL",
|
|
14741
|
+
"env.ANTHROPIC_FOUNDRY_API_KEY",
|
|
14742
|
+
"env.ANTHROPIC_AWS_BASE_URL",
|
|
14743
|
+
"env.ANTHROPIC_BEDROCK_MANTLE_BASE_URL",
|
|
14744
|
+
"env.ANTHROPIC_AWS_API_KEY",
|
|
14745
|
+
"env.ANTHROPIC_PROFILE",
|
|
14746
|
+
"env.ANTHROPIC_ENVIRONMENT_KEY",
|
|
14747
|
+
"env.ANTHROPIC_IDENTITY_TOKEN",
|
|
14748
|
+
"env.ANTHROPIC_FEDERATION_RULE_ID",
|
|
14749
|
+
"env.ANTHROPIC_SERVICE_ACCOUNT_ID",
|
|
14750
|
+
"env.CLAUDE_CODE_USE_BEDROCK",
|
|
14751
|
+
"env.CLAUDE_CODE_USE_VERTEX",
|
|
14752
|
+
"env.CLAUDE_CODE_USE_FOUNDRY",
|
|
14753
|
+
"env.CLAUDE_CODE_USE_MANTLE",
|
|
14754
|
+
"env.CLAUDE_CODE_USE_ANTHROPIC_AWS",
|
|
14755
|
+
"env.CLAUDE_CODE_OAUTH_TOKEN",
|
|
14756
|
+
"env.CLAUDE_CODE_API_BASE_URL",
|
|
14757
|
+
"env.CLAUDE_CODE_SKIP_BEDROCK_AUTH",
|
|
14758
|
+
"env.CLAUDE_CODE_SKIP_VERTEX_AUTH",
|
|
14759
|
+
"env.CLAUDE_CODE_API_KEY_HELPER_TTL_MS",
|
|
14760
|
+
"env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC",
|
|
14761
|
+
"env.CLAUDE_CODE_ENABLE_TELEMETRY",
|
|
14762
|
+
"env.CLAUDE_CODE_MAX_OUTPUT_TOKENS",
|
|
14763
|
+
"env.AWS_REGION",
|
|
14764
|
+
"env.AWS_PROFILE",
|
|
14765
|
+
"env.AWS_BEARER_TOKEN_BEDROCK",
|
|
14766
|
+
"env.AWS_ACCESS_KEY_ID",
|
|
14767
|
+
"env.AWS_SECRET_ACCESS_KEY",
|
|
14768
|
+
"env.AWS_SESSION_TOKEN"
|
|
14769
|
+
]);
|
|
14770
|
+
SETTINGS_CONFLICT_FAMILIES = [
|
|
14771
|
+
["env.ANTHROPIC_", "env.ANTHROPIC_other"],
|
|
14772
|
+
["env.CLAUDE_CODE_", "env.CLAUDE_CODE_other"],
|
|
14773
|
+
["env.AWS_", "env.AWS_other"]
|
|
14774
|
+
];
|
|
14638
14775
|
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})?$/;
|
|
14639
14776
|
LEARNER_MODEL_PATTERN = /^claude-[a-z0-9.-]{1,56}$/;
|
|
14640
14777
|
BACKFILL_OFFERS = new Set([
|
|
@@ -14649,6 +14786,7 @@ var init_telemetry = __esm(() => {
|
|
|
14649
14786
|
"sync_status",
|
|
14650
14787
|
"learner_outcome",
|
|
14651
14788
|
"gateway_reason",
|
|
14789
|
+
"settings_conflict_keys",
|
|
14652
14790
|
"claude_code_source",
|
|
14653
14791
|
"claude_code_version",
|
|
14654
14792
|
"learner_model"
|
|
@@ -14682,7 +14820,7 @@ var init_agent_select = __esm(() => {
|
|
|
14682
14820
|
});
|
|
14683
14821
|
|
|
14684
14822
|
// src/incognito/agents.ts
|
|
14685
|
-
import { existsSync as
|
|
14823
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "node:fs";
|
|
14686
14824
|
import { homedir as homedir4 } from "node:os";
|
|
14687
14825
|
import { dirname as dirname5, join as join13 } from "node:path";
|
|
14688
14826
|
function withFrontmatter(body) {
|
|
@@ -14707,18 +14845,18 @@ function fileAgent(options) {
|
|
|
14707
14845
|
commandPath,
|
|
14708
14846
|
isEnabled: () => {
|
|
14709
14847
|
const path = commandPath();
|
|
14710
|
-
if (!
|
|
14848
|
+
if (!existsSync15(path))
|
|
14711
14849
|
return false;
|
|
14712
14850
|
try {
|
|
14713
|
-
return
|
|
14851
|
+
return readFileSync16(path, "utf-8").includes(INCOGNITO_MARKER);
|
|
14714
14852
|
} catch {
|
|
14715
14853
|
return false;
|
|
14716
14854
|
}
|
|
14717
14855
|
},
|
|
14718
14856
|
enable: () => {
|
|
14719
14857
|
const path = commandPath();
|
|
14720
|
-
if (
|
|
14721
|
-
if (
|
|
14858
|
+
if (existsSync15(path)) {
|
|
14859
|
+
if (readFileSync16(path, "utf-8") === content)
|
|
14722
14860
|
return "unchanged";
|
|
14723
14861
|
writeFileSync10(path, content, "utf-8");
|
|
14724
14862
|
return "updated";
|
|
@@ -14729,7 +14867,7 @@ function fileAgent(options) {
|
|
|
14729
14867
|
},
|
|
14730
14868
|
disable: () => {
|
|
14731
14869
|
const path = commandPath();
|
|
14732
|
-
if (!
|
|
14870
|
+
if (!existsSync15(path))
|
|
14733
14871
|
return "not_found";
|
|
14734
14872
|
unlinkSync2(path);
|
|
14735
14873
|
return "removed";
|
|
@@ -15171,64 +15309,6 @@ function createRunConfigDir() {
|
|
|
15171
15309
|
}
|
|
15172
15310
|
var init_config_dir = () => {};
|
|
15173
15311
|
|
|
15174
|
-
// src/learner/conflicts.ts
|
|
15175
|
-
import { existsSync as existsSync15, readFileSync as readFileSync16 } from "node:fs";
|
|
15176
|
-
function managedSettingsPaths(platform = process.platform) {
|
|
15177
|
-
switch (platform) {
|
|
15178
|
-
case "darwin":
|
|
15179
|
-
return ["/Library/Application Support/ClaudeCode/managed-settings.json"];
|
|
15180
|
-
case "win32":
|
|
15181
|
-
return ["C:\\ProgramData\\ClaudeCode\\managed-settings.json"];
|
|
15182
|
-
default:
|
|
15183
|
-
return ["/etc/claude-code/managed-settings.json"];
|
|
15184
|
-
}
|
|
15185
|
-
}
|
|
15186
|
-
function conflictingKeysIn(settings) {
|
|
15187
|
-
const keys = [];
|
|
15188
|
-
for (const key of CONFLICTING_KEYS) {
|
|
15189
|
-
if (key in settings)
|
|
15190
|
-
keys.push(key);
|
|
15191
|
-
}
|
|
15192
|
-
const env = settings.env;
|
|
15193
|
-
if (typeof env === "object" && env !== null && !Array.isArray(env)) {
|
|
15194
|
-
for (const name of Object.keys(env)) {
|
|
15195
|
-
if (CONFLICTING_ENV_PREFIXES.some((p) => name.startsWith(p)))
|
|
15196
|
-
keys.push(`env.${name}`);
|
|
15197
|
-
}
|
|
15198
|
-
}
|
|
15199
|
-
return keys;
|
|
15200
|
-
}
|
|
15201
|
-
function detectSettingsConflicts(paths = managedSettingsPaths()) {
|
|
15202
|
-
const conflicts = [];
|
|
15203
|
-
for (const file of paths) {
|
|
15204
|
-
if (!existsSync15(file))
|
|
15205
|
-
continue;
|
|
15206
|
-
let settings;
|
|
15207
|
-
try {
|
|
15208
|
-
settings = JSON.parse(readFileSync16(file, "utf8"));
|
|
15209
|
-
} catch {
|
|
15210
|
-
conflicts.push({ file, keys: ["<unreadable or invalid JSON>"] });
|
|
15211
|
-
continue;
|
|
15212
|
-
}
|
|
15213
|
-
if (typeof settings !== "object" || settings === null)
|
|
15214
|
-
continue;
|
|
15215
|
-
const keys = conflictingKeysIn(settings);
|
|
15216
|
-
if (keys.length > 0)
|
|
15217
|
-
conflicts.push({ file, keys });
|
|
15218
|
-
}
|
|
15219
|
-
return conflicts;
|
|
15220
|
-
}
|
|
15221
|
-
var CONFLICTING_KEYS, CONFLICTING_ENV_PREFIXES;
|
|
15222
|
-
var init_conflicts = __esm(() => {
|
|
15223
|
-
CONFLICTING_KEYS = [
|
|
15224
|
-
"apiKeyHelper",
|
|
15225
|
-
"forceLoginMethod",
|
|
15226
|
-
"awsAuthRefresh",
|
|
15227
|
-
"awsCredentialExport"
|
|
15228
|
-
];
|
|
15229
|
-
CONFLICTING_ENV_PREFIXES = ["ANTHROPIC_", "CLAUDE_CODE_", "AWS_"];
|
|
15230
|
-
});
|
|
15231
|
-
|
|
15232
15312
|
// src/learner/env.ts
|
|
15233
15313
|
function isStripped(name) {
|
|
15234
15314
|
return STRIPPED_NAMES.has(name) || STRIPPED_PREFIXES.some((p) => name.startsWith(p));
|
|
@@ -58365,7 +58445,8 @@ async function runLearner(options) {
|
|
|
58365
58445
|
outcome: "settings_conflict",
|
|
58366
58446
|
notesWritten: 0,
|
|
58367
58447
|
turns: 0,
|
|
58368
|
-
message: `Refusing to run: conflicting Claude Code settings would override the study run's auth (${detail})
|
|
58448
|
+
message: `Refusing to run: conflicting Claude Code settings would override the study run's auth (${detail})`,
|
|
58449
|
+
conflictKeys: conflicts.flatMap((c) => c.keys)
|
|
58369
58450
|
};
|
|
58370
58451
|
}
|
|
58371
58452
|
const gatewayURL = options.gatewayURL ?? getLlmGatewayURL();
|
|
@@ -58803,6 +58884,7 @@ function learnerFacets(learner) {
|
|
|
58803
58884
|
return {
|
|
58804
58885
|
learner_outcome: learner.outcome,
|
|
58805
58886
|
...learner.gatewayReason ? { gateway_reason: learner.gatewayReason } : {},
|
|
58887
|
+
...learner.conflictKeys ? { settings_conflict_keys: learner.conflictKeys } : {},
|
|
58806
58888
|
...learner.claudeCodeSource ? { claude_code_source: learner.claudeCodeSource } : {},
|
|
58807
58889
|
...learner.claudeCodeVersion ? { claude_code_version: learner.claudeCodeVersion } : {},
|
|
58808
58890
|
...learner.model ? { learner_model: learner.model } : {}
|
|
@@ -59799,255 +59881,1036 @@ var init_review = __esm(() => {
|
|
|
59799
59881
|
import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
59800
59882
|
});
|
|
59801
59883
|
|
|
59802
|
-
// src/
|
|
59803
|
-
|
|
59804
|
-
|
|
59805
|
-
|
|
59806
|
-
|
|
59884
|
+
// src/generated/skills.ts
|
|
59885
|
+
var BUNDLED_SKILLS;
|
|
59886
|
+
var init_skills = __esm(() => {
|
|
59887
|
+
BUNDLED_SKILLS = [
|
|
59888
|
+
{
|
|
59889
|
+
name: "dosu",
|
|
59890
|
+
files: [
|
|
59891
|
+
{
|
|
59892
|
+
path: "SKILL.md",
|
|
59893
|
+
content: "---\nname: dosu\ndescription: 'Use the Dosu CLI to authenticate and configure coding agents; manage Libraries, Agents, sources, Monitor, documents, reviews, threads, topics, members, integrations, and deployments; query knowledge; or audit a repository for Dosu-generated docs. Use for Dosu platform work that should be done from a terminal instead of the web app.'\n---\n\n# Use the Dosu CLI\n\nOperate Dosu through `dosu`. Prefer structured output and let the CLI and App validate product rules.\n\n## Start correctly\n\n1. Run `dosu --version`. Do not probe installation with unrelated package-manager commands.\n2. If it is unavailable and Node is present, try `npx -y @dosu/cli --version` and use `npx -y @dosu/cli` as the command prefix for this session. Otherwise ask before installing anything.\n3. Run `dosu --help` or the relevant nested `--help` before using a command not covered by [the command reference](references/commands.md).\n4. Pass `--json` whenever that leaf command exposes it. Parse the result; do not scrape the human table.\n\n## Satisfy the right prerequisite\n\n- `dosu login` supplies the JWT used by tRPC-backed commands.\n- `dosu setup` selects an organization, Library context, and MCP deployment, creates an API key, and can configure an agent tool.\n- `dosu ask` needs an API key. `docs generate`, `docs auto-tag`, and `docs publish` need both JWT login and the API key. Other platform commands generally need JWT login; commands scoped to an organization or current Library also need the corresponding setup selection.\n- For coding-agent setup, follow the nonblocking `dosu setup --agent --tool <id>` workflow in [workflows.md](references/workflows.md). Relay its URL and execute its returned `resume_command`; never invent ticket commands.\n\n## Use current product terms\n\n- **Organization** is the account and permission boundary.\n- **Library** is the knowledge container shown in the App. Older APIs may call it a `space`; do not present that internal name to users.\n- **Data source** is an organization-level connection such as a repository, Slack channel, or Notion workspace. A Library can use already-connected sources.\n- **Agent** is a configurable GitHub, GitLab, Slack, or Teams deployment serving exactly one Library.\n- **Monitor** is per Library and source. It supports GitHub, GitLab, and Azure DevOps sources.\n- `dosu deployments` manages selectable **MCP deployments**. Do not use it as an Agent CRUD command.\n\n## Route by intent\n\n| Intent | Route |\n|---|---|\n| Set up Dosu end-to-end (\"set up dosu\", new Library from scratch) | Read the guided onboarding flow in [workflows.md](references/workflows.md) first; it is checkpoint-driven — ask, wait, then act |\n| Create or configure a Library | `dosu libraries ...` |\n| Attach existing organization sources | `dosu sources list` → `dosu libraries sources attach` |\n| Create or configure an Agent | `dosu agents ...` |\n| Ask for a synthesized answer | `dosu ask` |\n| Find source documents | `dosu knowledge search`, then `dosu docs get` |\n| Create, import, or publish docs | `dosu docs ...` |\n| Review a pending doc change or draft reply | Read [review-workflow.md](references/review-workflow.md) first |\n| Inspect conversations | `dosu threads ...` |\n| Browse managed topics | `dosu topics ...` |\n| Audit agent docs, README, architecture, or dependencies | Read [audit.md](references/audit.md) first |\n\nUse [commands.md](references/commands.md) as the sole detailed command and flag reference. Use [workflows.md](references/workflows.md) only for multi-command composition.\n\n## Apply Library and Agent semantics\n\n- To assemble a Library, list organization sources, create the Library, attach the chosen source IDs, then verify with `libraries info` and `libraries sources list`. The CLI cannot establish a brand-new OAuth connection.\n- `libraries sources config` resolves the provider on the App side. Read the command reference before choosing provider-specific options.\n- When creating a Library with a GitHub repository, or newly attaching one to an existing Library, treat Monitor as part of that setup unless the user opts out. Enable it with the whole-repository and `emoji` defaults, verify it, and explain that Monitor reviews pull requests to keep the Library's knowledge up to date. Follow [the Library workflow](references/workflows.md); do not ask the user to choose defaults.\n- Create an Agent from an existing source ID and let the App choose its defaults; do not synthesize config in shell commands. Each data source can back at most one Agent: a `CONFLICT` (409) from `agents create` means the source already has one — offer a different source or an authorized `agents move` instead of retrying.\n- Read Agent config before changing one existing leaf. Values are JSON. If a concurrent write returns `CONFLICT`, read again, re-evaluate the requested change, and retry only if it is still correct.\n- Moving an Agent replaces its Library. Verify the returned `space_id`; do not infer migration behavior for historical data from the move receipt.\n\n## Respect write boundaries\n\n- Treat an explicit, unambiguous user request for the exact mutation as authorization. Otherwise show the intended change and wait for confirmation.\n- For commands exposing `--confirm`, omit it first when a preview is useful; `{ \"confirmRequired\": true, \"applied\": false }` means nothing changed. Pass `--confirm` only after authorization.\n- Never batch-approve or batch-reject review items. Diff one item, explain it, and decide only the ID the user authorized.\n- Before deleting a Library, Agent, source, or document, state the exact target and impact. Before detaching a source, read and state the impact documented in the command reference. Some older delete commands do not enforce `--confirm`; the absence of a CLI prompt is not user approval.\n- Before attaching a source to a public Library, warn that its content becomes available to everyone who can access that Library.\n- OAuth connection and billing remain web-only. Report the boundary instead of claiming success.\n\n## Handle failures literally\n\n- `Not logged in` or an unrecoverable expired session: run `dosu login` (agent setup may instead return a ticket flow).\n- Missing organization, Library, deployment, or API-key context: run the appropriate `dosu setup` flow.\n- `confirmRequired`: no write occurred.\n- `CONFLICT` on config: reread before retrying.\n- A tRPC or backend error is a failed operation. Surface the code/path/status and do not imply the requested state exists.\n\n## References\n\n- [commands.md](references/commands.md): authoritative CLI syntax, choices, defaults, conflicts, and prerequisites\n- [workflows.md](references/workflows.md): reusable multi-command flows\n- [review-workflow.md](references/review-workflow.md): review safety and context\n- [audit.md](references/audit.md): repository audit procedure\n- [audit-findings-schema.md](references/audit-findings-schema.md): `.dosu/audit.json` contract\n",
|
|
59894
|
+
executable: false
|
|
59895
|
+
},
|
|
59896
|
+
{
|
|
59897
|
+
path: "references/audit-findings-schema.md",
|
|
59898
|
+
content: `# \`.dosu/audit.json\` — audit findings schema
|
|
59899
|
+
|
|
59900
|
+
The codebase audit (see [audit.md](audit.md)) writes its result to \`.dosu/audit.json\` at the
|
|
59901
|
+
repo root. This file is the contract between the audit you run in the coding agent and the
|
|
59902
|
+
\`dosu audit\` CLI command, which reads it, asks the user which docs to generate, and kicks off
|
|
59903
|
+
generation on Dosu cloud.
|
|
59904
|
+
|
|
59905
|
+
Write valid JSON matching this shape exactly. Do not add fields the CLI doesn't expect.
|
|
59906
|
+
|
|
59907
|
+
\`\`\`json
|
|
59908
|
+
{
|
|
59909
|
+
"version": 1,
|
|
59910
|
+
"generated_at": "2026-06-24T12:00:00Z",
|
|
59911
|
+
"repo": {
|
|
59912
|
+
"remote": "git@github.com:org/repo.git",
|
|
59913
|
+
"slug": "org/repo"
|
|
59914
|
+
},
|
|
59915
|
+
"items": [
|
|
59916
|
+
{
|
|
59917
|
+
"task": "generate-agents-md",
|
|
59918
|
+
"type": "agents",
|
|
59919
|
+
"file": "AGENTS.md",
|
|
59920
|
+
"status": "missing",
|
|
59921
|
+
"action": "create",
|
|
59922
|
+
"can_help": true,
|
|
59923
|
+
"confidence": "high",
|
|
59924
|
+
"rationale": "No AGENTS.md found; the repo has a clear src/ layout, a documented test command, and commit conventions worth capturing for agents.",
|
|
59925
|
+
"evidence": ["package.json", "src/cli/cli.ts", "CONTRIBUTING.md"]
|
|
59926
|
+
}
|
|
59927
|
+
]
|
|
59928
|
+
}
|
|
59929
|
+
\`\`\`
|
|
59930
|
+
|
|
59931
|
+
## Top-level fields
|
|
59932
|
+
|
|
59933
|
+
| Field | Type | Notes |
|
|
59934
|
+
|---|---|---|
|
|
59935
|
+
| \`version\` | number | Always \`1\`. The CLI rejects other versions. |
|
|
59936
|
+
| \`generated_at\` | string | ISO 8601 timestamp of when the audit ran. |
|
|
59937
|
+
| \`repo.remote\` | string | The \`git remote origin\` URL, verbatim. |
|
|
59938
|
+
| \`repo.slug\` | string | \`owner/name\` parsed from the remote (e.g. \`dosu-ai/dosu-cli\`). |
|
|
59939
|
+
| \`items\` | array | One entry per doc type you assessed. Include an entry for every type you looked at, even when \`can_help\` is \`false\` — the CLI uses these to explain what it skipped. |
|
|
59940
|
+
|
|
59941
|
+
## Item fields
|
|
59942
|
+
|
|
59943
|
+
| Field | Type | Allowed values | Notes |
|
|
59944
|
+
|---|---|---|---|
|
|
59945
|
+
| \`task\` | string | \`generate-agents-md\`, \`refresh-readme\`, \`generate-architecture-md\`, \`generate-deps-md\` | The backend capability id this item maps to. Must be one of these exact strings. |
|
|
59946
|
+
| \`type\` | string | \`agents\`, \`readme\`, \`architecture\`, \`deps\` | Short doc-type key. |
|
|
59947
|
+
| \`file\` | string | — | The target filename in the repo (e.g. \`AGENTS.md\`, \`README.md\`, \`architecture.md\`, \`deps.md\`). Use the casing already present in the repo when updating an existing file. |
|
|
59948
|
+
| \`status\` | string | \`missing\`, \`outdated\`, \`present_ok\` | What you found in the working tree. |
|
|
59949
|
+
| \`action\` | string | \`create\`, \`update\`, \`skip\` | What Dosu should do. \`create\` when \`missing\`; \`update\` when \`outdated\`; \`skip\` when \`present_ok\` (or when not enough info). |
|
|
59950
|
+
| \`can_help\` | boolean | — | Whether Dosu should offer this. \`false\` ⇒ the CLI shows it as not recommended (or omits it). |
|
|
59951
|
+
| \`confidence\` | string | \`high\`, \`medium\`, \`low\` | Your confidence in the recommendation. |
|
|
59952
|
+
| \`rationale\` | string | — | One or two sentences explaining the recommendation, citing what you saw. This is passed to Dosu cloud as generation guidance, so make it specific. |
|
|
59953
|
+
| \`evidence\` | string[] | — | Repo-relative paths (and optionally \`path:line\`) that justify the finding. |
|
|
59954
|
+
|
|
59955
|
+
## Mapping of \`task\` ↔ \`type\` ↔ \`file\`
|
|
59956
|
+
|
|
59957
|
+
| \`task\` | \`type\` | typical \`file\` |
|
|
59958
|
+
|---|---|---|
|
|
59959
|
+
| \`generate-agents-md\` | \`agents\` | \`AGENTS.md\` |
|
|
59960
|
+
| \`refresh-readme\` | \`readme\` | \`README.md\` |
|
|
59961
|
+
| \`generate-architecture-md\` | \`architecture\` | \`architecture.md\` |
|
|
59962
|
+
| \`generate-deps-md\` | \`deps\` | \`deps.md\` |
|
|
59963
|
+
`,
|
|
59964
|
+
executable: false
|
|
59965
|
+
},
|
|
59966
|
+
{
|
|
59967
|
+
path: "references/audit.md",
|
|
59968
|
+
content: `# Dosu codebase audit
|
|
59969
|
+
|
|
59970
|
+
This is the full procedure for the **codebase audit** referenced from [../SKILL.md](../SKILL.md).
|
|
59971
|
+
The goal: inspect the current repository and decide, with evidence, whether Dosu can help the
|
|
59972
|
+
user by creating or refreshing four docs. Write the result to \`.dosu/audit.json\`
|
|
59973
|
+
(see [audit-findings-schema.md](audit-findings-schema.md)), then tell the user to run
|
|
59974
|
+
\`dosu audit\` so the Dosu CLI can ask them which docs to generate and open a PR.
|
|
59975
|
+
|
|
59976
|
+
You (the coding agent) only do the **triage** here — you have the live working tree, so you can
|
|
59977
|
+
tell what exists, what's stale, and whether there's enough signal. You do **not** write the docs
|
|
59978
|
+
themselves; Dosu cloud generates them and opens the PR after the user picks via \`dosu audit\`.
|
|
59979
|
+
|
|
59980
|
+
## When to run this
|
|
59981
|
+
|
|
59982
|
+
Run when the user asks Dosu to audit the repo, asks "what can Dosu do for this codebase?", or
|
|
59983
|
+
asks to set up / refresh their agent docs, README, architecture doc, or dependency doc.
|
|
59984
|
+
|
|
59985
|
+
## The four doc types
|
|
59986
|
+
|
|
59987
|
+
| \`task\` | File | When Dosu can help |
|
|
59988
|
+
|---|---|---|
|
|
59989
|
+
| \`generate-agents-md\` | \`AGENTS.md\` | Missing, or present but stale/thin given the repo's structure, commands, and conventions. |
|
|
59990
|
+
| \`refresh-readme\` | \`README.md\` | Present but **outdated** — references removed scripts/deps, missing setup steps, or describes features that no longer match the code. |
|
|
59991
|
+
| \`generate-architecture-md\` | \`architecture.md\` | **Missing AND** there is genuinely enough structure to describe (multiple modules/services, clear layering). Do not recommend for a tiny or single-file repo. |
|
|
59992
|
+
| \`generate-deps-md\` | \`deps.md\` | Missing, or present but out of sync with the actual dependency manifests. |
|
|
59993
|
+
|
|
59994
|
+
## Rules
|
|
59995
|
+
|
|
59996
|
+
- **Be evidence-based.** Prefer direct repo evidence over inference. Cite concrete \`evidence\`:
|
|
59997
|
+
file paths (and \`path:line\` where useful), manifest entries, config keys.
|
|
59998
|
+
- **Gate \`architecture.md\` strictly.** Only set \`can_help: true\` for \`generate-architecture-md\`
|
|
59999
|
+
when the repo is large/structured enough that a useful architecture doc can be written. When in
|
|
60000
|
+
doubt, set \`can_help: false\`, \`action: "skip"\`, and a \`rationale\` saying why.
|
|
60001
|
+
- **Distinguish status from action.** \`status\` is what you found (\`missing\` / \`outdated\` /
|
|
60002
|
+
\`present_ok\`); \`action\` is what Dosu should do (\`create\` / \`update\` / \`skip\`).
|
|
60003
|
+
- **Include every type you assessed**, even when \`can_help\` is \`false\`, so the CLI can explain
|
|
60004
|
+
what it skipped and why.
|
|
60005
|
+
- **Make \`rationale\` specific** — it is forwarded to Dosu cloud as generation guidance. "README's
|
|
60006
|
+
install section references a \`make bootstrap\` target that no longer exists" beats "README looks
|
|
60007
|
+
old."
|
|
60008
|
+
- **Don't write the docs.** Producing the actual files is Dosu cloud's job, triggered by the user
|
|
60009
|
+
through \`dosu audit\`.
|
|
60010
|
+
|
|
60011
|
+
## Use Dosu MCP for org knowledge
|
|
60012
|
+
|
|
60013
|
+
Before finalizing recommendations, use the Dosu MCP tools to pull organization knowledge that
|
|
60014
|
+
should inform the docs (architecture decisions, naming, conventions, prior docs). The exposed
|
|
60015
|
+
tool set depends on the connection — always use what's actually listed:
|
|
60016
|
+
|
|
60017
|
+
1. Read first: call \`read_knowledge\` when listed (or \`init_knowledge\` on older connections) to
|
|
60018
|
+
get task-relevant context from the knowledge base.
|
|
60019
|
+
2. Go deeper with whichever search/ask tools the server exposes — check whether the org already
|
|
60020
|
+
documents the architecture, dependencies, or agent conventions elsewhere. If it does, factor
|
|
60021
|
+
that into \`status\`/\`rationale\` (e.g. an existing architecture doc in Dosu may mean a repo
|
|
60022
|
+
\`architecture.md\` should mirror it).
|
|
60023
|
+
|
|
60024
|
+
If no Dosu deployment is connected (only public-library tools are available), skip the MCP step
|
|
60025
|
+
and rely on repo evidence alone; note in the \`rationale\` that org knowledge wasn't consulted.
|
|
60026
|
+
|
|
60027
|
+
## Procedure
|
|
60028
|
+
|
|
60029
|
+
1. **Identify the repo.** Get the remote and slug:
|
|
60030
|
+
\`\`\`bash
|
|
60031
|
+
git config --get remote.origin.url
|
|
60032
|
+
\`\`\`
|
|
60033
|
+
Parse \`owner/name\` from it for \`repo.slug\`. If there is no GitHub remote, tell the user the
|
|
60034
|
+
audit needs a GitHub repo connected to Dosu and stop.
|
|
60035
|
+
|
|
60036
|
+
2. **Inspect the working tree** for each doc type. Useful starting points:
|
|
60037
|
+
\`\`\`bash
|
|
60038
|
+
ls -a
|
|
60039
|
+
# existing docs (any casing)
|
|
60040
|
+
ls AGENTS.md README.md architecture.md ARCHITECTURE.md deps.md DEPS.md docs/ 2>/dev/null
|
|
60041
|
+
# dependency manifests
|
|
60042
|
+
ls package.json pyproject.toml requirements*.txt go.mod Cargo.toml Gemfile pom.xml build.gradle 2>/dev/null
|
|
60043
|
+
\`\`\`
|
|
60044
|
+
- **AGENTS.md** — does it exist? If yes, is it consistent with the current build/test commands,
|
|
60045
|
+
directory layout, and contribution conventions? Read it and compare against \`package.json\`
|
|
60046
|
+
scripts / Makefile / CI config.
|
|
60047
|
+
- **README.md** — read it. Are the setup/build/run steps still accurate? Do referenced scripts,
|
|
60048
|
+
commands, env vars, and features still exist in the code? Mark \`outdated\` only with evidence.
|
|
60049
|
+
- **architecture.md** — does it exist? Is the repo structured enough to warrant one? Look at the
|
|
60050
|
+
top-level layout, number of modules/services, and whether there's a clear separation worth
|
|
60051
|
+
documenting.
|
|
60052
|
+
- **deps.md** — does it exist? If yes, does it match the actual manifests/lockfiles? If missing,
|
|
60053
|
+
are there real dependencies worth documenting?
|
|
60054
|
+
|
|
60055
|
+
3. **Consult Dosu MCP** (see above) to enrich and cross-check.
|
|
60056
|
+
|
|
60057
|
+
4. **Write \`.dosu/audit.json\`** following [audit-findings-schema.md](audit-findings-schema.md).
|
|
60058
|
+
Create the \`.dosu/\` directory if needed. Write one \`items\` entry per type you assessed.
|
|
60059
|
+
|
|
60060
|
+
5. **Tell the user to run the CLI.** End with a short message, e.g.:
|
|
60061
|
+
|
|
60062
|
+
> Audit complete — I wrote \`.dosu/audit.json\`. Run \`dosu audit\` to choose which docs Dosu
|
|
60063
|
+
> should generate; it will open a PR with the ones you pick.
|
|
60064
|
+
|
|
60065
|
+
Do not attempt to generate or commit the docs yourself.
|
|
60066
|
+
|
|
60067
|
+
## Example \`.dosu/audit.json\`
|
|
60068
|
+
|
|
60069
|
+
\`\`\`json
|
|
60070
|
+
{
|
|
60071
|
+
"version": 1,
|
|
60072
|
+
"generated_at": "2026-06-24T12:00:00Z",
|
|
60073
|
+
"repo": { "remote": "git@github.com:acme/widget.git", "slug": "acme/widget" },
|
|
60074
|
+
"items": [
|
|
60075
|
+
{
|
|
60076
|
+
"task": "generate-agents-md", "type": "agents", "file": "AGENTS.md",
|
|
60077
|
+
"status": "missing", "action": "create", "can_help": true, "confidence": "high",
|
|
60078
|
+
"rationale": "No AGENTS.md; repo has documented \`pnpm test\`/\`pnpm build\` scripts and a clear packages/ layout worth capturing for agents.",
|
|
60079
|
+
"evidence": ["package.json", "packages/", "CONTRIBUTING.md"]
|
|
60080
|
+
},
|
|
60081
|
+
{
|
|
60082
|
+
"task": "refresh-readme", "type": "readme", "file": "README.md",
|
|
60083
|
+
"status": "outdated", "action": "update", "can_help": true, "confidence": "medium",
|
|
60084
|
+
"rationale": "README's Getting Started references a \`make bootstrap\` target that no longer exists; setup now uses \`pnpm install\`.",
|
|
60085
|
+
"evidence": ["README.md:24", "Makefile", "package.json"]
|
|
60086
|
+
},
|
|
60087
|
+
{
|
|
60088
|
+
"task": "generate-architecture-md", "type": "architecture", "file": "architecture.md",
|
|
60089
|
+
"status": "missing", "action": "skip", "can_help": false, "confidence": "high",
|
|
60090
|
+
"rationale": "Single-package repo with one entry point; not enough structure to justify a separate architecture doc yet.",
|
|
60091
|
+
"evidence": ["src/index.ts"]
|
|
60092
|
+
},
|
|
60093
|
+
{
|
|
60094
|
+
"task": "generate-deps-md", "type": "deps", "file": "deps.md",
|
|
60095
|
+
"status": "missing", "action": "create", "can_help": true, "confidence": "medium",
|
|
60096
|
+
"rationale": "No deps doc; package.json has ~30 runtime deps across HTTP, DB, and queue concerns worth summarizing.",
|
|
60097
|
+
"evidence": ["package.json", "pnpm-lock.yaml"]
|
|
60098
|
+
}
|
|
60099
|
+
]
|
|
59807
60100
|
}
|
|
59808
|
-
|
|
60101
|
+
\`\`\`
|
|
60102
|
+
`,
|
|
60103
|
+
executable: false
|
|
60104
|
+
},
|
|
60105
|
+
{
|
|
60106
|
+
path: "references/commands.md",
|
|
60107
|
+
content: `# Dosu CLI command reference
|
|
60108
|
+
|
|
60109
|
+
This file is the detailed source for the current command surface. Optional flags are in brackets. Only commands showing \`--json\` support structured JSON. Run the nested \`--help\` if the installed CLI differs.
|
|
60110
|
+
|
|
60111
|
+
## Authentication and setup
|
|
60112
|
+
|
|
60113
|
+
\`\`\`text
|
|
60114
|
+
dosu login [--request | --check <ticket>] [--json] [--no-browser]
|
|
60115
|
+
dosu logout
|
|
60116
|
+
dosu status [--json]
|
|
60117
|
+
dosu setup [--deployment <id>] [--mode <oss|cloud>] [--agent --tool <id>]
|
|
60118
|
+
[--login-ticket <ticket>]
|
|
60119
|
+
\`\`\`
|
|
60120
|
+
|
|
60121
|
+
- \`--request\` and \`--check\` are mutually exclusive login modes.
|
|
60122
|
+
- \`setup --agent\` requires \`--tool\`, emits NDJSON, and exits instead of waiting for a browser callback.
|
|
60123
|
+
|
|
60124
|
+
## Libraries
|
|
60125
|
+
|
|
60126
|
+
\`\`\`text
|
|
60127
|
+
dosu libraries list [--json]
|
|
60128
|
+
dosu libraries info <library-id> [--json]
|
|
60129
|
+
dosu libraries create --name <name> [--visibility public|internal|private] [--json]
|
|
60130
|
+
dosu libraries update <library-id> [--name <name>]
|
|
60131
|
+
[--visibility public|internal|private] [--confirm] [--json]
|
|
60132
|
+
dosu libraries delete <library-id> [--confirm] [--json]
|
|
60133
|
+
\`\`\`
|
|
60134
|
+
|
|
60135
|
+
- Library and source IDs in this section must be UUID v4. Names are nonempty and at most 50 characters. Omitted visibility uses the App default, \`internal\`. \`update\` requires at least one changed field.
|
|
60136
|
+
- \`update\` and \`delete\` prompt only in an interactive non-JSON terminal; agents pass \`--confirm\` after authorization.
|
|
60137
|
+
- The last Library in an organization cannot be deleted. A successful delete hides it immediately; child-data cleanup continues asynchronously.
|
|
60138
|
+
|
|
60139
|
+
### Library documentation config
|
|
60140
|
+
|
|
60141
|
+
\`\`\`text
|
|
60142
|
+
dosu libraries config get <library-id> [--json]
|
|
60143
|
+
dosu libraries config set <library-id> <setting> --value <json> [--confirm] [--json]
|
|
60144
|
+
\`\`\`
|
|
60145
|
+
|
|
60146
|
+
Settings and values:
|
|
60147
|
+
|
|
60148
|
+
| Setting | JSON value |
|
|
60149
|
+
|---|---|
|
|
60150
|
+
| \`commit_to_trigger_pr\` | boolean |
|
|
60151
|
+
| \`default_accept_review\` | boolean |
|
|
60152
|
+
| \`default_save_publish\` | boolean |
|
|
60153
|
+
| \`review_timeout_days\` | \`7\`, \`14\`, \`30\`, or \`90\` |
|
|
60154
|
+
|
|
60155
|
+
\`set\` reads the current version immediately before writing and sends that version with the mutation.
|
|
60156
|
+
|
|
60157
|
+
### Library sources
|
|
60158
|
+
|
|
60159
|
+
\`\`\`text
|
|
60160
|
+
dosu libraries sources list <library-id> [--json]
|
|
60161
|
+
dosu libraries sources attach <library-id> <source-id...> [--confirm] [--json]
|
|
60162
|
+
dosu libraries sources detach <library-id> <source-id...> [--confirm] [--json]
|
|
60163
|
+
|
|
60164
|
+
dosu libraries sources config get <library-id> <source-id> [--json]
|
|
60165
|
+
dosu libraries sources config update <library-id> <source-id>
|
|
60166
|
+
[--issues on|off] [--pull-requests on|off] [--discussions on|off] [--wiki on|off]
|
|
60167
|
+
[--include-patterns <json-string-array>] [--exclude-patterns <json-string-array>]
|
|
60168
|
+
[--confirm] [--json]
|
|
60169
|
+
\`\`\`
|
|
60170
|
+
|
|
60171
|
+
- \`attach\` and \`detach\` require one or more UUID source IDs. Repeated IDs are deduplicated.
|
|
60172
|
+
- Detaching archives pages that source synced into this Library; copies in other Libraries are unaffected.
|
|
60173
|
+
- Source config requires at least one option. GitHub accepts every option above; GitLab accepts only include/exclude patterns. The App resolves the provider.
|
|
60174
|
+
- Pattern options replace the list. Use \`[]\` to clear it.
|
|
60175
|
+
|
|
60176
|
+
### Library Monitor
|
|
60177
|
+
|
|
60178
|
+
\`\`\`text
|
|
60179
|
+
dosu libraries monitors list <library-id> [--json]
|
|
60180
|
+
dosu libraries monitors update <library-id> <source-id>
|
|
60181
|
+
[--enabled on|off] [--paths <json-string-array>]
|
|
60182
|
+
[--up-to-date-behavior emoji|comment|silent] [--confirm] [--json]
|
|
60183
|
+
\`\`\`
|
|
60184
|
+
|
|
60185
|
+
\`update\` requires at least one option. Monitor supports GitHub, GitLab, and Azure DevOps. It performs first-time setup for an attached supported source, reusing existing deployment infrastructure when available. When no Monitor row exists, omitted \`--enabled\`, paths, and behavior default to \`true\`, \`[]\`, and \`emoji\`.
|
|
60186
|
+
|
|
60187
|
+
## Agents
|
|
60188
|
+
|
|
60189
|
+
\`\`\`text
|
|
60190
|
+
dosu agents list [--json]
|
|
60191
|
+
dosu agents info <agent-id> [--json]
|
|
60192
|
+
dosu agents create --library <library-id> --source <source-id>
|
|
60193
|
+
[--name <name>] [--guidelines <text>] [--json]
|
|
60194
|
+
dosu agents update <agent-id> [--name <name>] [--enabled on|off]
|
|
60195
|
+
[--guidelines <text> | --clear-guidelines] [--confirm] [--json]
|
|
60196
|
+
dosu agents delete <agent-id> [--confirm] [--json]
|
|
60197
|
+
dosu agents move <agent-id> --library <library-id> [--confirm] [--json]
|
|
60198
|
+
|
|
60199
|
+
dosu agents config get <agent-id> [--json]
|
|
60200
|
+
dosu agents config set <agent-id> <existing.leaf.path>
|
|
60201
|
+
--value <json> [--confirm] [--json]
|
|
60202
|
+
\`\`\`
|
|
60203
|
+
|
|
60204
|
+
- Agent, Library, and source IDs in this section must be UUID v4. \`create\` accepts an existing GitHub, GitLab, Slack, or Teams source. The App supplies provider defaults, enables the Agent, and starts Mention-only reply behavior. Omitted name uses the source name.
|
|
60205
|
+
- Agent names are at most 80 characters; guidelines are at most 20,000 characters.
|
|
60206
|
+
- \`update\` requires at least one option. \`--guidelines\` conflicts with \`--clear-guidelines\`.
|
|
60207
|
+
- Config \`set\` changes one existing non-object leaf. Read the config first to select a valid path and value type.
|
|
60208
|
+
- \`move\` replaces the Agent's Library and returns the updated Agent. It does not report any historical-data migration.
|
|
60209
|
+
|
|
60210
|
+
## Knowledge and documents
|
|
60211
|
+
|
|
60212
|
+
\`\`\`text
|
|
60213
|
+
dosu ask <question> [--session <id>] [--timeout <seconds>] [--json]
|
|
60214
|
+
dosu knowledge search <query> [--limit <positive-int>] [--json] # default 10
|
|
60215
|
+
dosu knowledge list [--json]
|
|
60216
|
+
|
|
60217
|
+
dosu docs list [--search <query>] [--topic <id>] [--limit <positive-int>] [--json]
|
|
60218
|
+
dosu docs get <id> [--revision <positive-int>] [--json]
|
|
60219
|
+
dosu docs create --title <title> [--body <markdown> | --body-file <path>] [--json]
|
|
60220
|
+
dosu docs update <id> [--title <title>] [--body <markdown> | --body-file <path>] [--json]
|
|
60221
|
+
dosu docs archive <id> [--json]
|
|
60222
|
+
dosu docs unarchive <id> [--json]
|
|
60223
|
+
dosu docs delete <id> [--json]
|
|
60224
|
+
dosu docs versions <id> [--json]
|
|
60225
|
+
dosu docs restore <id> --revision <positive-int> [--json]
|
|
60226
|
+
dosu docs generate --title <title> [--instructions <text>] [--json]
|
|
60227
|
+
dosu docs auto-tag <id> [--json]
|
|
60228
|
+
dosu docs import <platform> --files <comma-separated-ids> [--json]
|
|
60229
|
+
dosu docs import-status <task-id> [--json]
|
|
60230
|
+
dosu docs publish <id> --to <platform> [target flags] [--json]
|
|
60231
|
+
dosu docs sync-back <id> [--json]
|
|
60232
|
+
\`\`\`
|
|
60233
|
+
|
|
60234
|
+
- Document list defaults to 20. \`create\` and \`update\` reject combining \`--body\` with \`--body-file\`; \`update\` requires at least one field.
|
|
60235
|
+
- Import platforms: \`github\`, \`gitlab\`, \`azure_devops\`, \`confluence\`, \`notion\`, \`coda\`.
|
|
60236
|
+
- Publish platforms: the same six. Target flags are \`--repo-id\`, \`--project-id\`, \`--parent-page-id\`, \`--doc-id\`, \`--directory\`, and \`--data-source-id\`; Azure DevOps requires \`--data-source-id\`. Other target validation may occur in the backend.
|
|
60237
|
+
- \`generate\`, \`auto-tag\`, import, publish, and sync operations may be asynchronous. Use the returned task/status identifiers rather than assuming completion.
|
|
60238
|
+
|
|
60239
|
+
## Review
|
|
60240
|
+
|
|
60241
|
+
Read [review-workflow.md](review-workflow.md) before mutating a review item.
|
|
60242
|
+
|
|
60243
|
+
\`\`\`text
|
|
60244
|
+
dosu review list [--json]
|
|
60245
|
+
dosu review diff <id> [--json]
|
|
60246
|
+
dosu review edit <id> [--title <title>] [--body <markdown> | --body-file <path>] [--json]
|
|
60247
|
+
dosu review context <thread-id> [--json]
|
|
60248
|
+
dosu review approve <id> [--confirm] [--json]
|
|
60249
|
+
dosu review reject <id> [--confirm] [--json]
|
|
60250
|
+
dosu review revert <id> [--json]
|
|
60251
|
+
\`\`\`
|
|
60252
|
+
|
|
60253
|
+
\`edit\` requires at least one field. \`approve\` and \`reject\` do not write without interactive confirmation or \`--confirm\`.
|
|
60254
|
+
|
|
60255
|
+
## Sources, integrations, members, and organization
|
|
60256
|
+
|
|
60257
|
+
\`\`\`text
|
|
60258
|
+
dosu sources list [--json]
|
|
60259
|
+
dosu sources info <id> [--json]
|
|
60260
|
+
dosu sources sync <id> [--json]
|
|
60261
|
+
dosu sources update <id> [--name <name>] [--description <text>] [--json]
|
|
60262
|
+
dosu sources delete <id> [--json]
|
|
60263
|
+
dosu sources connect [github] [--json] [--timeout <seconds>] [--no-open]
|
|
60264
|
+
dosu sources create github --repo <owner/name> [--library <id>] [--confirm] [--json]
|
|
60265
|
+
|
|
60266
|
+
dosu integrations list [--json]
|
|
60267
|
+
dosu integrations status <platform> [--json]
|
|
60268
|
+
dosu integrations slack-channels [--json]
|
|
60269
|
+
dosu integrations slack-join <channel-id> [--json]
|
|
60270
|
+
dosu integrations github-collaborators <positive-repository-id> [--json]
|
|
60271
|
+
|
|
60272
|
+
dosu members invite <email> [--role admin|member] [--json] # default member
|
|
60273
|
+
dosu org info [--json]
|
|
60274
|
+
\`\`\`
|
|
60275
|
+
|
|
60276
|
+
- \`sources update\` requires \`--name\` or \`--description\`.
|
|
60277
|
+
- \`sources connect\` currently supports only \`github\`: it prints an install URL for the user to
|
|
60278
|
+
open, then waits for the GitHub App install to complete (default 600s). With \`--json\` it emits
|
|
60279
|
+
NDJSON events — \`awaiting_install\` (give the \`url\` to the user), then \`installed\` with
|
|
60280
|
+
\`new_repositories\`, or \`timeout\` (exit 1). Other providers exit 1 with a web-app handoff URL.
|
|
60281
|
+
- \`sources create\` wires an installed GitHub repo into a Library: it creates (or reuses) the
|
|
60282
|
+
repo's data source + deployment, attaches it, and verifies the first sync. \`--library\` defaults
|
|
60283
|
+
to the active Library. A repo not listed means the GitHub App lacks access — run
|
|
60284
|
+
\`sources connect github\` first. Forks can't be connected.
|
|
60285
|
+
- Integration status choices: \`github\`, \`gitlab\`, \`azure_devops\`, \`slack\`, \`confluence\`, \`notion\`, \`coda\`, \`teams\`. GitHub, Slack, and Teams currently return \`connected: null\` because CLI status probing is unavailable for them.
|
|
60286
|
+
- The CLI has no member list/remove/request commands; \`members invite\` is its only member operation.
|
|
60287
|
+
|
|
60288
|
+
## Threads, Topics, suggestions, and analytics
|
|
60289
|
+
|
|
60290
|
+
\`\`\`text
|
|
60291
|
+
dosu threads list [--status pending|resolved|archived] [--search <query>]
|
|
60292
|
+
[--limit <1..100>] [--json] # default 20
|
|
60293
|
+
dosu threads get <id> [--limit <-1|positive-int>] [--json] # default 20
|
|
60294
|
+
dosu threads archive <id> [--json]
|
|
60295
|
+
|
|
60296
|
+
dosu topics list [--json]
|
|
60297
|
+
dosu topics pages <topic-id> [--search <query>] [--limit <positive-int>] [--json]
|
|
60298
|
+
|
|
60299
|
+
dosu suggest list [--json]
|
|
60300
|
+
dosu suggest generate [--json]
|
|
60301
|
+
dosu suggest reject <id> [--json]
|
|
60302
|
+
|
|
60303
|
+
dosu analytics [--days <positive-int>] [--json] # default 30
|
|
60304
|
+
\`\`\`
|
|
60305
|
+
|
|
60306
|
+
Topics are read-only. The CLI has no \`tags\` command and no suggestion-accept command.
|
|
60307
|
+
|
|
60308
|
+
## MCP deployments and local utilities
|
|
60309
|
+
|
|
60310
|
+
\`\`\`text
|
|
60311
|
+
dosu deployments list [--json]
|
|
60312
|
+
dosu deployments info [--json]
|
|
60313
|
+
dosu deployments switch <id> [--json]
|
|
60314
|
+
|
|
60315
|
+
dosu mcp list
|
|
60316
|
+
dosu mcp add <agent> [--global] [--show-secret]
|
|
60317
|
+
dosu skill install | remove | update
|
|
60318
|
+
dosu telemetry status [--json]
|
|
60319
|
+
dosu telemetry enable | disable | reset
|
|
60320
|
+
dosu insights
|
|
60321
|
+
dosu upgrade
|
|
60322
|
+
dosu logs [--tail [n]] [--clear]
|
|
60323
|
+
\`\`\`
|
|
60324
|
+
|
|
60325
|
+
\`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file.
|
|
60326
|
+
|
|
60327
|
+
## Codebase audit
|
|
60328
|
+
|
|
60329
|
+
\`\`\`text
|
|
60330
|
+
dosu audit [--findings <path>] [--data-source-id <id>]
|
|
60331
|
+
[--tasks <comma-separated-task-ids> | --yes] [--list-tasks] [--json]
|
|
60332
|
+
\`\`\`
|
|
60333
|
+
|
|
60334
|
+
The coding agent writes the findings; Dosu generates the selected docs. Follow [audit.md](audit.md) and [audit-findings-schema.md](audit-findings-schema.md).
|
|
60335
|
+
`,
|
|
60336
|
+
executable: false
|
|
60337
|
+
},
|
|
60338
|
+
{
|
|
60339
|
+
path: "references/review-workflow.md",
|
|
60340
|
+
content: `# Review workflow
|
|
60341
|
+
|
|
60342
|
+
How to work Dosu's review queue from the CLI: triage pending items, read the
|
|
60343
|
+
diff, optionally edit, and apply a decision — safely.
|
|
60344
|
+
|
|
60345
|
+
The queue holds **document versions** (AI-generated, user-edited, synced from
|
|
60346
|
+
source, or API-created) and **draft messages**, all surfaced through the same
|
|
60347
|
+
\`dosu review\` commands. Items are keyed on a single \`page-version-id\` so
|
|
60348
|
+
\`list\` → \`diff\` → \`edit\` → \`approve\`/\`reject\` all share one ID.
|
|
60349
|
+
|
|
60350
|
+
> \`list\` returns only the most recent pending items (server-capped, currently
|
|
60351
|
+
> 50) and does not flag truncation. If the queue is large, don't assume \`list\`
|
|
60352
|
+
> shows everything.
|
|
60353
|
+
|
|
60354
|
+
## Scope tool access for a review session
|
|
60355
|
+
|
|
60356
|
+
Approving and rejecting are destructive and outward-facing. When you spin up an
|
|
60357
|
+
agent session dedicated to reviewing, scope it to just the review commands:
|
|
60358
|
+
|
|
60359
|
+
\`\`\`yaml
|
|
60360
|
+
allowed-tools: Bash(dosu review:*)
|
|
60361
|
+
\`\`\`
|
|
60362
|
+
|
|
60363
|
+
This lets the agent triage, diff, and edit, but keeps it from running unrelated
|
|
60364
|
+
CLI commands during a review pass.
|
|
60365
|
+
|
|
60366
|
+
## The flow
|
|
60367
|
+
|
|
60368
|
+
\`\`\`bash
|
|
60369
|
+
# 1. Triage — what's pending? Columns: ID, Kind, Title, Source, Status, Created.
|
|
60370
|
+
dosu review list --json
|
|
60371
|
+
|
|
60372
|
+
# 2. Inspect — read the exact change before deciding anything.
|
|
60373
|
+
dosu review diff <page-version-id> --json
|
|
60374
|
+
|
|
60375
|
+
# 3. (optional) Edit in place instead of rejecting a near-miss.
|
|
60376
|
+
dosu review edit <page-version-id> --body-file ./revised.md # or --body / --title
|
|
60377
|
+
|
|
60378
|
+
# 4. Decide — only on the item the user named, only after they OK it.
|
|
60379
|
+
dosu review approve <page-version-id> --confirm --json
|
|
60380
|
+
dosu review reject <page-version-id> --confirm --json
|
|
60381
|
+
|
|
60382
|
+
# Undo a decision — back to pending.
|
|
60383
|
+
dosu review revert <page-version-id> --json
|
|
60384
|
+
\`\`\`
|
|
60385
|
+
|
|
60386
|
+
### \`--confirm\` is mandatory for agents
|
|
60387
|
+
|
|
60388
|
+
\`approve\` and \`reject\` only prompt interactively in a TTY *without* \`--json\`.
|
|
60389
|
+
The skill always passes \`--json\`, which suppresses both the diff preview and
|
|
60390
|
+
the prompt — so without \`--confirm\` the command changes nothing and returns
|
|
60391
|
+
\`{ "applied": false, "confirmRequired": true }\`. Run \`dosu review diff <id>\` to
|
|
60392
|
+
see the change, then pass \`--confirm\` to apply — only after the user has
|
|
60393
|
+
approved that specific item.
|
|
60394
|
+
|
|
60395
|
+
## Reading the \`Source\` column
|
|
60396
|
+
|
|
60397
|
+
\`Source\` is the humanized \`origin\` field:
|
|
60398
|
+
|
|
60399
|
+
| \`origin\` | Source | Meaning |
|
|
60400
|
+
|---|---|---|
|
|
60401
|
+
| \`manual_update\` | User created / User updated | A teammate authored or edited the doc |
|
|
60402
|
+
| \`llm_generated\` | AI generated | Dosu drafted the change |
|
|
60403
|
+
| \`sync_upstream\` | Synced from source | Came in from a connected source (Notion/Confluence/GitHub) |
|
|
60404
|
+
| \`api_update\` | Created via API | Pushed in programmatically |
|
|
60405
|
+
|
|
60406
|
+
## Feeding PR / thread context
|
|
60407
|
+
|
|
60408
|
+
A review often originates from a conversation thread (a GitHub issue, a Slack
|
|
60409
|
+
message, a sync-back PR). Pull that context before deciding:
|
|
60410
|
+
|
|
60411
|
+
\`\`\`bash
|
|
60412
|
+
dosu review context <thread-id> --json
|
|
60413
|
+
\`\`\`
|
|
60414
|
+
|
|
60415
|
+
It returns the review \`type\`, the review/published page IDs, and — when the
|
|
60416
|
+
change round-trips to an external system — a **Sync PR URL**. Use it to:
|
|
60417
|
+
|
|
60418
|
+
- show the user where the change came from and where approval will land, and
|
|
60419
|
+
- read the originating discussion so the decision matches intent.
|
|
60420
|
+
|
|
60421
|
+
## Safety rules
|
|
60422
|
+
|
|
60423
|
+
- **Explicit item only.** Decide on the \`id\` the user named. "Review my queue"
|
|
60424
|
+
→ run \`list\` and show it; never decide on their behalf.
|
|
60425
|
+
- **Diff before deciding.** Always \`diff\` and surface the change first.
|
|
60426
|
+
- **Never batch-accept.** No loop over \`list\` that approves everything. One
|
|
60427
|
+
item, one confirmation.
|
|
60428
|
+
- **Extra care for sync/PR origins.** \`Synced from source\` items and anything
|
|
60429
|
+
with a Sync PR URL push back to an upstream system on approval. Call it out
|
|
60430
|
+
and get explicit sign-off.
|
|
60431
|
+
`,
|
|
60432
|
+
executable: false
|
|
60433
|
+
},
|
|
60434
|
+
{
|
|
60435
|
+
path: "references/workflows.md",
|
|
60436
|
+
content: `# Dosu CLI workflows
|
|
60437
|
+
|
|
60438
|
+
Use these patterns to compose commands. Replace placeholders with IDs read from JSON output; never guess them. See [commands.md](commands.md) for exact flags and choices.
|
|
60439
|
+
|
|
60440
|
+
## Configure Dosu for a coding agent
|
|
60441
|
+
|
|
60442
|
+
\`\`\`bash
|
|
60443
|
+
dosu setup --agent --tool <tool-id>
|
|
60444
|
+
\`\`\`
|
|
60445
|
+
|
|
60446
|
+
Read every NDJSON event:
|
|
60447
|
+
|
|
60448
|
+
1. On \`need_user_action\`, give the returned URL to the user and stop.
|
|
60449
|
+
2. After the user confirms sign-in, run the returned \`resume_command\` verbatim.
|
|
60450
|
+
3. On \`pending\`, wait for the user and repeat that command.
|
|
60451
|
+
4. On \`multiple_deployments\`, list MCP deployments, let the user choose, and retry with \`--deployment <id>\`.
|
|
60452
|
+
5. Treat \`done\` as setup completion, then verify with \`dosu status --json\`.
|
|
60453
|
+
|
|
60454
|
+
## Onboard from scratch (guided)
|
|
60455
|
+
|
|
60456
|
+
Use this flow when the user asks to "set up Dosu", "create a library and set it up", or any
|
|
60457
|
+
end-to-end onboarding. It is a conversation, not a script: never invent names, never auto-pick
|
|
60458
|
+
sources, and stop at every checkpoint below until the user answers. Run each mutation only after
|
|
60459
|
+
its checkpoint. One step per turn is better than one turn with every step.
|
|
60460
|
+
|
|
60461
|
+
**Step 0 — Discover (read-only, no confirmation needed).**
|
|
60462
|
+
|
|
60463
|
+
\`\`\`bash
|
|
60464
|
+
dosu status --json
|
|
60465
|
+
dosu sources list --json
|
|
60466
|
+
dosu libraries list --json
|
|
60467
|
+
\`\`\`
|
|
60468
|
+
|
|
60469
|
+
If not configured, run the "Configure Dosu for a coding agent" flow first.
|
|
60470
|
+
|
|
60471
|
+
**Checkpoint 1 — Scope.** Present a short summary of the connected sources (name + provider, not
|
|
60472
|
+
raw JSON) and any existing Libraries, then ask and wait:
|
|
60473
|
+
|
|
60474
|
+
1. Which source(s) should the new Library use? Existing ones, a new one, or both.
|
|
60475
|
+
2. What should the Library be called? Suggest a name derived from the chosen sources, but let the
|
|
60476
|
+
user decide.
|
|
60477
|
+
3. Visibility: default \`internal\`; mention \`private\`/\`public\` only if relevant (warn about the
|
|
60478
|
+
public-Library boundary from [SKILL.md](../SKILL.md)).
|
|
60479
|
+
4. For each chosen GitHub repository: Monitor will be enabled with defaults (whole repository,
|
|
60480
|
+
\`emoji\`) unless they opt out.
|
|
60481
|
+
|
|
60482
|
+
**Step 0.5 — Connect a new source (only when the user asked for one).** Ask which provider. For
|
|
60483
|
+
GitHub, run the CLI bridge — do not send the user hunting through the App:
|
|
60484
|
+
|
|
60485
|
+
\`\`\`bash
|
|
60486
|
+
dosu sources connect github --json
|
|
60487
|
+
\`\`\`
|
|
60488
|
+
|
|
60489
|
+
Give the user the \`url\` from the \`awaiting_install\` event and wait; the command completes on its
|
|
60490
|
+
own when the install finishes and reports \`new_repositories\`. For any other provider (Slack, web
|
|
60491
|
+
docs, Notion, Coda, Confluence, ...) the connect flow is web-only: give the user the App URL the
|
|
60492
|
+
command prints, wait for them to confirm, then re-run \`dosu sources list --json\` to pick up the
|
|
60493
|
+
new source.
|
|
60494
|
+
|
|
60495
|
+
**Step 1 — Create and attach (after the user answers).**
|
|
60496
|
+
|
|
60497
|
+
\`\`\`bash
|
|
60498
|
+
dosu libraries create --name "<user-approved name>" --json
|
|
60499
|
+
dosu libraries sources attach <library-id> <existing-source-ids...> --confirm --json
|
|
60500
|
+
dosu sources create github --repo <owner/name> --library <library-id> --confirm --json
|
|
60501
|
+
dosu libraries monitors update <library-id> <repository-source-id> --enabled on --confirm --json
|
|
60502
|
+
\`\`\`
|
|
60503
|
+
|
|
60504
|
+
Use \`libraries sources attach\` for sources that already exist; use \`sources create\` for a GitHub
|
|
60505
|
+
repo that became visible via \`sources connect\` but has no data source yet (it creates, attaches,
|
|
60506
|
+
and verifies the first sync in one receipt).
|
|
60507
|
+
|
|
60508
|
+
Report each receipt in one line as it lands (Library ID, sources attached, Monitor state).
|
|
60509
|
+
|
|
60510
|
+
**Checkpoint 2 — Agent (optional).** Ask whether the user wants an Agent (GitHub/GitLab/Slack/Teams
|
|
60511
|
+
responder) on one of the attached sources. Only on yes:
|
|
60512
|
+
|
|
60513
|
+
\`\`\`bash
|
|
60514
|
+
dosu agents create --library <library-id> --source <source-id> --name "<user-approved name>" --json
|
|
60515
|
+
\`\`\`
|
|
60516
|
+
|
|
60517
|
+
A \`CONFLICT\` (409) means that data source already has an Agent — one Agent per source. Report which
|
|
60518
|
+
source conflicted and offer the alternatives: pick a different source, or (only with explicit
|
|
60519
|
+
authorization) \`dosu agents move\` the existing Agent, which removes it from its current Library.
|
|
60520
|
+
|
|
60521
|
+
**Step 2 — Verify and hand off.**
|
|
60522
|
+
|
|
60523
|
+
\`\`\`bash
|
|
60524
|
+
dosu libraries info <library-id> --json
|
|
60525
|
+
dosu libraries sources list <library-id> --json
|
|
60526
|
+
dosu libraries monitors list <library-id> --json
|
|
60527
|
+
\`\`\`
|
|
60528
|
+
|
|
60529
|
+
Summarize the final state. Creating an MCP deployment for the new Library is not available in the
|
|
60530
|
+
CLI; if the user wants their MCP/CLI target pointed at this Library, send them to the App to create
|
|
60531
|
+
the MCP deployment, then run \`dosu deployments switch\`.
|
|
60532
|
+
|
|
60533
|
+
## Create a Library from existing sources
|
|
60534
|
+
|
|
60535
|
+
This works with any number or mix of organization sources.
|
|
60536
|
+
|
|
60537
|
+
\`\`\`bash
|
|
60538
|
+
# Discover connected sources and select exact IDs by provider/name.
|
|
60539
|
+
dosu sources list --json
|
|
60540
|
+
|
|
60541
|
+
# Create the Library; capture its id. Omitted visibility defaults to \`internal\`;
|
|
60542
|
+
# pass --visibility public|internal|private only when the user asks for it.
|
|
60543
|
+
dosu libraries create --name "Incident Response" --json
|
|
60544
|
+
|
|
60545
|
+
# The user's explicit request authorizes these exact attachments.
|
|
60546
|
+
dosu libraries sources attach <library-id> <repository-source-id> <handbook-source-id> \\
|
|
60547
|
+
--confirm --json
|
|
60548
|
+
|
|
60549
|
+
# Enable the default for each newly attached GitHub repository unless the user opted out.
|
|
60550
|
+
dosu libraries monitors update <library-id> <repository-source-id> \\
|
|
60551
|
+
--enabled on --confirm --json
|
|
60552
|
+
|
|
60553
|
+
# Verify the final state, not just mutation receipts.
|
|
60554
|
+
dosu libraries info <library-id> --json
|
|
60555
|
+
dosu libraries sources list <library-id> --json
|
|
60556
|
+
dosu libraries monitors list <library-id> --json
|
|
60557
|
+
\`\`\`
|
|
60558
|
+
|
|
60559
|
+
Apply the connection and public-Library safety boundaries from [SKILL.md](../SKILL.md) before attaching.
|
|
60560
|
+
|
|
60561
|
+
## Change an existing Library safely
|
|
60562
|
+
|
|
60563
|
+
\`\`\`bash
|
|
60564
|
+
dosu libraries list --json
|
|
60565
|
+
dosu libraries info <library-id> --json
|
|
60566
|
+
|
|
60567
|
+
# Rename or change visibility only after the exact target/change is authorized.
|
|
60568
|
+
dosu libraries update <library-id> --name "Operations Handbook" --confirm --json
|
|
60569
|
+
|
|
60570
|
+
# Read before changing one documentation setting.
|
|
60571
|
+
dosu libraries config get <library-id> --json
|
|
60572
|
+
dosu libraries config set <library-id> review_timeout_days --value 30 --confirm --json
|
|
60573
|
+
\`\`\`
|
|
60574
|
+
|
|
60575
|
+
## Create and configure an Agent
|
|
60576
|
+
|
|
60577
|
+
\`\`\`bash
|
|
60578
|
+
# Select a Library and an existing GitHub, GitLab, Slack, or Teams source.
|
|
60579
|
+
dosu libraries list --json
|
|
60580
|
+
dosu sources list --json
|
|
60581
|
+
|
|
60582
|
+
dosu agents create --library <library-id> --source <source-id> \\
|
|
60583
|
+
--name "Repository Helper" --json
|
|
60584
|
+
|
|
60585
|
+
dosu agents info <agent-id> --json
|
|
60586
|
+
dosu agents config get <agent-id> --json
|
|
60587
|
+
|
|
60588
|
+
# Change one leaf only after reading the current structure.
|
|
60589
|
+
dosu agents config set <agent-id> issues.auto_reply.review_required \\
|
|
60590
|
+
--value true --confirm --json
|
|
60591
|
+
\`\`\`
|
|
60592
|
+
|
|
60593
|
+
To move the Agent, confirm the destination and verify the returned \`space_id\`:
|
|
60594
|
+
|
|
60595
|
+
\`\`\`bash
|
|
60596
|
+
dosu agents move <agent-id> --library <destination-library-id> --confirm --json
|
|
60597
|
+
\`\`\`
|
|
60598
|
+
|
|
60599
|
+
## Configure a Library source and Monitor
|
|
60600
|
+
|
|
60601
|
+
\`\`\`bash
|
|
60602
|
+
dosu libraries sources config get <library-id> <source-id> --json
|
|
60603
|
+
dosu libraries sources config update <library-id> <source-id> \\
|
|
60604
|
+
--include-patterns '["docs/**","*.md"]' \\
|
|
60605
|
+
--exclude-patterns '["archive/**"]' --confirm --json
|
|
60606
|
+
|
|
60607
|
+
dosu libraries monitors list <library-id> --json
|
|
60608
|
+
dosu libraries monitors update <library-id> <source-id> \\
|
|
60609
|
+
--enabled on --paths '["docs/**"]' \\
|
|
60610
|
+
--up-to-date-behavior silent --confirm --json
|
|
60611
|
+
\`\`\`
|
|
60612
|
+
|
|
60613
|
+
## Find information and inspect its source
|
|
60614
|
+
|
|
60615
|
+
\`\`\`bash
|
|
60616
|
+
dosu ask "How is access control enforced?" --json
|
|
60617
|
+
dosu knowledge search "access control" --json
|
|
60618
|
+
dosu docs get <page-id> --json
|
|
60619
|
+
\`\`\`
|
|
60620
|
+
|
|
60621
|
+
Use \`ask\` for a synthesized answer. Use \`knowledge search\` and \`docs get\` when the user wants the underlying documents.
|
|
60622
|
+
|
|
60623
|
+
## Import external documents
|
|
60624
|
+
|
|
60625
|
+
\`\`\`bash
|
|
60626
|
+
dosu sources list --json
|
|
60627
|
+
dosu docs import <platform> --files <comma-separated-ids> --json
|
|
60628
|
+
dosu docs import-status <task-id> --json
|
|
60629
|
+
\`\`\`
|
|
60630
|
+
|
|
60631
|
+
Capture the returned task ID. Poll only when the user asked you to wait for completion.
|
|
60632
|
+
|
|
60633
|
+
## Review one pending item
|
|
60634
|
+
|
|
60635
|
+
\`\`\`bash
|
|
60636
|
+
dosu review list --json
|
|
60637
|
+
dosu review diff <item-id> --json
|
|
60638
|
+
dosu review approve <item-id> --confirm --json
|
|
60639
|
+
\`\`\`
|
|
60640
|
+
|
|
60641
|
+
Use \`reject\` instead of \`approve\` only for the same explicitly authorized item. Follow [review-workflow.md](review-workflow.md) for edits, draft replies, upstream sync, and rollback.
|
|
60642
|
+
|
|
60643
|
+
## Audit repository documentation
|
|
60644
|
+
|
|
60645
|
+
Follow [audit.md](audit.md) to inspect the repository and write \`.dosu/audit.json\`, then invoke only the task IDs the user chooses:
|
|
60646
|
+
|
|
60647
|
+
\`\`\`bash
|
|
60648
|
+
dosu audit --tasks <comma-separated-task-ids> --json
|
|
60649
|
+
\`\`\`
|
|
60650
|
+
|
|
60651
|
+
The coding agent performs triage; Dosu cloud generates docs and opens the PR.
|
|
60652
|
+
`,
|
|
60653
|
+
executable: false
|
|
60654
|
+
}
|
|
60655
|
+
]
|
|
60656
|
+
}
|
|
60657
|
+
];
|
|
60658
|
+
});
|
|
60659
|
+
|
|
60660
|
+
// src/commands/skill.ts
|
|
60661
|
+
import {
|
|
60662
|
+
cpSync,
|
|
60663
|
+
existsSync as existsSync19,
|
|
60664
|
+
lstatSync as lstatSync2,
|
|
60665
|
+
mkdirSync as mkdirSync11,
|
|
60666
|
+
readFileSync as readFileSync19,
|
|
60667
|
+
rmSync as rmSync5,
|
|
60668
|
+
symlinkSync,
|
|
60669
|
+
writeFileSync as writeFileSync12
|
|
60670
|
+
} from "node:fs";
|
|
60671
|
+
import { homedir as homedir8 } from "node:os";
|
|
60672
|
+
import { dirname as dirname10, join as join22, relative as relative3 } from "node:path";
|
|
60673
|
+
function skillAgentIDsForProviders(providerIDs) {
|
|
60674
|
+
return [
|
|
60675
|
+
...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
|
|
60676
|
+
];
|
|
60677
|
+
}
|
|
60678
|
+
function isSkillAgentID(agent) {
|
|
60679
|
+
return SUPPORTED_SKILL_AGENTS.includes(agent);
|
|
60680
|
+
}
|
|
60681
|
+
function universalSkillsDir() {
|
|
60682
|
+
return join22(homedir8(), ".agents", "skills");
|
|
60683
|
+
}
|
|
60684
|
+
function linkedSkillsDir(agent) {
|
|
60685
|
+
if (agent === "claude-code") {
|
|
60686
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join22(homedir8(), ".claude");
|
|
60687
|
+
return join22(claudeConfigDir, "skills");
|
|
60688
|
+
}
|
|
60689
|
+
if (agent === "windsurf")
|
|
60690
|
+
return join22(homedir8(), ".codeium", "windsurf", "skills");
|
|
60691
|
+
return null;
|
|
60692
|
+
}
|
|
60693
|
+
function skillInstallTargetForProvider(providerID) {
|
|
60694
|
+
const agentID = SKILL_AGENT_BY_PROVIDER[providerID];
|
|
60695
|
+
if (!agentID)
|
|
60696
|
+
return null;
|
|
60697
|
+
const linked = linkedSkillsDir(agentID);
|
|
60698
|
+
if (linked)
|
|
60699
|
+
return { path: join22(linked, SKILL_NAME), symlink: true };
|
|
60700
|
+
return { path: join22(universalSkillsDir(), SKILL_NAME), symlink: false };
|
|
60701
|
+
}
|
|
60702
|
+
function installStatePath() {
|
|
60703
|
+
return join22(getConfigDir(), INSTALL_STATE_FILENAME);
|
|
60704
|
+
}
|
|
60705
|
+
function readSkillInstallState() {
|
|
59809
60706
|
try {
|
|
59810
|
-
const path =
|
|
60707
|
+
const path = installStatePath();
|
|
59811
60708
|
if (!existsSync19(path))
|
|
59812
60709
|
return null;
|
|
59813
60710
|
const data = JSON.parse(readFileSync19(path, "utf-8"));
|
|
59814
|
-
if (typeof data
|
|
59815
|
-
return data;
|
|
60711
|
+
if (typeof data?.version === "string" && Array.isArray(data.agents) && data.agents.every((agent) => typeof agent === "string") && typeof data.installedAt === "number") {
|
|
60712
|
+
return { version: data.version, agents: data.agents, installedAt: data.installedAt };
|
|
59816
60713
|
}
|
|
59817
60714
|
return null;
|
|
59818
60715
|
} catch {
|
|
59819
60716
|
return null;
|
|
59820
60717
|
}
|
|
59821
60718
|
}
|
|
59822
|
-
function
|
|
60719
|
+
function writeSkillInstallState(state) {
|
|
59823
60720
|
try {
|
|
59824
60721
|
const dir = getConfigDir();
|
|
59825
|
-
if (!existsSync19(dir))
|
|
60722
|
+
if (!existsSync19(dir))
|
|
59826
60723
|
mkdirSync11(dir, { recursive: true, mode: 448 });
|
|
59827
|
-
}
|
|
59828
|
-
|
|
59829
|
-
|
|
59830
|
-
}
|
|
59831
|
-
function clearInstalledSha() {
|
|
59832
|
-
const cache = readSkillCache();
|
|
59833
|
-
if (cache)
|
|
59834
|
-
writeSkillCache({ ...cache, installedSha: "" });
|
|
59835
|
-
}
|
|
59836
|
-
async function fetchLatestSha() {
|
|
59837
|
-
const controller = new AbortController;
|
|
59838
|
-
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
59839
|
-
try {
|
|
59840
|
-
const resp = await fetch(GITHUB_API_URL, {
|
|
59841
|
-
signal: controller.signal,
|
|
59842
|
-
headers: {
|
|
59843
|
-
"User-Agent": `dosu-cli/${VERSION}`,
|
|
59844
|
-
Accept: "application/vnd.github+json"
|
|
59845
|
-
}
|
|
59846
|
-
});
|
|
59847
|
-
if (!resp.ok)
|
|
59848
|
-
return null;
|
|
59849
|
-
const data = await resp.json();
|
|
59850
|
-
const sha = data.sha;
|
|
59851
|
-
return typeof sha === "string" ? sha : null;
|
|
59852
|
-
} catch {
|
|
59853
|
-
return null;
|
|
59854
|
-
} finally {
|
|
59855
|
-
clearTimeout(timeout);
|
|
60724
|
+
writeFileSync12(installStatePath(), JSON.stringify(state), { mode: 384 });
|
|
60725
|
+
} catch (err) {
|
|
60726
|
+
logger.debug("skill", `Could not record skill install state: ${err}`);
|
|
59856
60727
|
}
|
|
59857
60728
|
}
|
|
59858
|
-
function
|
|
59859
|
-
|
|
59860
|
-
${import_picocolors26.default.yellow(" Dosu skill update available")}
|
|
59861
|
-
` + `${import_picocolors26.default.dim(' Run "dosu skill update" to upgrade')}
|
|
59862
|
-
`;
|
|
59863
|
-
console.error(msg);
|
|
60729
|
+
function clearSkillInstallState() {
|
|
60730
|
+
rmSync5(installStatePath(), { force: true });
|
|
59864
60731
|
}
|
|
59865
|
-
function
|
|
60732
|
+
function pruneLegacySkillLock() {
|
|
60733
|
+
const lockPath = join22(homedir8(), ".agents", ".skill-lock.json");
|
|
59866
60734
|
try {
|
|
59867
|
-
|
|
59868
|
-
|
|
59869
|
-
|
|
59870
|
-
|
|
59871
|
-
|
|
59872
|
-
|
|
59873
|
-
|
|
59874
|
-
|
|
59875
|
-
|
|
59876
|
-
|
|
59877
|
-
|
|
59878
|
-
|
|
59879
|
-
|
|
59880
|
-
|
|
59881
|
-
|
|
59882
|
-
}
|
|
59883
|
-
}).catch((err) => {
|
|
59884
|
-
logger.error("skill-update-check", `Background fetch failed: ${err}`);
|
|
59885
|
-
});
|
|
59886
|
-
}
|
|
60735
|
+
if (!existsSync19(lockPath))
|
|
60736
|
+
return [];
|
|
60737
|
+
const lock = JSON.parse(readFileSync19(lockPath, "utf-8"));
|
|
60738
|
+
const skills = lock?.skills;
|
|
60739
|
+
if (!skills || typeof skills !== "object")
|
|
60740
|
+
return [];
|
|
60741
|
+
const legacy = Object.entries(skills).filter(([, entry]) => entry?.source === LEGACY_SKILL_SOURCE).map(([name]) => name);
|
|
60742
|
+
if (legacy.length === 0)
|
|
60743
|
+
return [];
|
|
60744
|
+
for (const name of legacy)
|
|
60745
|
+
delete skills[name];
|
|
60746
|
+
writeFileSync12(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
60747
|
+
`);
|
|
60748
|
+
logger.debug("skill", `Removed legacy lock entries: ${legacy.join(", ")}`);
|
|
60749
|
+
return legacy;
|
|
59887
60750
|
} catch (err) {
|
|
59888
|
-
logger.
|
|
60751
|
+
logger.debug("skill", `Could not read legacy skill lock: ${err}`);
|
|
60752
|
+
return [];
|
|
59889
60753
|
}
|
|
59890
60754
|
}
|
|
59891
|
-
|
|
59892
|
-
|
|
59893
|
-
|
|
59894
|
-
|
|
59895
|
-
|
|
59896
|
-
|
|
59897
|
-
});
|
|
59898
|
-
|
|
59899
|
-
// src/commands/skill.ts
|
|
59900
|
-
import { exec as exec2, execSync as execSync2 } from "node:child_process";
|
|
59901
|
-
import { homedir as homedir8 } from "node:os";
|
|
59902
|
-
import { join as join23 } from "node:path";
|
|
59903
|
-
function skillAgentIDsForProviders(providerIDs) {
|
|
59904
|
-
return [
|
|
59905
|
-
...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
|
|
59906
|
-
];
|
|
59907
|
-
}
|
|
59908
|
-
function skillInstallTargetForProvider(providerID) {
|
|
59909
|
-
const agentID = SKILL_AGENT_BY_PROVIDER[providerID];
|
|
59910
|
-
if (!agentID)
|
|
59911
|
-
return null;
|
|
59912
|
-
if (agentID === "claude-code") {
|
|
59913
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join23(homedir8(), ".claude");
|
|
59914
|
-
return { path: join23(claudeConfigDir, "skills", SKILL_NAME), symlink: true };
|
|
60755
|
+
function pathExists(path) {
|
|
60756
|
+
try {
|
|
60757
|
+
lstatSync2(path);
|
|
60758
|
+
return true;
|
|
60759
|
+
} catch {
|
|
60760
|
+
return false;
|
|
59915
60761
|
}
|
|
59916
|
-
|
|
59917
|
-
|
|
59918
|
-
|
|
59919
|
-
|
|
59920
|
-
|
|
60762
|
+
}
|
|
60763
|
+
function writeSkillDir(skill, dir) {
|
|
60764
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
60765
|
+
for (const file of skill.files) {
|
|
60766
|
+
const target = join22(dir, ...file.path.split("/"));
|
|
60767
|
+
mkdirSync11(dirname10(target), { recursive: true });
|
|
60768
|
+
writeFileSync12(target, file.content, { mode: file.executable ? 493 : 420 });
|
|
59921
60769
|
}
|
|
59922
|
-
return {
|
|
59923
|
-
path: join23(homedir8(), ".agents", "skills", SKILL_NAME),
|
|
59924
|
-
symlink: false
|
|
59925
|
-
};
|
|
59926
60770
|
}
|
|
59927
|
-
function
|
|
59928
|
-
|
|
59929
|
-
|
|
60771
|
+
function linkSkillDir(linkPath, targetDir) {
|
|
60772
|
+
mkdirSync11(dirname10(linkPath), { recursive: true });
|
|
60773
|
+
rmSync5(linkPath, { recursive: true, force: true });
|
|
60774
|
+
try {
|
|
60775
|
+
symlinkSync(relative3(dirname10(linkPath), targetDir), linkPath, "dir");
|
|
60776
|
+
return "symlink";
|
|
60777
|
+
} catch (err) {
|
|
60778
|
+
logger.debug("skill", `Symlink failed for ${linkPath}, copying instead: ${err}`);
|
|
60779
|
+
cpSync(targetDir, linkPath, { recursive: true });
|
|
60780
|
+
return "copy";
|
|
60781
|
+
}
|
|
59930
60782
|
}
|
|
59931
|
-
function
|
|
59932
|
-
|
|
59933
|
-
|
|
59934
|
-
|
|
59935
|
-
|
|
59936
|
-
else
|
|
59937
|
-
resolve();
|
|
59938
|
-
});
|
|
59939
|
-
});
|
|
60783
|
+
function removeSkillDir(dir) {
|
|
60784
|
+
if (!pathExists(dir))
|
|
60785
|
+
return false;
|
|
60786
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
60787
|
+
return true;
|
|
59940
60788
|
}
|
|
59941
|
-
|
|
59942
|
-
const
|
|
59943
|
-
if (
|
|
59944
|
-
logger.debug("skill", "No selected
|
|
60789
|
+
function installBundledSkills(agentIDs) {
|
|
60790
|
+
const agents = agentIDs.filter(isSkillAgentID);
|
|
60791
|
+
if (agents.length === 0) {
|
|
60792
|
+
logger.debug("skill", "No selected agents support the Dosu skill");
|
|
59945
60793
|
return { success: true };
|
|
59946
60794
|
}
|
|
59947
60795
|
try {
|
|
59948
|
-
const
|
|
59949
|
-
|
|
59950
|
-
|
|
59951
|
-
|
|
59952
|
-
|
|
60796
|
+
const legacy = pruneLegacySkillLock();
|
|
60797
|
+
const bundledNames = new Set(BUNDLED_SKILLS.map((skill) => skill.name));
|
|
60798
|
+
const linkDirs = [
|
|
60799
|
+
...new Set(agents.map(linkedSkillsDir).filter((dir) => !!dir))
|
|
60800
|
+
];
|
|
60801
|
+
for (const name of legacy) {
|
|
60802
|
+
if (bundledNames.has(name))
|
|
60803
|
+
continue;
|
|
60804
|
+
for (const dir of [universalSkillsDir(), ...linkDirs])
|
|
60805
|
+
removeSkillDir(join22(dir, name));
|
|
60806
|
+
}
|
|
60807
|
+
const paths = [];
|
|
60808
|
+
for (const skill of BUNDLED_SKILLS) {
|
|
60809
|
+
const universal = join22(universalSkillsDir(), skill.name);
|
|
60810
|
+
writeSkillDir(skill, universal);
|
|
60811
|
+
paths.push(universal);
|
|
60812
|
+
for (const dir of linkDirs) {
|
|
60813
|
+
const linkPath = join22(dir, skill.name);
|
|
60814
|
+
linkSkillDir(linkPath, universal);
|
|
60815
|
+
paths.push(linkPath);
|
|
60816
|
+
}
|
|
60817
|
+
}
|
|
60818
|
+
const previous = readSkillInstallState();
|
|
60819
|
+
writeSkillInstallState({
|
|
60820
|
+
version: VERSION,
|
|
60821
|
+
agents: [...new Set([...previous?.agents ?? [], ...agents])],
|
|
60822
|
+
installedAt: Date.now()
|
|
60823
|
+
});
|
|
60824
|
+
rmSync5(join22(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
|
|
60825
|
+
logger.info("skill", `Installed bundled skills v${VERSION} for ${agents.join(", ")}`);
|
|
60826
|
+
return { success: true, version: VERSION, paths };
|
|
59953
60827
|
} catch (err) {
|
|
59954
60828
|
logger.error("skill", `Failed to install skill: ${err}`);
|
|
59955
60829
|
return { success: false };
|
|
59956
60830
|
}
|
|
59957
|
-
const sha = await fetchLatestSha();
|
|
59958
|
-
if (sha) {
|
|
59959
|
-
writeSkillCache({
|
|
59960
|
-
lastCheck: Date.now(),
|
|
59961
|
-
latestSha: sha,
|
|
59962
|
-
installedSha: sha
|
|
59963
|
-
});
|
|
59964
|
-
return { success: true, sha };
|
|
59965
|
-
}
|
|
59966
|
-
logger.debug("skill", "Skill installed but could not fetch latest SHA");
|
|
59967
|
-
return { success: true };
|
|
59968
60831
|
}
|
|
59969
|
-
function
|
|
59970
|
-
|
|
59971
|
-
|
|
59972
|
-
|
|
59973
|
-
|
|
59974
|
-
|
|
59975
|
-
|
|
59976
|
-
|
|
59977
|
-
|
|
59978
|
-
|
|
59979
|
-
|
|
59980
|
-
|
|
59981
|
-
|
|
59982
|
-
|
|
59983
|
-
|
|
59984
|
-
|
|
59985
|
-
|
|
59986
|
-
if (entry.source !== SKILL_REPO || typeof entry.name !== "string")
|
|
59987
|
-
continue;
|
|
59988
|
-
if (!SAFE_SKILL_NAME.test(entry.name)) {
|
|
59989
|
-
logger.warn("skill", `Skipping skill with an unsupported name: ${entry.name}`);
|
|
59990
|
-
continue;
|
|
60832
|
+
async function installSkill(providerIDs) {
|
|
60833
|
+
const agents = providerIDs === undefined ? [...SUPPORTED_SKILL_AGENTS] : skillAgentIDsForProviders(providerIDs);
|
|
60834
|
+
return installBundledSkills(agents);
|
|
60835
|
+
}
|
|
60836
|
+
function removeSkills() {
|
|
60837
|
+
const legacy = pruneLegacySkillLock();
|
|
60838
|
+
const names = new Set([...BUNDLED_SKILLS.map((skill) => skill.name), ...legacy]);
|
|
60839
|
+
const dirs = [
|
|
60840
|
+
universalSkillsDir(),
|
|
60841
|
+
...new Set(SUPPORTED_SKILL_AGENTS.map(linkedSkillsDir).filter((dir) => !!dir))
|
|
60842
|
+
];
|
|
60843
|
+
const removed = [];
|
|
60844
|
+
for (const dir of dirs) {
|
|
60845
|
+
for (const name of names) {
|
|
60846
|
+
const path = join22(dir, name);
|
|
60847
|
+
if (removeSkillDir(path))
|
|
60848
|
+
removed.push(path);
|
|
59991
60849
|
}
|
|
59992
|
-
names.push(entry.name);
|
|
59993
60850
|
}
|
|
59994
|
-
|
|
60851
|
+
clearSkillInstallState();
|
|
60852
|
+
rmSync5(join22(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
|
|
60853
|
+
return removed;
|
|
60854
|
+
}
|
|
60855
|
+
function printPaths(paths) {
|
|
60856
|
+
for (const path of paths)
|
|
60857
|
+
console.log(import_picocolors26.default.dim(` ${path}`));
|
|
59995
60858
|
}
|
|
59996
60859
|
function skillCommand() {
|
|
59997
|
-
const cmd = new Command("skill").description("Manage the Dosu agent
|
|
59998
|
-
cmd.command("install").description("Install the Dosu
|
|
59999
|
-
console.log(`Installing skills
|
|
60860
|
+
const cmd = new Command("skill").description("Manage the Dosu agent skills bundled with the CLI");
|
|
60861
|
+
cmd.command("install").description("Install the bundled Dosu skills for AI coding agents").action(async () => {
|
|
60862
|
+
console.log(`Installing Dosu skills (v${VERSION})...`);
|
|
60000
60863
|
const result = await installSkill();
|
|
60001
60864
|
if (result.success) {
|
|
60002
|
-
|
|
60865
|
+
printPaths(result.paths ?? []);
|
|
60866
|
+
console.log(import_picocolors26.default.green(`
|
|
60003
60867
|
✓ Skills installed successfully.`));
|
|
60004
60868
|
} else {
|
|
60005
|
-
console.error(
|
|
60006
|
-
Failed to install skill.
|
|
60869
|
+
console.error(import_picocolors26.default.red(`
|
|
60870
|
+
Failed to install skill. Run with --debug for details.`));
|
|
60007
60871
|
process.exit(1);
|
|
60008
60872
|
}
|
|
60009
60873
|
});
|
|
60010
60874
|
cmd.command("remove").description("Remove the Dosu skills").action(() => {
|
|
60011
|
-
const installed = installedSkillNames();
|
|
60012
|
-
if (installed?.length === 0) {
|
|
60013
|
-
console.log(`No skills from ${SKILL_REPO} are installed.`);
|
|
60014
|
-
return;
|
|
60015
|
-
}
|
|
60016
|
-
const targets = installed ?? [SKILL_NAME];
|
|
60017
|
-
console.log(`Removing skills from ${SKILL_REPO}...`);
|
|
60018
60875
|
try {
|
|
60019
|
-
|
|
60020
|
-
|
|
60021
|
-
|
|
60022
|
-
|
|
60023
|
-
|
|
60876
|
+
const removed = removeSkills();
|
|
60877
|
+
if (removed.length === 0) {
|
|
60878
|
+
console.log("No Dosu skills are installed.");
|
|
60879
|
+
return;
|
|
60880
|
+
}
|
|
60881
|
+
console.log("Removing Dosu skills...");
|
|
60882
|
+
printPaths(removed);
|
|
60883
|
+
console.log(import_picocolors26.default.green(`
|
|
60024
60884
|
✓ Skills removed.`));
|
|
60025
|
-
} catch {
|
|
60026
|
-
|
|
60885
|
+
} catch (err) {
|
|
60886
|
+
logger.error("skill", `Failed to remove skills: ${err}`);
|
|
60887
|
+
console.error(import_picocolors26.default.red(`
|
|
60027
60888
|
Failed to remove skills.`));
|
|
60028
60889
|
process.exit(1);
|
|
60029
60890
|
}
|
|
60030
60891
|
});
|
|
60031
|
-
cmd.command("update").description("
|
|
60032
|
-
console.log(`Updating skills
|
|
60892
|
+
cmd.command("update").description("Rewrite the Dosu skills from this CLI version (upgrade the CLI for newer skills)").action(async () => {
|
|
60893
|
+
console.log(`Updating Dosu skills to the copy bundled with v${VERSION}...`);
|
|
60033
60894
|
const result = await installSkill();
|
|
60034
60895
|
if (!result.success) {
|
|
60035
|
-
console.error(
|
|
60896
|
+
console.error(import_picocolors26.default.red(`
|
|
60036
60897
|
Failed to update skill.`));
|
|
60037
60898
|
process.exit(1);
|
|
60038
60899
|
}
|
|
60039
|
-
|
|
60900
|
+
printPaths(result.paths ?? []);
|
|
60901
|
+
console.log(import_picocolors26.default.green(`
|
|
60040
60902
|
✓ Skills updated.`));
|
|
60903
|
+
console.log(import_picocolors26.default.dim(" Skills ship with the CLI; run `dosu upgrade` to get newer ones."));
|
|
60041
60904
|
});
|
|
60042
60905
|
return cmd;
|
|
60043
60906
|
}
|
|
60044
|
-
var
|
|
60907
|
+
var import_picocolors26, SKILL_NAME = "dosu", LEGACY_SKILL_SOURCE = "dosu-ai/dosu-skill", INSTALL_STATE_FILENAME = "skill-install.json", LEGACY_CACHE_FILENAME = "skill-update-check.json", SUPPORTED_SKILL_AGENTS, SKILL_AGENT_BY_PROVIDER;
|
|
60045
60908
|
var init_skill = __esm(() => {
|
|
60046
60909
|
init_commander();
|
|
60910
|
+
init_config();
|
|
60047
60911
|
init_logger();
|
|
60048
|
-
|
|
60049
|
-
|
|
60050
|
-
SAFE_SKILL_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
60912
|
+
init_skills();
|
|
60913
|
+
import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
60051
60914
|
SUPPORTED_SKILL_AGENTS = [
|
|
60052
60915
|
"claude-code",
|
|
60053
60916
|
"cursor",
|
|
@@ -60080,7 +60943,7 @@ var init_skill = __esm(() => {
|
|
|
60080
60943
|
function requireConfig11() {
|
|
60081
60944
|
const cfg = requireLoginConfig();
|
|
60082
60945
|
if (!cfg.active_account?.target?.org_id) {
|
|
60083
|
-
console.error(
|
|
60946
|
+
console.error(import_picocolors27.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
|
|
60084
60947
|
process.exit(1);
|
|
60085
60948
|
}
|
|
60086
60949
|
return cfg;
|
|
@@ -60090,7 +60953,7 @@ function rejectWebOnlyProvider(provider, json) {
|
|
|
60090
60953
|
if (json) {
|
|
60091
60954
|
printResult({ provider, cli_supported: false, connect_via: "web", url }, { json: true });
|
|
60092
60955
|
} else {
|
|
60093
|
-
console.error(
|
|
60956
|
+
console.error(import_picocolors27.default.yellow(`Connecting '${provider}' sources is web-only for now. Open ${url}, add the source ` + `under Data Sources, then re-run 'dosu sources list'.`));
|
|
60094
60957
|
}
|
|
60095
60958
|
process.exit(1);
|
|
60096
60959
|
}
|
|
@@ -60109,7 +60972,7 @@ function sourcesCommand() {
|
|
|
60109
60972
|
}
|
|
60110
60973
|
const list = dataSources ?? [];
|
|
60111
60974
|
if (list.length === 0) {
|
|
60112
|
-
console.log(
|
|
60975
|
+
console.log(import_picocolors27.default.dim("No data sources connected."));
|
|
60113
60976
|
return;
|
|
60114
60977
|
}
|
|
60115
60978
|
printTable(["ID", "Name", "Provider", "Created"], list.map((ds) => [
|
|
@@ -60128,7 +60991,7 @@ function sourcesCommand() {
|
|
|
60128
60991
|
return;
|
|
60129
60992
|
}
|
|
60130
60993
|
if (!ds) {
|
|
60131
|
-
console.log(
|
|
60994
|
+
console.log(import_picocolors27.default.dim("Data source not found."));
|
|
60132
60995
|
return;
|
|
60133
60996
|
}
|
|
60134
60997
|
printInfo([
|
|
@@ -60147,7 +61010,7 @@ function sourcesCommand() {
|
|
|
60147
61010
|
printResult({ success: true, id }, opts);
|
|
60148
61011
|
return;
|
|
60149
61012
|
}
|
|
60150
|
-
console.log(
|
|
61013
|
+
console.log(import_picocolors27.default.green(`Data source sync triggered for ${id.slice(0, 8)}.`));
|
|
60151
61014
|
});
|
|
60152
61015
|
cmd.command("update").description("Update a data source").argument("<id>", "Data source ID").option("--name <name>", "New name").option("--description <desc>", "New description").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
60153
61016
|
if (opts.name === undefined && opts.description === undefined) {
|
|
@@ -60164,7 +61027,7 @@ function sourcesCommand() {
|
|
|
60164
61027
|
printResult(result, opts);
|
|
60165
61028
|
return;
|
|
60166
61029
|
}
|
|
60167
|
-
console.log(
|
|
61030
|
+
console.log(import_picocolors27.default.green("Data source updated."));
|
|
60168
61031
|
});
|
|
60169
61032
|
cmd.command("delete").description("Delete a data source").argument("<id>", "Data source ID").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
60170
61033
|
const cfg = requireConfig11();
|
|
@@ -60174,7 +61037,7 @@ function sourcesCommand() {
|
|
|
60174
61037
|
printResult({ success: true, id }, opts);
|
|
60175
61038
|
return;
|
|
60176
61039
|
}
|
|
60177
|
-
console.log(
|
|
61040
|
+
console.log(import_picocolors27.default.green("Data source deleted."));
|
|
60178
61041
|
});
|
|
60179
61042
|
cmd.command("connect").description("Install or update a provider integration (currently GitHub) via the browser").argument("[provider]", "Provider to connect (github)", "github").option("--json", "Emit machine-readable NDJSON progress events").option("--timeout <seconds>", "Seconds to wait for the browser install to complete", String(CONNECT_TIMEOUT_DEFAULT_SECONDS)).option("--no-open", "Print the URL without opening a browser").action(async (provider, opts) => {
|
|
60180
61043
|
const providerName = provider.toLowerCase();
|
|
@@ -60202,14 +61065,14 @@ function sourcesCommand() {
|
|
|
60202
61065
|
}));
|
|
60203
61066
|
} else {
|
|
60204
61067
|
console.log(`Open this URL to install or update the Dosu GitHub App:
|
|
60205
|
-
${
|
|
61068
|
+
${import_picocolors27.default.cyan(url)}`);
|
|
60206
61069
|
if (opts.open !== false) {
|
|
60207
61070
|
try {
|
|
60208
61071
|
const open = await Promise.resolve().then(() => (init_open(), {}));
|
|
60209
61072
|
await open_default(url);
|
|
60210
61073
|
} catch {}
|
|
60211
61074
|
}
|
|
60212
|
-
console.log(
|
|
61075
|
+
console.log(import_picocolors27.default.dim("Waiting for the install to complete..."));
|
|
60213
61076
|
}
|
|
60214
61077
|
const timedOut = new Promise((resolve) => {
|
|
60215
61078
|
timeoutId = setTimeout(() => resolve(null), timeoutSeconds * 1000);
|
|
@@ -60219,7 +61082,7 @@ function sourcesCommand() {
|
|
|
60219
61082
|
if (opts.json) {
|
|
60220
61083
|
console.log(JSON.stringify({ event: "timeout", timeout_seconds: timeoutSeconds }));
|
|
60221
61084
|
} else {
|
|
60222
|
-
console.error(
|
|
61085
|
+
console.error(import_picocolors27.default.red(`Timed out after ${timeoutSeconds}s. Finish the install in the browser, then re-run 'dosu sources connect github'.`));
|
|
60223
61086
|
}
|
|
60224
61087
|
process.exit(1);
|
|
60225
61088
|
return;
|
|
@@ -60235,14 +61098,14 @@ function sourcesCommand() {
|
|
|
60235
61098
|
}));
|
|
60236
61099
|
return;
|
|
60237
61100
|
}
|
|
60238
|
-
console.log(
|
|
61101
|
+
console.log(import_picocolors27.default.green(`GitHub App connected (installation ${result.installation_id}).`));
|
|
60239
61102
|
if (newRepositories.length > 0) {
|
|
60240
61103
|
for (const repo of newRepositories) {
|
|
60241
61104
|
console.log(` ${repo.slug}`);
|
|
60242
61105
|
}
|
|
60243
|
-
console.log(
|
|
61106
|
+
console.log(import_picocolors27.default.dim("Next: dosu sources create github --repo <owner/name> --library <library-id>"));
|
|
60244
61107
|
} else {
|
|
60245
|
-
console.log(
|
|
61108
|
+
console.log(import_picocolors27.default.dim("No new repositories visible yet — GitHub may still be syncing. " + "Re-run 'dosu sources connect github' or check 'dosu sources list' shortly."));
|
|
60246
61109
|
}
|
|
60247
61110
|
} finally {
|
|
60248
61111
|
clearTimeout(timeoutId);
|
|
@@ -60259,7 +61122,7 @@ function sourcesCommand() {
|
|
|
60259
61122
|
const orgID = cfg.active_account.target.org_id;
|
|
60260
61123
|
const libraryID = opts.library ?? cfg.active_account?.target?.space_id;
|
|
60261
61124
|
if (!libraryID) {
|
|
60262
|
-
console.error(
|
|
61125
|
+
console.error(import_picocolors27.default.red("No library specified and no active library. Pass --library <id>."));
|
|
60263
61126
|
process.exit(1);
|
|
60264
61127
|
return;
|
|
60265
61128
|
}
|
|
@@ -60267,12 +61130,12 @@ function sourcesCommand() {
|
|
|
60267
61130
|
const repos = await fetchListForOrg(client, orgID);
|
|
60268
61131
|
const repo = repos.find((r) => r.slug.toLowerCase() === opts.repo.toLowerCase());
|
|
60269
61132
|
if (!repo) {
|
|
60270
|
-
console.error(
|
|
61133
|
+
console.error(import_picocolors27.default.red(`Repository '${opts.repo}' is not visible to Dosu. Run ` + `'dosu sources connect github' to grant the GitHub App access, then retry.`));
|
|
60271
61134
|
process.exit(1);
|
|
60272
61135
|
return;
|
|
60273
61136
|
}
|
|
60274
61137
|
if (repo.is_fork === true) {
|
|
60275
|
-
console.error(
|
|
61138
|
+
console.error(import_picocolors27.default.red(`'${repo.slug}' is a fork and can't be synced.` + (repo.fork_parent_slug ? ` Connect '${repo.fork_parent_slug}' instead.` : "")));
|
|
60276
61139
|
process.exit(1);
|
|
60277
61140
|
return;
|
|
60278
61141
|
}
|
|
@@ -60296,14 +61159,14 @@ function sourcesCommand() {
|
|
|
60296
61159
|
dataSourceID: existingDataSources.get(repo.repository_id)
|
|
60297
61160
|
});
|
|
60298
61161
|
if (!created) {
|
|
60299
|
-
console.error(
|
|
61162
|
+
console.error(import_picocolors27.default.red("Could not create the data source. Check 'dosu logs --tail 50' for details."));
|
|
60300
61163
|
process.exit(1);
|
|
60301
61164
|
return;
|
|
60302
61165
|
}
|
|
60303
61166
|
const survivors = await verifyDataSourcesPersist(client, orgID, [created.data_source_id]);
|
|
60304
61167
|
if (survivors.dropped.size > 0) {
|
|
60305
61168
|
await deleteOrphanDeployment(client, created.deployment_id, repo.slug);
|
|
60306
|
-
console.error(
|
|
61169
|
+
console.error(import_picocolors27.default.red(`Dosu couldn't sync '${repo.slug}' (the GitHub App may not have access to it). ` + "Nothing was created."));
|
|
60307
61170
|
process.exit(1);
|
|
60308
61171
|
return;
|
|
60309
61172
|
}
|
|
@@ -60320,13 +61183,13 @@ function sourcesCommand() {
|
|
|
60320
61183
|
printResult(receipt, opts);
|
|
60321
61184
|
return;
|
|
60322
61185
|
}
|
|
60323
|
-
console.log(
|
|
60324
|
-
console.log(
|
|
60325
|
-
console.log(
|
|
61186
|
+
console.log(import_picocolors27.default.green(`Connected ${repo.slug} to library ${libraryID}.`));
|
|
61187
|
+
console.log(import_picocolors27.default.dim(` data source ${created.data_source_id}`));
|
|
61188
|
+
console.log(import_picocolors27.default.dim(` deployment ${created.deployment_id}`));
|
|
60326
61189
|
});
|
|
60327
61190
|
return cmd;
|
|
60328
61191
|
}
|
|
60329
|
-
var
|
|
61192
|
+
var import_picocolors27, CONNECT_TIMEOUT_DEFAULT_SECONDS = 600;
|
|
60330
61193
|
var init_sources = __esm(() => {
|
|
60331
61194
|
init_commander();
|
|
60332
61195
|
init_trpc();
|
|
@@ -60335,23 +61198,23 @@ var init_sources = __esm(() => {
|
|
|
60335
61198
|
init_auth();
|
|
60336
61199
|
init_confirmation();
|
|
60337
61200
|
init_output();
|
|
60338
|
-
|
|
61201
|
+
import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
60339
61202
|
});
|
|
60340
61203
|
|
|
60341
61204
|
// src/telemetry/settings.ts
|
|
60342
61205
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
60343
61206
|
import {
|
|
60344
61207
|
existsSync as existsSync20,
|
|
60345
|
-
lstatSync as
|
|
61208
|
+
lstatSync as lstatSync3,
|
|
60346
61209
|
mkdirSync as mkdirSync12,
|
|
60347
61210
|
readFileSync as readFileSync20,
|
|
60348
61211
|
renameSync as renameSync5,
|
|
60349
61212
|
unlinkSync as unlinkSync4,
|
|
60350
61213
|
writeFileSync as writeFileSync13
|
|
60351
61214
|
} from "node:fs";
|
|
60352
|
-
import { join as
|
|
61215
|
+
import { join as join23 } from "node:path";
|
|
60353
61216
|
function getTelemetrySettingsPath() {
|
|
60354
|
-
return
|
|
61217
|
+
return join23(getConfigDir(), TELEMETRY_SETTINGS_FILENAME);
|
|
60355
61218
|
}
|
|
60356
61219
|
function loadTelemetrySettings() {
|
|
60357
61220
|
return readTelemetrySettings().settings;
|
|
@@ -60407,7 +61270,7 @@ function readTelemetrySettings() {
|
|
|
60407
61270
|
const path = getTelemetrySettingsPath();
|
|
60408
61271
|
let file;
|
|
60409
61272
|
try {
|
|
60410
|
-
file =
|
|
61273
|
+
file = lstatSync3(path);
|
|
60411
61274
|
} catch (error) {
|
|
60412
61275
|
if (isErrorCode(error, "ENOENT")) {
|
|
60413
61276
|
return { status: "missing", settings: emptyTelemetrySettings() };
|
|
@@ -60567,7 +61430,7 @@ var init_telemetry2 = __esm(() => {
|
|
|
60567
61430
|
function requireConfig12() {
|
|
60568
61431
|
const cfg = requireLoginConfig();
|
|
60569
61432
|
if (!cfg.active_account?.target?.space_id) {
|
|
60570
|
-
console.error(
|
|
61433
|
+
console.error(import_picocolors28.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
60571
61434
|
process.exit(1);
|
|
60572
61435
|
}
|
|
60573
61436
|
return cfg;
|
|
@@ -60618,7 +61481,7 @@ function threadsCommand() {
|
|
|
60618
61481
|
return;
|
|
60619
61482
|
}
|
|
60620
61483
|
if (!threads || threads.length === 0) {
|
|
60621
|
-
console.log(
|
|
61484
|
+
console.log(import_picocolors28.default.dim("No threads found."));
|
|
60622
61485
|
return;
|
|
60623
61486
|
}
|
|
60624
61487
|
printTable(["ID", "Title", "Status", "Created"], threads.map((t) => [
|
|
@@ -60643,10 +61506,10 @@ function threadsCommand() {
|
|
|
60643
61506
|
return;
|
|
60644
61507
|
}
|
|
60645
61508
|
if (!thread) {
|
|
60646
|
-
console.log(
|
|
61509
|
+
console.log(import_picocolors28.default.dim("Thread not found."));
|
|
60647
61510
|
return;
|
|
60648
61511
|
}
|
|
60649
|
-
console.log(
|
|
61512
|
+
console.log(import_picocolors28.default.bold(thread.generated_title ?? "(untitled thread)"));
|
|
60650
61513
|
printInfo([
|
|
60651
61514
|
["ID", thread.id],
|
|
60652
61515
|
["Created", formatDate(thread.created_at)],
|
|
@@ -60657,13 +61520,13 @@ function threadsCommand() {
|
|
|
60657
61520
|
if (messages && messages.length > 0) {
|
|
60658
61521
|
const allMessages = messages.flatMap((group) => group.messages);
|
|
60659
61522
|
console.log(`
|
|
60660
|
-
${
|
|
60661
|
-
console.log(
|
|
61523
|
+
${import_picocolors28.default.bold("Messages")} (${allMessages.length})`);
|
|
61524
|
+
console.log(import_picocolors28.default.dim("─".repeat(60)));
|
|
60662
61525
|
for (const msg of allMessages) {
|
|
60663
61526
|
const role = msg.author_role ?? "unknown";
|
|
60664
61527
|
const date = formatDate(msg.created_at);
|
|
60665
61528
|
console.log(`
|
|
60666
|
-
${
|
|
61529
|
+
${import_picocolors28.default.bold(role)} ${import_picocolors28.default.dim(date)}`);
|
|
60667
61530
|
if (msg.body) {
|
|
60668
61531
|
console.log(truncate(msg.body, 500));
|
|
60669
61532
|
}
|
|
@@ -60678,25 +61541,25 @@ ${import_picocolors29.default.bold(role)} ${import_picocolors29.default.dim(date
|
|
|
60678
61541
|
printResult({ success: true, id }, opts);
|
|
60679
61542
|
return;
|
|
60680
61543
|
}
|
|
60681
|
-
console.log(
|
|
61544
|
+
console.log(import_picocolors28.default.green(`Thread ${id.slice(0, 8)} archived.`));
|
|
60682
61545
|
});
|
|
60683
61546
|
return cmd;
|
|
60684
61547
|
}
|
|
60685
|
-
var
|
|
61548
|
+
var import_picocolors28;
|
|
60686
61549
|
var init_threads = __esm(() => {
|
|
60687
61550
|
init_commander();
|
|
60688
61551
|
init_trpc();
|
|
60689
61552
|
init_arguments();
|
|
60690
61553
|
init_auth();
|
|
60691
61554
|
init_output();
|
|
60692
|
-
|
|
61555
|
+
import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
60693
61556
|
});
|
|
60694
61557
|
|
|
60695
61558
|
// src/commands/topics.ts
|
|
60696
61559
|
function requireConfig13() {
|
|
60697
61560
|
const cfg = requireLoginConfig();
|
|
60698
61561
|
if (!cfg.active_account?.target?.space_id) {
|
|
60699
|
-
console.error(
|
|
61562
|
+
console.error(import_picocolors29.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
60700
61563
|
process.exit(1);
|
|
60701
61564
|
}
|
|
60702
61565
|
return cfg;
|
|
@@ -60706,7 +61569,7 @@ async function getKnowledgeStoreId3(client, spaceId) {
|
|
|
60706
61569
|
space_id: spaceId
|
|
60707
61570
|
});
|
|
60708
61571
|
if (!store) {
|
|
60709
|
-
console.error(
|
|
61572
|
+
console.error(import_picocolors29.default.red("No knowledge store found for this deployment."));
|
|
60710
61573
|
process.exit(1);
|
|
60711
61574
|
}
|
|
60712
61575
|
return store.id;
|
|
@@ -60725,7 +61588,7 @@ function topicsCommand() {
|
|
|
60725
61588
|
return;
|
|
60726
61589
|
}
|
|
60727
61590
|
if (!topics || topics.length === 0) {
|
|
60728
|
-
console.log(
|
|
61591
|
+
console.log(import_picocolors29.default.dim("No topics found."));
|
|
60729
61592
|
return;
|
|
60730
61593
|
}
|
|
60731
61594
|
printTable(["ID", "Name", "Description"], topics.map((t) => [
|
|
@@ -60750,7 +61613,7 @@ function topicsCommand() {
|
|
|
60750
61613
|
return;
|
|
60751
61614
|
}
|
|
60752
61615
|
if (!pages || pages.length === 0) {
|
|
60753
|
-
console.log(
|
|
61616
|
+
console.log(import_picocolors29.default.dim("No pages found with this topic."));
|
|
60754
61617
|
return;
|
|
60755
61618
|
}
|
|
60756
61619
|
printTable(["ID", "Title"], pages.map((p) => [
|
|
@@ -60760,14 +61623,14 @@ function topicsCommand() {
|
|
|
60760
61623
|
});
|
|
60761
61624
|
return cmd;
|
|
60762
61625
|
}
|
|
60763
|
-
var
|
|
61626
|
+
var import_picocolors29;
|
|
60764
61627
|
var init_topics = __esm(() => {
|
|
60765
61628
|
init_commander();
|
|
60766
61629
|
init_trpc();
|
|
60767
61630
|
init_arguments();
|
|
60768
61631
|
init_auth();
|
|
60769
61632
|
init_output();
|
|
60770
|
-
|
|
61633
|
+
import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
60771
61634
|
});
|
|
60772
61635
|
|
|
60773
61636
|
// src/commands/upgrade.ts
|
|
@@ -60920,7 +61783,7 @@ Could not update Dosu automatically.`);
|
|
|
60920
61783
|
${plan.manualCommand}`);
|
|
60921
61784
|
return result.status && result.status > 0 ? result.status : 1;
|
|
60922
61785
|
}
|
|
60923
|
-
console.log(
|
|
61786
|
+
console.log(import_picocolors30.default.green(`
|
|
60924
61787
|
✓ Update command completed.`));
|
|
60925
61788
|
console.log('Run "dosu --version" to verify.');
|
|
60926
61789
|
return 0;
|
|
@@ -60969,7 +61832,7 @@ async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
|
60969
61832
|
try {
|
|
60970
61833
|
const result = await installSkill();
|
|
60971
61834
|
if (result.success) {
|
|
60972
|
-
console.log(
|
|
61835
|
+
console.log(import_picocolors30.default.green("✓ Skills updated."));
|
|
60973
61836
|
} else {
|
|
60974
61837
|
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
60975
61838
|
}
|
|
@@ -60987,11 +61850,11 @@ function upgradeCommand() {
|
|
|
60987
61850
|
process.exitCode = status;
|
|
60988
61851
|
});
|
|
60989
61852
|
}
|
|
60990
|
-
var
|
|
61853
|
+
var import_picocolors30, 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.';
|
|
60991
61854
|
var init_upgrade = __esm(() => {
|
|
60992
61855
|
init_commander();
|
|
60993
61856
|
init_skill();
|
|
60994
|
-
|
|
61857
|
+
import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
60995
61858
|
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
60996
61859
|
PACKAGE_MANAGERS = {
|
|
60997
61860
|
npm: {
|
|
@@ -61116,7 +61979,7 @@ var init_antigravity = __esm(() => {
|
|
|
61116
61979
|
});
|
|
61117
61980
|
|
|
61118
61981
|
// src/mcp/providers/claude.ts
|
|
61119
|
-
import { join as
|
|
61982
|
+
import { join as join24 } from "node:path";
|
|
61120
61983
|
var ClaudeProvider = () => createJSONProvider({
|
|
61121
61984
|
providerName: "Claude Code",
|
|
61122
61985
|
providerID: "claude",
|
|
@@ -61125,24 +61988,24 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
61125
61988
|
paths: ["~/.claude"],
|
|
61126
61989
|
globalPath: "~/.claude.json",
|
|
61127
61990
|
topKey: "mcpServers",
|
|
61128
|
-
localConfigPath: (cwd) =>
|
|
61991
|
+
localConfigPath: (cwd) => join24(cwd, ".mcp.json")
|
|
61129
61992
|
});
|
|
61130
61993
|
var init_claude = __esm(() => {
|
|
61131
61994
|
init_base();
|
|
61132
61995
|
});
|
|
61133
61996
|
|
|
61134
61997
|
// src/mcp/providers/claude-desktop.ts
|
|
61135
|
-
import { join as
|
|
61998
|
+
import { join as join25 } from "node:path";
|
|
61136
61999
|
function configPath() {
|
|
61137
|
-
return
|
|
62000
|
+
return join25(appSupportDir(), "Claude", "claude_desktop_config.json");
|
|
61138
62001
|
}
|
|
61139
62002
|
var ClaudeDesktopProvider = () => ({
|
|
61140
62003
|
name: () => "Claude Desktop",
|
|
61141
62004
|
id: () => "claude-desktop",
|
|
61142
62005
|
supportsLocal: () => false,
|
|
61143
62006
|
priority: () => 2,
|
|
61144
|
-
detectPaths: () => [
|
|
61145
|
-
isInstalled: () => isInstalled([
|
|
62007
|
+
detectPaths: () => [join25(appSupportDir(), "Claude")],
|
|
62008
|
+
isInstalled: () => isInstalled([join25(appSupportDir(), "Claude")]),
|
|
61146
62009
|
globalConfigPath: () => configPath(),
|
|
61147
62010
|
isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
|
|
61148
62011
|
install(cfg, global2) {
|
|
@@ -61169,14 +62032,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
61169
62032
|
});
|
|
61170
62033
|
|
|
61171
62034
|
// src/mcp/providers/cline.ts
|
|
61172
|
-
import { join as
|
|
61173
|
-
var extensionDir = () =>
|
|
62035
|
+
import { join as join26 } from "node:path";
|
|
62036
|
+
var extensionDir = () => join26(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
61174
62037
|
providerName: "Cline",
|
|
61175
62038
|
providerID: "cline",
|
|
61176
62039
|
local: false,
|
|
61177
62040
|
priorityValue: 11,
|
|
61178
62041
|
paths: [extensionDir()],
|
|
61179
|
-
globalPath:
|
|
62042
|
+
globalPath: join26(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
61180
62043
|
topKey: "mcpServers",
|
|
61181
62044
|
buildServer: ({ url, headers }) => ({
|
|
61182
62045
|
url,
|
|
@@ -61191,7 +62054,7 @@ var init_cline = __esm(() => {
|
|
|
61191
62054
|
});
|
|
61192
62055
|
|
|
61193
62056
|
// src/mcp/providers/cline-cli.ts
|
|
61194
|
-
import { join as
|
|
62057
|
+
import { join as join27 } from "node:path";
|
|
61195
62058
|
function clineDir() {
|
|
61196
62059
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
61197
62060
|
}
|
|
@@ -61201,7 +62064,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
61201
62064
|
local: false,
|
|
61202
62065
|
priorityValue: 12,
|
|
61203
62066
|
paths: [clineDir()],
|
|
61204
|
-
globalPath:
|
|
62067
|
+
globalPath: join27(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
61205
62068
|
topKey: "mcpServers",
|
|
61206
62069
|
buildServer: ({ url, headers }) => ({
|
|
61207
62070
|
url,
|
|
@@ -61217,14 +62080,14 @@ var init_cline_cli = __esm(() => {
|
|
|
61217
62080
|
|
|
61218
62081
|
// src/mcp/providers/codex.ts
|
|
61219
62082
|
import { existsSync as existsSync21, readFileSync as readFileSync21 } from "node:fs";
|
|
61220
|
-
import { dirname as
|
|
62083
|
+
import { dirname as dirname11, join as join28 } from "node:path";
|
|
61221
62084
|
function codexHome3() {
|
|
61222
62085
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
61223
62086
|
}
|
|
61224
62087
|
function getConfigPath2(global2) {
|
|
61225
62088
|
if (global2)
|
|
61226
|
-
return
|
|
61227
|
-
return
|
|
62089
|
+
return join28(codexHome3(), "config.toml");
|
|
62090
|
+
return join28(process.cwd(), ".codex", "config.toml");
|
|
61228
62091
|
}
|
|
61229
62092
|
function readTOML(path) {
|
|
61230
62093
|
if (!existsSync21(path))
|
|
@@ -61304,14 +62167,14 @@ function projectConfigPaths() {
|
|
|
61304
62167
|
const chain = [];
|
|
61305
62168
|
for (let dir = cwd;; ) {
|
|
61306
62169
|
chain.push(dir);
|
|
61307
|
-
if (existsSync21(
|
|
62170
|
+
if (existsSync21(join28(dir, ".git")))
|
|
61308
62171
|
break;
|
|
61309
|
-
const parent =
|
|
62172
|
+
const parent = dirname11(dir);
|
|
61310
62173
|
if (parent === dir)
|
|
61311
|
-
return [
|
|
62174
|
+
return [join28(cwd, ".codex", "config.toml")];
|
|
61312
62175
|
dir = parent;
|
|
61313
62176
|
}
|
|
61314
|
-
return chain.reverse().map((dir) =>
|
|
62177
|
+
return chain.reverse().map((dir) => join28(dir, ".codex", "config.toml"));
|
|
61315
62178
|
}
|
|
61316
62179
|
function pruneLegacyRemoteEntry(path) {
|
|
61317
62180
|
if (!existsSync21(path))
|
|
@@ -61328,9 +62191,9 @@ var REMOTE_HTTP_KEY, CodexProvider = () => ({
|
|
|
61328
62191
|
priority: () => 8,
|
|
61329
62192
|
detectPaths: () => ["~/.codex"],
|
|
61330
62193
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
61331
|
-
globalConfigPath: () =>
|
|
62194
|
+
globalConfigPath: () => join28(codexHome3(), "config.toml"),
|
|
61332
62195
|
isConfigured: () => {
|
|
61333
|
-
const content = readTOML(
|
|
62196
|
+
const content = readTOML(join28(codexHome3(), "config.toml"));
|
|
61334
62197
|
return content.includes("[mcp_servers.dosu]");
|
|
61335
62198
|
},
|
|
61336
62199
|
install(cfg, global2) {
|
|
@@ -61361,10 +62224,10 @@ var init_codex = __esm(() => {
|
|
|
61361
62224
|
});
|
|
61362
62225
|
|
|
61363
62226
|
// src/mcp/providers/copilot.ts
|
|
61364
|
-
import { join as
|
|
62227
|
+
import { join as join29 } from "node:path";
|
|
61365
62228
|
function globalPath() {
|
|
61366
62229
|
if (process.env.XDG_CONFIG_HOME) {
|
|
61367
|
-
return
|
|
62230
|
+
return join29(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
61368
62231
|
}
|
|
61369
62232
|
return expandHome("~/.copilot/mcp-config.json");
|
|
61370
62233
|
}
|
|
@@ -61388,7 +62251,7 @@ var CopilotProvider = () => ({
|
|
|
61388
62251
|
};
|
|
61389
62252
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
61390
62253
|
} else {
|
|
61391
|
-
const configPath =
|
|
62254
|
+
const configPath = join29(process.cwd(), ".vscode", "mcp.json");
|
|
61392
62255
|
const server = {
|
|
61393
62256
|
type: "http",
|
|
61394
62257
|
url,
|
|
@@ -61401,7 +62264,7 @@ var CopilotProvider = () => ({
|
|
|
61401
62264
|
if (global2) {
|
|
61402
62265
|
removeJSONServer(globalPath(), "mcpServers");
|
|
61403
62266
|
} else {
|
|
61404
|
-
const configPath =
|
|
62267
|
+
const configPath = join29(process.cwd(), ".vscode", "mcp.json");
|
|
61405
62268
|
removeJSONServer(configPath, "servers");
|
|
61406
62269
|
}
|
|
61407
62270
|
}
|
|
@@ -61412,7 +62275,7 @@ var init_copilot = __esm(() => {
|
|
|
61412
62275
|
});
|
|
61413
62276
|
|
|
61414
62277
|
// src/mcp/providers/cursor.ts
|
|
61415
|
-
import { join as
|
|
62278
|
+
import { join as join30 } from "node:path";
|
|
61416
62279
|
var CursorProvider = () => createJSONProvider({
|
|
61417
62280
|
providerName: "Cursor",
|
|
61418
62281
|
providerID: "cursor",
|
|
@@ -61425,14 +62288,14 @@ var CursorProvider = () => createJSONProvider({
|
|
|
61425
62288
|
url,
|
|
61426
62289
|
headers
|
|
61427
62290
|
}),
|
|
61428
|
-
localConfigPath: (cwd) =>
|
|
62291
|
+
localConfigPath: (cwd) => join30(cwd, ".cursor", "mcp.json")
|
|
61429
62292
|
});
|
|
61430
62293
|
var init_cursor = __esm(() => {
|
|
61431
62294
|
init_base();
|
|
61432
62295
|
});
|
|
61433
62296
|
|
|
61434
62297
|
// src/mcp/providers/factory.ts
|
|
61435
|
-
import { join as
|
|
62298
|
+
import { join as join31 } from "node:path";
|
|
61436
62299
|
var FactoryProvider = () => createJSONProvider({
|
|
61437
62300
|
providerName: "Factory",
|
|
61438
62301
|
providerID: "factory",
|
|
@@ -61441,14 +62304,14 @@ var FactoryProvider = () => createJSONProvider({
|
|
|
61441
62304
|
paths: ["~/.factory"],
|
|
61442
62305
|
globalPath: "~/.factory/mcp.json",
|
|
61443
62306
|
topKey: "mcpServers",
|
|
61444
|
-
localConfigPath: (cwd) =>
|
|
62307
|
+
localConfigPath: (cwd) => join31(cwd, ".factory", "mcp.json")
|
|
61445
62308
|
});
|
|
61446
62309
|
var init_factory = __esm(() => {
|
|
61447
62310
|
init_base();
|
|
61448
62311
|
});
|
|
61449
62312
|
|
|
61450
62313
|
// src/mcp/providers/gemini.ts
|
|
61451
|
-
import { join as
|
|
62314
|
+
import { join as join32 } from "node:path";
|
|
61452
62315
|
var GeminiProvider = () => createJSONProvider({
|
|
61453
62316
|
providerName: "Gemini CLI",
|
|
61454
62317
|
providerID: "gemini",
|
|
@@ -61457,7 +62320,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
61457
62320
|
paths: ["~/.gemini"],
|
|
61458
62321
|
globalPath: "~/.gemini/settings.json",
|
|
61459
62322
|
topKey: "mcpServers",
|
|
61460
|
-
localConfigPath: (cwd) =>
|
|
62323
|
+
localConfigPath: (cwd) => join32(cwd, ".gemini", "settings.json")
|
|
61461
62324
|
});
|
|
61462
62325
|
var init_gemini = __esm(() => {
|
|
61463
62326
|
init_base();
|
|
@@ -61500,7 +62363,7 @@ var init_manual = __esm(() => {
|
|
|
61500
62363
|
|
|
61501
62364
|
// src/mcp/providers/mcporter.ts
|
|
61502
62365
|
import { existsSync as existsSync22 } from "node:fs";
|
|
61503
|
-
import { join as
|
|
62366
|
+
import { join as join33 } from "node:path";
|
|
61504
62367
|
function resolveGlobalConfigPath() {
|
|
61505
62368
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
61506
62369
|
if (existsSync22(jsonPath))
|
|
@@ -61520,7 +62383,7 @@ var MCPorterProvider = () => ({
|
|
|
61520
62383
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
61521
62384
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
61522
62385
|
install(cfg, global2) {
|
|
61523
|
-
const configPath = global2 ? resolveGlobalConfigPath() :
|
|
62386
|
+
const configPath = global2 ? resolveGlobalConfigPath() : join33(process.cwd(), "config", "mcporter.json");
|
|
61524
62387
|
const server = {
|
|
61525
62388
|
type: "http",
|
|
61526
62389
|
url: mcpEndpoint(cfg),
|
|
@@ -61529,7 +62392,7 @@ var MCPorterProvider = () => ({
|
|
|
61529
62392
|
installJSONServer(configPath, "mcpServers", server);
|
|
61530
62393
|
},
|
|
61531
62394
|
remove(global2) {
|
|
61532
|
-
const configPath = global2 ? resolveGlobalConfigPath() :
|
|
62395
|
+
const configPath = global2 ? resolveGlobalConfigPath() : join33(process.cwd(), "config", "mcporter.json");
|
|
61533
62396
|
removeJSONServer(configPath, "mcpServers");
|
|
61534
62397
|
}
|
|
61535
62398
|
});
|
|
@@ -61539,7 +62402,7 @@ var init_mcporter = __esm(() => {
|
|
|
61539
62402
|
});
|
|
61540
62403
|
|
|
61541
62404
|
// src/mcp/providers/opencode.ts
|
|
61542
|
-
import { join as
|
|
62405
|
+
import { join as join34 } from "node:path";
|
|
61543
62406
|
var OpenCodeProvider = () => createJSONProvider({
|
|
61544
62407
|
providerName: "OpenCode",
|
|
61545
62408
|
providerID: "opencode",
|
|
@@ -61554,23 +62417,23 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
61554
62417
|
enabled: true,
|
|
61555
62418
|
headers
|
|
61556
62419
|
}),
|
|
61557
|
-
localConfigPath: (cwd) =>
|
|
62420
|
+
localConfigPath: (cwd) => join34(cwd, "opencode.json")
|
|
61558
62421
|
});
|
|
61559
62422
|
var init_opencode = __esm(() => {
|
|
61560
62423
|
init_base();
|
|
61561
62424
|
});
|
|
61562
62425
|
|
|
61563
62426
|
// src/mcp/providers/vscode.ts
|
|
61564
|
-
import { join as
|
|
62427
|
+
import { join as join35 } from "node:path";
|
|
61565
62428
|
var VSCodeProvider = () => createJSONProvider({
|
|
61566
62429
|
providerName: "VS Code",
|
|
61567
62430
|
providerID: "vscode",
|
|
61568
62431
|
local: true,
|
|
61569
62432
|
priorityValue: 6,
|
|
61570
|
-
paths: [
|
|
61571
|
-
globalPath:
|
|
62433
|
+
paths: [join35(appSupportDir(), "Code")],
|
|
62434
|
+
globalPath: join35(appSupportDir(), "Code", "User", "mcp.json"),
|
|
61572
62435
|
topKey: "servers",
|
|
61573
|
-
localConfigPath: (cwd) =>
|
|
62436
|
+
localConfigPath: (cwd) => join35(cwd, ".vscode", "mcp.json")
|
|
61574
62437
|
});
|
|
61575
62438
|
var init_vscode = __esm(() => {
|
|
61576
62439
|
init_detect();
|
|
@@ -61579,14 +62442,14 @@ var init_vscode = __esm(() => {
|
|
|
61579
62442
|
|
|
61580
62443
|
// src/mcp/providers/windsurf.ts
|
|
61581
62444
|
import { homedir as homedir10 } from "node:os";
|
|
61582
|
-
import { join as
|
|
62445
|
+
import { join as join36 } from "node:path";
|
|
61583
62446
|
var WindsurfProvider = () => createJSONProvider({
|
|
61584
62447
|
providerName: "Windsurf",
|
|
61585
62448
|
providerID: "windsurf",
|
|
61586
62449
|
local: false,
|
|
61587
62450
|
priorityValue: 9,
|
|
61588
|
-
paths: [
|
|
61589
|
-
globalPath:
|
|
62451
|
+
paths: [join36(homedir10(), ".codeium", "windsurf")],
|
|
62452
|
+
globalPath: join36(homedir10(), ".codeium", "windsurf", "mcp_config.json"),
|
|
61590
62453
|
topKey: "mcpServers"
|
|
61591
62454
|
});
|
|
61592
62455
|
var init_windsurf = __esm(() => {
|
|
@@ -61594,27 +62457,27 @@ var init_windsurf = __esm(() => {
|
|
|
61594
62457
|
});
|
|
61595
62458
|
|
|
61596
62459
|
// src/mcp/providers/zed.ts
|
|
61597
|
-
import { rmSync as
|
|
62460
|
+
import { rmSync as rmSync6 } from "node:fs";
|
|
61598
62461
|
import { homedir as homedir11, platform as platform3 } from "node:os";
|
|
61599
|
-
import { join as
|
|
62462
|
+
import { join as join37 } from "node:path";
|
|
61600
62463
|
function zedConfigDir() {
|
|
61601
62464
|
const os = platform3();
|
|
61602
62465
|
if (os === "win32")
|
|
61603
|
-
return
|
|
62466
|
+
return join37(appSupportDir(), "Zed");
|
|
61604
62467
|
if (os === "darwin")
|
|
61605
|
-
return
|
|
61606
|
-
return
|
|
62468
|
+
return join37(homedir11(), ".config", "zed");
|
|
62469
|
+
return join37(appSupportDir(), "zed");
|
|
61607
62470
|
}
|
|
61608
62471
|
function zedDataDir() {
|
|
61609
62472
|
const os = platform3();
|
|
61610
62473
|
if (os === "darwin")
|
|
61611
|
-
return
|
|
62474
|
+
return join37(appSupportDir(), "Zed");
|
|
61612
62475
|
if (os === "win32")
|
|
61613
|
-
return
|
|
61614
|
-
return
|
|
62476
|
+
return join37(process.env.LOCALAPPDATA ?? "", "Zed");
|
|
62477
|
+
return join37(process.env.XDG_DATA_HOME ?? join37(homedir11(), ".local", "share"), "zed");
|
|
61615
62478
|
}
|
|
61616
62479
|
function legacyDarwinSettingsPath() {
|
|
61617
|
-
return platform3() === "darwin" ?
|
|
62480
|
+
return platform3() === "darwin" ? join37(appSupportDir(), "Zed", "settings.json") : null;
|
|
61618
62481
|
}
|
|
61619
62482
|
function removeLegacyDosuEntry(path) {
|
|
61620
62483
|
let cfg;
|
|
@@ -61629,7 +62492,7 @@ function removeLegacyDosuEntry(path) {
|
|
|
61629
62492
|
delete servers.dosu;
|
|
61630
62493
|
const nothingElse = Object.keys(cfg).length === 1 && Object.keys(servers).length === 0;
|
|
61631
62494
|
if (nothingElse)
|
|
61632
|
-
|
|
62495
|
+
rmSync6(path, { force: true });
|
|
61633
62496
|
else
|
|
61634
62497
|
saveJSONConfig(path, cfg);
|
|
61635
62498
|
}
|
|
@@ -61640,10 +62503,10 @@ var ZedProvider = (legacyPath = legacyDarwinSettingsPath()) => {
|
|
|
61640
62503
|
local: true,
|
|
61641
62504
|
priorityValue: 10,
|
|
61642
62505
|
paths: [zedConfigDir(), zedDataDir()],
|
|
61643
|
-
globalPath:
|
|
62506
|
+
globalPath: join37(zedConfigDir(), "settings.json"),
|
|
61644
62507
|
topKey: "context_servers",
|
|
61645
62508
|
buildServer: ({ url, headers }) => ({ url, headers }),
|
|
61646
|
-
localConfigPath: (cwd) =>
|
|
62509
|
+
localConfigPath: (cwd) => join37(cwd, ".zed", "settings.json")
|
|
61647
62510
|
});
|
|
61648
62511
|
if (!legacyPath)
|
|
61649
62512
|
return provider;
|
|
@@ -61749,7 +62612,7 @@ var init_refresh = __esm(() => {
|
|
|
61749
62612
|
|
|
61750
62613
|
// src/version/update-check.ts
|
|
61751
62614
|
import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
|
|
61752
|
-
import { join as
|
|
62615
|
+
import { join as join38 } from "node:path";
|
|
61753
62616
|
function isValidVersion(value) {
|
|
61754
62617
|
return typeof value === "string" && SEMVER_PATTERN.test(value);
|
|
61755
62618
|
}
|
|
@@ -61770,12 +62633,12 @@ function isNewerVersion(latest, current) {
|
|
|
61770
62633
|
}
|
|
61771
62634
|
return false;
|
|
61772
62635
|
}
|
|
61773
|
-
function
|
|
61774
|
-
return
|
|
62636
|
+
function getCachePath2() {
|
|
62637
|
+
return join38(getConfigDir(), CACHE_FILENAME3);
|
|
61775
62638
|
}
|
|
61776
62639
|
function readCache() {
|
|
61777
62640
|
try {
|
|
61778
|
-
const path =
|
|
62641
|
+
const path = getCachePath2();
|
|
61779
62642
|
if (!existsSync23(path))
|
|
61780
62643
|
return null;
|
|
61781
62644
|
const data = JSON.parse(readFileSync22(path, "utf-8"));
|
|
@@ -61793,12 +62656,12 @@ function writeCache(cache) {
|
|
|
61793
62656
|
if (!existsSync23(dir)) {
|
|
61794
62657
|
mkdirSync13(dir, { recursive: true, mode: 448 });
|
|
61795
62658
|
}
|
|
61796
|
-
writeFileSync14(
|
|
62659
|
+
writeFileSync14(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
61797
62660
|
} catch {}
|
|
61798
62661
|
}
|
|
61799
62662
|
async function fetchLatestVersion() {
|
|
61800
62663
|
const controller = new AbortController;
|
|
61801
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
62664
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
61802
62665
|
try {
|
|
61803
62666
|
const resp = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
61804
62667
|
if (!resp.ok)
|
|
@@ -61821,29 +62684,29 @@ function buildUpdateHint(channel, npx = false) {
|
|
|
61821
62684
|
function styleHint(hint) {
|
|
61822
62685
|
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
61823
62686
|
if (!match)
|
|
61824
|
-
return
|
|
62687
|
+
return import_picocolors31.default.dim(hint);
|
|
61825
62688
|
const [, before, command, after] = match;
|
|
61826
|
-
return [before &&
|
|
62689
|
+
return [before && import_picocolors31.default.dim(before), import_picocolors31.default.cyan(command), after && import_picocolors31.default.dim(after)].filter(Boolean).join("");
|
|
61827
62690
|
}
|
|
61828
62691
|
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
61829
62692
|
const hint = buildUpdateHint(channel, npx);
|
|
61830
62693
|
if (interactive) {
|
|
61831
62694
|
const content = [
|
|
61832
|
-
`Update available: ${
|
|
62695
|
+
`Update available: ${import_picocolors31.default.dim(current)} ${import_picocolors31.default.dim("→")} ${import_picocolors31.default.bold(brand(latest))}`,
|
|
61833
62696
|
styleHint(hint)
|
|
61834
62697
|
];
|
|
61835
62698
|
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
61836
62699
|
const framed = (line) => {
|
|
61837
62700
|
const pad = innerWidth - visibleWidth2(line);
|
|
61838
62701
|
const left = Math.floor(pad / 2);
|
|
61839
|
-
return `${
|
|
62702
|
+
return `${import_picocolors31.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors31.default.yellow("│")}`;
|
|
61840
62703
|
};
|
|
61841
62704
|
const box = [
|
|
61842
|
-
|
|
62705
|
+
import_picocolors31.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
61843
62706
|
framed(""),
|
|
61844
62707
|
...content.map(framed),
|
|
61845
62708
|
framed(""),
|
|
61846
|
-
|
|
62709
|
+
import_picocolors31.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
61847
62710
|
];
|
|
61848
62711
|
return `
|
|
61849
62712
|
${centerBlock(box, width).join(`
|
|
@@ -61861,17 +62724,17 @@ function getAvailableUpdate() {
|
|
|
61861
62724
|
const cache = readCache();
|
|
61862
62725
|
return cache && isNewerVersion(cache.latestVersion, VERSION) ? cache.latestVersion : null;
|
|
61863
62726
|
}
|
|
61864
|
-
function
|
|
62727
|
+
function displayNotice(current, latest) {
|
|
61865
62728
|
console.error(buildUpdateNotice(current, latest, INSTALL_CHANNEL, process.stderr.isTTY === true, isNpxInvocation()));
|
|
61866
62729
|
}
|
|
61867
62730
|
async function checkForUpdates(options = {}) {
|
|
61868
62731
|
const notify = options.notify ?? true;
|
|
61869
62732
|
try {
|
|
61870
62733
|
const cache = readCache();
|
|
61871
|
-
const isStale = !cache || Date.now() - cache.lastCheck >
|
|
62734
|
+
const isStale = !cache || Date.now() - cache.lastCheck > CHECK_INTERVAL_MS2;
|
|
61872
62735
|
if (!isStale) {
|
|
61873
62736
|
if (notify && isNewerVersion(cache.latestVersion, VERSION)) {
|
|
61874
|
-
|
|
62737
|
+
displayNotice(VERSION, cache.latestVersion);
|
|
61875
62738
|
}
|
|
61876
62739
|
return;
|
|
61877
62740
|
}
|
|
@@ -61885,26 +62748,26 @@ async function checkForUpdates(options = {}) {
|
|
|
61885
62748
|
logger.debug("update-check", `Cached latest version: ${latest}`);
|
|
61886
62749
|
}
|
|
61887
62750
|
if (notify && isNewerVersion(latestKnownVersion, VERSION)) {
|
|
61888
|
-
|
|
62751
|
+
displayNotice(VERSION, latestKnownVersion);
|
|
61889
62752
|
}
|
|
61890
62753
|
} catch (err) {
|
|
61891
62754
|
logger.error("update-check", `Update check failed: ${err}`);
|
|
61892
62755
|
}
|
|
61893
62756
|
}
|
|
61894
|
-
var
|
|
62757
|
+
var import_picocolors31, CACHE_FILENAME3 = "update-check.json", CHECK_INTERVAL_MS2, FETCH_TIMEOUT_MS2 = 1000, REGISTRY_URL = "https://registry.npmjs.org/-/package/@dosu/cli/dist-tags", SEMVER_PATTERN, BOX_PADDING = 3;
|
|
61895
62758
|
var init_update_check = __esm(() => {
|
|
61896
62759
|
init_config();
|
|
61897
62760
|
init_logger();
|
|
61898
62761
|
init_styles();
|
|
61899
62762
|
init_layout();
|
|
61900
|
-
|
|
61901
|
-
|
|
62763
|
+
import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
62764
|
+
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
61902
62765
|
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-]+)*)?$/;
|
|
61903
62766
|
});
|
|
61904
62767
|
|
|
61905
62768
|
// src/version/mcp-refresh-check.ts
|
|
61906
62769
|
import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
|
|
61907
|
-
import { join as
|
|
62770
|
+
import { join as join39 } from "node:path";
|
|
61908
62771
|
function needsMcpRefresh(previous, current) {
|
|
61909
62772
|
if (previous === null)
|
|
61910
62773
|
return true;
|
|
@@ -61913,12 +62776,12 @@ function needsMcpRefresh(previous, current) {
|
|
|
61913
62776
|
const [older, newer] = isNewerVersion(current, previous) ? [previous, current] : [current, previous];
|
|
61914
62777
|
return MCP_FORMAT_CHANGES.some((change) => isNewerVersion(change, older) && !isNewerVersion(change, newer));
|
|
61915
62778
|
}
|
|
61916
|
-
function
|
|
61917
|
-
return
|
|
62779
|
+
function getCachePath3() {
|
|
62780
|
+
return join39(getConfigDir(), CACHE_FILENAME4);
|
|
61918
62781
|
}
|
|
61919
62782
|
function readMcpRefreshCache() {
|
|
61920
62783
|
try {
|
|
61921
|
-
const path =
|
|
62784
|
+
const path = getCachePath3();
|
|
61922
62785
|
if (!existsSync24(path))
|
|
61923
62786
|
return null;
|
|
61924
62787
|
const data = JSON.parse(readFileSync23(path, "utf-8"));
|
|
@@ -61935,7 +62798,7 @@ function writeMcpRefreshCache(cache) {
|
|
|
61935
62798
|
if (!existsSync24(dir)) {
|
|
61936
62799
|
mkdirSync14(dir, { recursive: true, mode: 448 });
|
|
61937
62800
|
}
|
|
61938
|
-
writeFileSync15(
|
|
62801
|
+
writeFileSync15(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
61939
62802
|
} catch {}
|
|
61940
62803
|
}
|
|
61941
62804
|
function canRefreshMcp(cfg) {
|
|
@@ -61944,10 +62807,10 @@ function canRefreshMcp(cfg) {
|
|
|
61944
62807
|
return false;
|
|
61945
62808
|
return cfg.mode === MODE_OSS || Boolean(target.deployment_id);
|
|
61946
62809
|
}
|
|
61947
|
-
function
|
|
62810
|
+
function displayNotice2(names) {
|
|
61948
62811
|
console.error(`
|
|
61949
|
-
${
|
|
61950
|
-
` + `${
|
|
62812
|
+
${import_picocolors32.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
|
|
62813
|
+
` + `${import_picocolors32.default.dim(` Run ${import_picocolors32.default.cyan('"dosu setup"')} to also update hooks and rules, then restart your AI agents.`)}
|
|
61951
62814
|
`);
|
|
61952
62815
|
}
|
|
61953
62816
|
function checkForMcpRefresh(options = {}) {
|
|
@@ -61969,31 +62832,63 @@ function checkForMcpRefresh(options = {}) {
|
|
|
61969
62832
|
writeMcpRefreshCache({ version: VERSION });
|
|
61970
62833
|
logger.info("mcp-refresh", `Version ${VERSION}: refreshed ${result.updated.length}, failed ${result.failed.length}`);
|
|
61971
62834
|
if (notify && result.updated.length > 0) {
|
|
61972
|
-
|
|
62835
|
+
displayNotice2(result.updated.map((provider) => provider.name()));
|
|
61973
62836
|
}
|
|
61974
62837
|
} catch (err) {
|
|
61975
62838
|
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
61976
62839
|
}
|
|
61977
62840
|
}
|
|
61978
|
-
var
|
|
62841
|
+
var import_picocolors32, CACHE_FILENAME4 = "mcp-refresh.json", MCP_FORMAT_CHANGES;
|
|
61979
62842
|
var init_mcp_refresh_check = __esm(() => {
|
|
61980
62843
|
init_config();
|
|
61981
62844
|
init_logger();
|
|
61982
62845
|
init_refresh();
|
|
61983
62846
|
init_update_check();
|
|
61984
|
-
|
|
62847
|
+
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
61985
62848
|
MCP_FORMAT_CHANGES = ["0.53.0"];
|
|
61986
62849
|
});
|
|
61987
62850
|
|
|
62851
|
+
// src/version/skill-update-check.ts
|
|
62852
|
+
function displayNotice3() {
|
|
62853
|
+
console.error(`
|
|
62854
|
+
${import_picocolors33.default.green(`✓ Dosu ${VERSION}: refreshed the bundled agent skills`)}
|
|
62855
|
+
` + `${import_picocolors33.default.dim(" Restart your AI agents to pick up the new skill content.")}
|
|
62856
|
+
`);
|
|
62857
|
+
}
|
|
62858
|
+
function checkForSkillUpdates(options = {}) {
|
|
62859
|
+
const notify = options.notify ?? true;
|
|
62860
|
+
try {
|
|
62861
|
+
const state = readSkillInstallState();
|
|
62862
|
+
if (!state || state.version === VERSION)
|
|
62863
|
+
return;
|
|
62864
|
+
const result = installBundledSkills(state.agents);
|
|
62865
|
+
if (!result.success) {
|
|
62866
|
+
logger.error("skill-update-check", `Skill refresh to ${VERSION} failed; will retry`);
|
|
62867
|
+
return;
|
|
62868
|
+
}
|
|
62869
|
+
logger.info("skill-update-check", `Refreshed skills from ${state.version} to ${VERSION}`);
|
|
62870
|
+
if (notify && result.version)
|
|
62871
|
+
displayNotice3();
|
|
62872
|
+
} catch (err) {
|
|
62873
|
+
logger.error("skill-update-check", `Skill update check failed: ${err}`);
|
|
62874
|
+
}
|
|
62875
|
+
}
|
|
62876
|
+
var import_picocolors33;
|
|
62877
|
+
var init_skill_update_check = __esm(() => {
|
|
62878
|
+
init_skill();
|
|
62879
|
+
init_logger();
|
|
62880
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
62881
|
+
});
|
|
62882
|
+
|
|
61988
62883
|
// src/rules/installer.ts
|
|
61989
62884
|
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "node:fs";
|
|
61990
62885
|
import { homedir as homedir12 } from "node:os";
|
|
61991
|
-
import { dirname as
|
|
62886
|
+
import { dirname as dirname12, join as join40 } from "node:path";
|
|
61992
62887
|
function claudeConfigDir4() {
|
|
61993
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
62888
|
+
return process.env.CLAUDE_CONFIG_DIR || join40(homedir12(), ".claude");
|
|
61994
62889
|
}
|
|
61995
62890
|
function codexHome4() {
|
|
61996
|
-
return process.env.CODEX_HOME ||
|
|
62891
|
+
return process.env.CODEX_HOME || join40(homedir12(), ".codex");
|
|
61997
62892
|
}
|
|
61998
62893
|
function isRuleAgent(agent) {
|
|
61999
62894
|
return Object.hasOwn(RULE_TARGETS, agent);
|
|
@@ -62019,7 +62914,7 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
62019
62914
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
62020
62915
|
}
|
|
62021
62916
|
function ensureParent(path) {
|
|
62022
|
-
mkdirSync15(
|
|
62917
|
+
mkdirSync15(dirname12(path), { recursive: true });
|
|
62023
62918
|
}
|
|
62024
62919
|
function writeIfChanged(path, content) {
|
|
62025
62920
|
if (!existsSync25(path)) {
|
|
@@ -62135,39 +63030,39 @@ var init_installer = __esm(() => {
|
|
|
62135
63030
|
RULE_TARGETS = {
|
|
62136
63031
|
claude: {
|
|
62137
63032
|
kind: "file",
|
|
62138
|
-
path: () =>
|
|
63033
|
+
path: () => join40(claudeConfigDir4(), "rules", "dosu.md")
|
|
62139
63034
|
},
|
|
62140
63035
|
cursor: {
|
|
62141
63036
|
kind: "file",
|
|
62142
|
-
path: () =>
|
|
63037
|
+
path: () => join40(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
62143
63038
|
cursorFrontmatter: true
|
|
62144
63039
|
},
|
|
62145
63040
|
codex: {
|
|
62146
63041
|
kind: "section",
|
|
62147
|
-
path: () =>
|
|
63042
|
+
path: () => join40(codexHome4(), "AGENTS.md")
|
|
62148
63043
|
},
|
|
62149
63044
|
opencode: {
|
|
62150
63045
|
kind: "section",
|
|
62151
|
-
path: () =>
|
|
63046
|
+
path: () => join40(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
62152
63047
|
},
|
|
62153
63048
|
gemini: {
|
|
62154
63049
|
kind: "section",
|
|
62155
|
-
path: () =>
|
|
63050
|
+
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
62156
63051
|
},
|
|
62157
63052
|
antigravity: {
|
|
62158
63053
|
kind: "section",
|
|
62159
|
-
path: () =>
|
|
63054
|
+
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
62160
63055
|
}
|
|
62161
63056
|
};
|
|
62162
63057
|
});
|
|
62163
63058
|
|
|
62164
63059
|
// src/setup/agents-md-step.ts
|
|
62165
|
-
import { execSync as
|
|
63060
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
62166
63061
|
import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
62167
|
-
import { join as
|
|
63062
|
+
import { join as join41 } from "node:path";
|
|
62168
63063
|
function inGitWorkTree(cwd = process.cwd()) {
|
|
62169
63064
|
try {
|
|
62170
|
-
const stdout =
|
|
63065
|
+
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
62171
63066
|
cwd,
|
|
62172
63067
|
stdio: ["ignore", "pipe", "ignore"]
|
|
62173
63068
|
});
|
|
@@ -62178,7 +63073,7 @@ function inGitWorkTree(cwd = process.cwd()) {
|
|
|
62178
63073
|
}
|
|
62179
63074
|
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
62180
63075
|
try {
|
|
62181
|
-
const path =
|
|
63076
|
+
const path = join41(cwd, "AGENTS.md");
|
|
62182
63077
|
if (!existsSync26(path))
|
|
62183
63078
|
return "missing";
|
|
62184
63079
|
const content = readFileSync25(path, "utf-8");
|
|
@@ -62216,7 +63111,7 @@ function findSection2(content) {
|
|
|
62216
63111
|
return { start, end };
|
|
62217
63112
|
}
|
|
62218
63113
|
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
62219
|
-
const path =
|
|
63114
|
+
const path = join41(cwd, "AGENTS.md");
|
|
62220
63115
|
if (!existsSync26(path)) {
|
|
62221
63116
|
const section = buildDosuAgentsSection(content);
|
|
62222
63117
|
writeFileSync17(path, `${section}
|
|
@@ -62293,9 +63188,9 @@ var MCP_PROVIDER_SLUG2 = "dosu_mcp";
|
|
|
62293
63188
|
// src/sessions/session-title.ts
|
|
62294
63189
|
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync18 } from "node:fs";
|
|
62295
63190
|
import { homedir as homedir13 } from "node:os";
|
|
62296
|
-
import { join as
|
|
63191
|
+
import { join as join42 } from "node:path";
|
|
62297
63192
|
function cachePath2(configDir) {
|
|
62298
|
-
return
|
|
63193
|
+
return join42(configDir, CACHE_FILENAME5);
|
|
62299
63194
|
}
|
|
62300
63195
|
function loadCacheFile2(configDir) {
|
|
62301
63196
|
try {
|
|
@@ -62352,10 +63247,10 @@ function reconstructSession(harness, id, slug, home = homedir13(), exists = exis
|
|
|
62352
63247
|
return null;
|
|
62353
63248
|
const candidates = [];
|
|
62354
63249
|
if (harness === "claude") {
|
|
62355
|
-
candidates.push(
|
|
63250
|
+
candidates.push(join42(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
62356
63251
|
} else if (harness === "cursor") {
|
|
62357
|
-
const project =
|
|
62358
|
-
candidates.push(
|
|
63252
|
+
const project = join42(home, ".cursor", "projects", slug);
|
|
63253
|
+
candidates.push(join42(project, "agent-transcripts", id, `${id}.jsonl`), join42(project, "agent-transcripts", `${id}.jsonl`));
|
|
62359
63254
|
} else {
|
|
62360
63255
|
return null;
|
|
62361
63256
|
}
|
|
@@ -62418,7 +63313,7 @@ function createSessionTitleResolver(configDir = getConfigDir(), deps = {}) {
|
|
|
62418
63313
|
}
|
|
62419
63314
|
};
|
|
62420
63315
|
}
|
|
62421
|
-
var
|
|
63316
|
+
var CACHE_FILENAME5 = "session-titles.json", CACHE_SCHEMA_VERSION2 = 3, HEAD_LINES2 = 50, SESSION_NAME_MAX = 80;
|
|
62422
63317
|
var init_session_title = __esm(() => {
|
|
62423
63318
|
init_config();
|
|
62424
63319
|
init_read();
|
|
@@ -63930,9 +64825,9 @@ async function runInstallSkill(providers) {
|
|
|
63930
64825
|
const agentLabel = providers.length === 1 ? "agent" : "agents";
|
|
63931
64826
|
spinner.start(`Installing skill for ${providers.length} ${agentLabel}`);
|
|
63932
64827
|
try {
|
|
63933
|
-
const result = await installSkill(providers.map((provider) => provider.id())
|
|
64828
|
+
const result = await installSkill(providers.map((provider) => provider.id()));
|
|
63934
64829
|
if (result.success) {
|
|
63935
|
-
logger.info("setup", `Skill installed${result.
|
|
64830
|
+
logger.info("setup", `Skill installed${result.version ? ` v${result.version}` : ""}`);
|
|
63936
64831
|
const items = providers.flatMap((provider) => {
|
|
63937
64832
|
const target = skillInstallTargetForProvider(provider.id());
|
|
63938
64833
|
if (!target)
|
|
@@ -66079,7 +66974,7 @@ async function runAgentSetup(opts) {
|
|
|
66079
66974
|
}
|
|
66080
66975
|
if (skillAgentIDsForProviders([provider.id()]).length > 0) {
|
|
66081
66976
|
try {
|
|
66082
|
-
const skill = await installSkill([provider.id()]
|
|
66977
|
+
const skill = await installSkill([provider.id()]);
|
|
66083
66978
|
if (!skill.success) {
|
|
66084
66979
|
throw new Error("the skills installer failed");
|
|
66085
66980
|
}
|
|
@@ -66087,7 +66982,8 @@ async function runAgentSetup(opts) {
|
|
|
66087
66982
|
step: "skill_install",
|
|
66088
66983
|
tool: provider.id(),
|
|
66089
66984
|
tool_name: provider.name(),
|
|
66090
|
-
source: "dosu
|
|
66985
|
+
source: "@dosu/cli",
|
|
66986
|
+
version: skill.version
|
|
66091
66987
|
});
|
|
66092
66988
|
} catch (err) {
|
|
66093
66989
|
emitError({
|
|
@@ -66469,7 +67365,7 @@ function createProgram(options = {}) {
|
|
|
66469
67365
|
if (!process.env.CI) {
|
|
66470
67366
|
await checkForUpdates({ notify: !launchesTUI });
|
|
66471
67367
|
}
|
|
66472
|
-
checkForSkillUpdates();
|
|
67368
|
+
checkForSkillUpdates({ notify: !launchesTUI });
|
|
66473
67369
|
checkForReadyTasks();
|
|
66474
67370
|
if (shouldRunMcpRefreshCheck(actionCommand)) {
|
|
66475
67371
|
checkForMcpRefresh({ notify: !launchesTUI });
|
|
@@ -66947,4 +67843,4 @@ main().catch((err) => {
|
|
|
66947
67843
|
process.exit(1);
|
|
66948
67844
|
});
|
|
66949
67845
|
|
|
66950
|
-
//# debugId=
|
|
67846
|
+
//# debugId=bd089d5e-a4ab-0f80-6475-6e2164756e21
|