@dosu/cli 0.66.1 → 0.67.1
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 +1 -1
- package/bin/dosu.js +403 -206
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,7 +119,7 @@ Once authenticated against a deployment, you can drive the Dosu platform without
|
|
|
119
119
|
| `dosu knowledge` | Search and browse your knowledge base |
|
|
120
120
|
| `dosu docs` | Manage documents (list, create, update, import, publish) |
|
|
121
121
|
| `dosu threads` | List and manage conversation threads |
|
|
122
|
-
| `dosu review` | Document review workflow, plus `review notifications` to route a Library's or Agent's reviews to a Slack channel |
|
|
122
|
+
| `dosu review` | Document review workflow for the selected Library, plus `review notifications` to route a Library's or Agent's reviews to a Slack channel |
|
|
123
123
|
| `dosu sources` | Manage connected data sources (list, connect, create, sync, update) |
|
|
124
124
|
| `dosu integrations` | List and inspect platform integrations (Slack, GitHub, …) |
|
|
125
125
|
| `dosu topics` | List knowledge base topics and their pages |
|
package/bin/dosu.js
CHANGED
|
@@ -47,6 +47,111 @@ var __esm = (fn, res, err) => () => {
|
|
|
47
47
|
};
|
|
48
48
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
49
49
|
|
|
50
|
+
// node_modules/picocolors/picocolors.js
|
|
51
|
+
var require_picocolors = __commonJS(function(exports, module) {
|
|
52
|
+
var p = process || {};
|
|
53
|
+
var argv = p.argv || [];
|
|
54
|
+
var env = p.env || {};
|
|
55
|
+
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
56
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
57
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
58
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
59
|
+
};
|
|
60
|
+
var replaceClose = (string, close, replace, index) => {
|
|
61
|
+
let result = "", cursor = 0;
|
|
62
|
+
do {
|
|
63
|
+
result += string.substring(cursor, index) + replace;
|
|
64
|
+
cursor = index + close.length;
|
|
65
|
+
index = string.indexOf(close, cursor);
|
|
66
|
+
} while (~index);
|
|
67
|
+
return result + string.substring(cursor);
|
|
68
|
+
};
|
|
69
|
+
var createColors = (enabled = isColorSupported) => {
|
|
70
|
+
let f = enabled ? formatter : () => String;
|
|
71
|
+
return {
|
|
72
|
+
isColorSupported: enabled,
|
|
73
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
74
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
75
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
76
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
77
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
78
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
79
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
80
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
81
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
82
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
83
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
84
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
85
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
86
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
87
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
88
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
89
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
90
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
91
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
92
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
93
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
94
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
95
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
96
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
97
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
98
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
99
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
100
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
101
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
102
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
103
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
104
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
105
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
106
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
107
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
108
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
109
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
110
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
111
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
112
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
113
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
module.exports = createColors();
|
|
117
|
+
module.exports.createColors = createColors;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// src/cli/command-error.ts
|
|
121
|
+
function isCommandError(error) {
|
|
122
|
+
return error instanceof CommandError;
|
|
123
|
+
}
|
|
124
|
+
var COMMAND_ERROR_CODES, CommandError;
|
|
125
|
+
var init_command_error = __esm(() => {
|
|
126
|
+
COMMAND_ERROR_CODES = [
|
|
127
|
+
"NOT_LOGGED_IN",
|
|
128
|
+
"NO_ORG_SELECTED",
|
|
129
|
+
"NO_API_KEY",
|
|
130
|
+
"NO_LIBRARY_SELECTED",
|
|
131
|
+
"NO_DEPLOYMENT_SELECTED",
|
|
132
|
+
"ORG_UNAVAILABLE",
|
|
133
|
+
"LIBRARY_UNAVAILABLE",
|
|
134
|
+
"DEPLOYMENT_UNAVAILABLE",
|
|
135
|
+
"SCOPE_MISMATCH",
|
|
136
|
+
"DEPLOYMENT_NOT_FOUND",
|
|
137
|
+
"DEPLOYMENT_AMBIGUOUS",
|
|
138
|
+
"NOT_MCP_DEPLOYMENT",
|
|
139
|
+
"REVIEW_ITEM_NOT_FOUND",
|
|
140
|
+
"INVALID_ARGUMENT"
|
|
141
|
+
];
|
|
142
|
+
CommandError = class CommandError extends Error {
|
|
143
|
+
code;
|
|
144
|
+
details;
|
|
145
|
+
exitCode = 1;
|
|
146
|
+
constructor(code, message, details = []) {
|
|
147
|
+
super(message);
|
|
148
|
+
this.code = code;
|
|
149
|
+
this.details = details;
|
|
150
|
+
this.name = "CommandError";
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
|
|
50
155
|
// src/statusline/argv.ts
|
|
51
156
|
function agentFromArgv(argv) {
|
|
52
157
|
for (let i = 0;i < argv.length; i++) {
|
|
@@ -1006,76 +1111,6 @@ var init_config_helpers = __esm(() => {
|
|
|
1006
1111
|
writeFileAtomic = import_write_file_atomic.default;
|
|
1007
1112
|
});
|
|
1008
1113
|
|
|
1009
|
-
// node_modules/picocolors/picocolors.js
|
|
1010
|
-
var require_picocolors = __commonJS(function(exports, module) {
|
|
1011
|
-
var p = process || {};
|
|
1012
|
-
var argv = p.argv || [];
|
|
1013
|
-
var env = p.env || {};
|
|
1014
|
-
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
1015
|
-
var formatter = (open, close, replace = open) => (input) => {
|
|
1016
|
-
let string = "" + input, index = string.indexOf(close, open.length);
|
|
1017
|
-
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
1018
|
-
};
|
|
1019
|
-
var replaceClose = (string, close, replace, index) => {
|
|
1020
|
-
let result = "", cursor = 0;
|
|
1021
|
-
do {
|
|
1022
|
-
result += string.substring(cursor, index) + replace;
|
|
1023
|
-
cursor = index + close.length;
|
|
1024
|
-
index = string.indexOf(close, cursor);
|
|
1025
|
-
} while (~index);
|
|
1026
|
-
return result + string.substring(cursor);
|
|
1027
|
-
};
|
|
1028
|
-
var createColors = (enabled = isColorSupported) => {
|
|
1029
|
-
let f = enabled ? formatter : () => String;
|
|
1030
|
-
return {
|
|
1031
|
-
isColorSupported: enabled,
|
|
1032
|
-
reset: f("\x1B[0m", "\x1B[0m"),
|
|
1033
|
-
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
1034
|
-
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
1035
|
-
italic: f("\x1B[3m", "\x1B[23m"),
|
|
1036
|
-
underline: f("\x1B[4m", "\x1B[24m"),
|
|
1037
|
-
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
1038
|
-
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
1039
|
-
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
1040
|
-
black: f("\x1B[30m", "\x1B[39m"),
|
|
1041
|
-
red: f("\x1B[31m", "\x1B[39m"),
|
|
1042
|
-
green: f("\x1B[32m", "\x1B[39m"),
|
|
1043
|
-
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
1044
|
-
blue: f("\x1B[34m", "\x1B[39m"),
|
|
1045
|
-
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
1046
|
-
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
1047
|
-
white: f("\x1B[37m", "\x1B[39m"),
|
|
1048
|
-
gray: f("\x1B[90m", "\x1B[39m"),
|
|
1049
|
-
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
1050
|
-
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
1051
|
-
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
1052
|
-
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
1053
|
-
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
1054
|
-
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
1055
|
-
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
1056
|
-
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
1057
|
-
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
1058
|
-
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
1059
|
-
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
1060
|
-
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
1061
|
-
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
1062
|
-
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
1063
|
-
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
1064
|
-
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
1065
|
-
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
1066
|
-
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
1067
|
-
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
1068
|
-
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
1069
|
-
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
1070
|
-
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
1071
|
-
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
1072
|
-
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
1073
|
-
};
|
|
1074
|
-
};
|
|
1075
|
-
module.exports = createColors();
|
|
1076
|
-
module.exports.createColors = createColors;
|
|
1077
|
-
});
|
|
1078
|
-
|
|
1079
1114
|
// src/version/version.ts
|
|
1080
1115
|
function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
1081
1116
|
return channel === "npm" && (env.npm_lifecycle_event === "npx" || env.npm_command === "exec");
|
|
@@ -1083,7 +1118,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
1083
1118
|
function getVersionString() {
|
|
1084
1119
|
return `v${VERSION}`;
|
|
1085
1120
|
}
|
|
1086
|
-
var VERSION = "0.
|
|
1121
|
+
var VERSION = "0.67.1", INSTALL_CHANNEL = "npm";
|
|
1087
1122
|
|
|
1088
1123
|
// src/debug/logger.ts
|
|
1089
1124
|
import {
|
|
@@ -1173,18 +1208,18 @@ function writeEntry(level, mod, message) {
|
|
|
1173
1208
|
} catch {}
|
|
1174
1209
|
if (debugToConsole) {
|
|
1175
1210
|
const colorize = {
|
|
1176
|
-
DEBUG:
|
|
1177
|
-
INFO:
|
|
1178
|
-
WARN:
|
|
1179
|
-
ERROR:
|
|
1211
|
+
DEBUG: import_picocolors2.default.dim,
|
|
1212
|
+
INFO: import_picocolors2.default.cyan,
|
|
1213
|
+
WARN: import_picocolors2.default.yellow,
|
|
1214
|
+
ERROR: import_picocolors2.default.red
|
|
1180
1215
|
}[level];
|
|
1181
1216
|
console.error(colorize(line.trimEnd()));
|
|
1182
1217
|
}
|
|
1183
1218
|
}
|
|
1184
|
-
var
|
|
1219
|
+
var import_picocolors2, MAX_LOG_SIZE = 1048576, TRUNCATE_KEEP = 524288, LOG_FILENAME = "debug.log", REDACTED = "[REDACTED]", SECRET_QUERY_KEYS, initialized = false, debugToConsole = false, logFilePath = null, ANSI_PATTERN, logger;
|
|
1185
1220
|
var init_logger = __esm(() => {
|
|
1186
1221
|
init_config();
|
|
1187
|
-
|
|
1222
|
+
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
1188
1223
|
SECRET_QUERY_KEYS = [
|
|
1189
1224
|
"access_token",
|
|
1190
1225
|
"refresh_token",
|
|
@@ -7187,8 +7222,7 @@ var init_arguments = __esm(() => {
|
|
|
7187
7222
|
function requireLoginConfig() {
|
|
7188
7223
|
const cfg = loadConfig();
|
|
7189
7224
|
if (!cfg.active_account?.session.access_token) {
|
|
7190
|
-
|
|
7191
|
-
process.exit(1);
|
|
7225
|
+
throw new CommandError("NOT_LOGGED_IN", "Not logged in. Run 'dosu login' first.");
|
|
7192
7226
|
}
|
|
7193
7227
|
return cfg;
|
|
7194
7228
|
}
|
|
@@ -7196,22 +7230,20 @@ function requireOrgConfig() {
|
|
|
7196
7230
|
const cfg = requireLoginConfig();
|
|
7197
7231
|
const orgId = cfg.active_account?.target?.org_id;
|
|
7198
7232
|
if (!orgId) {
|
|
7199
|
-
|
|
7200
|
-
process.exit(1);
|
|
7233
|
+
throw new CommandError("NO_ORG_SELECTED", "Missing org config. Run 'dosu setup' to reconfigure.");
|
|
7201
7234
|
}
|
|
7202
7235
|
return { cfg, orgId };
|
|
7203
7236
|
}
|
|
7204
7237
|
function requireAPIKey(cfg) {
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7238
|
+
const apiKey = cfg.active_account?.target?.api_key;
|
|
7239
|
+
if (!apiKey) {
|
|
7240
|
+
throw new CommandError("NO_API_KEY", "API key not configured. Run 'dosu setup' first.");
|
|
7208
7241
|
}
|
|
7209
|
-
return
|
|
7242
|
+
return apiKey;
|
|
7210
7243
|
}
|
|
7211
|
-
var import_picocolors2;
|
|
7212
7244
|
var init_auth = __esm(() => {
|
|
7245
|
+
init_command_error();
|
|
7213
7246
|
init_config();
|
|
7214
|
-
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
7215
7247
|
});
|
|
7216
7248
|
|
|
7217
7249
|
// node_modules/fast-string-truncated-width/dist/utils.js
|
|
@@ -11430,8 +11462,16 @@ function requireConfig4() {
|
|
|
11430
11462
|
return requireLoginConfig();
|
|
11431
11463
|
}
|
|
11432
11464
|
async function listAccessibleDeployments(client, activeOrgId) {
|
|
11433
|
-
if (activeOrgId)
|
|
11434
|
-
|
|
11465
|
+
if (activeOrgId) {
|
|
11466
|
+
const deployments = await client.workspaces.listForOrg.query(activeOrgId);
|
|
11467
|
+
if (deployments.length > 0)
|
|
11468
|
+
return deployments;
|
|
11469
|
+
const orgs = await client.organization.getOrganizations.query({});
|
|
11470
|
+
if (!orgs.some((org) => org.org_id === activeOrgId)) {
|
|
11471
|
+
throw new CommandError("ORG_UNAVAILABLE", "The saved organization is not available to this account.", ["Run 'dosu setup' to choose an organization and MCP deployment."]);
|
|
11472
|
+
}
|
|
11473
|
+
return deployments;
|
|
11474
|
+
}
|
|
11435
11475
|
const orgs = await client.organization.getOrganizations.query({});
|
|
11436
11476
|
const deployments = await Promise.all(orgs.map((org) => client.workspaces.listForOrg.query(org.org_id)));
|
|
11437
11477
|
return deployments.flat();
|
|
@@ -11445,15 +11485,11 @@ async function resolveDeploymentId(client, activeOrgId, id) {
|
|
|
11445
11485
|
if (matches.length === 1)
|
|
11446
11486
|
return matches[0].deployment_id;
|
|
11447
11487
|
if (matches.length === 0) {
|
|
11448
|
-
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
}
|
|
11452
|
-
console.error(import_picocolors15.default.red(`Ambiguous deployment ID prefix: ${id} matches ${matches.length}:`));
|
|
11453
|
-
for (const d of matches) {
|
|
11454
|
-
console.error(import_picocolors15.default.dim(` ${d.deployment_id} ${d.name}`));
|
|
11488
|
+
throw new CommandError("DEPLOYMENT_NOT_FOUND", `Deployment not found: ${id}`, [
|
|
11489
|
+
"Expected a full deployment ID (UUID). Run 'dosu deployments list --json' to see full IDs."
|
|
11490
|
+
]);
|
|
11455
11491
|
}
|
|
11456
|
-
|
|
11492
|
+
throw new CommandError("DEPLOYMENT_AMBIGUOUS", `Ambiguous deployment ID prefix: ${id} matches ${matches.length}:`, matches.map((d) => ` ${d.deployment_id} ${d.name}`));
|
|
11457
11493
|
}
|
|
11458
11494
|
function deploymentsCommand() {
|
|
11459
11495
|
const cmd = new Command("deployments").description("Select the MCP deployment (and its Library) this CLI uses; not for Agents");
|
|
@@ -11484,14 +11520,12 @@ ${import_picocolors15.default.dim(`Current: ${cfg.active_account?.target?.deploy
|
|
|
11484
11520
|
cmd.command("info").description("Show the selected MCP deployment").option("--json", "Output as JSON").action(async (opts) => {
|
|
11485
11521
|
const cfg = requireConfig4();
|
|
11486
11522
|
if (!cfg.active_account?.target?.deployment_id) {
|
|
11487
|
-
|
|
11488
|
-
process.exit(1);
|
|
11523
|
+
throw new CommandError("NO_DEPLOYMENT_SELECTED", "No deployment selected. Run 'dosu setup' or 'dosu deployments switch'.");
|
|
11489
11524
|
}
|
|
11490
11525
|
const client = createTypedClient(cfg);
|
|
11491
11526
|
const deployment = await client.workspaces.get.query(cfg.active_account?.target?.deployment_id);
|
|
11492
11527
|
if (!deployment) {
|
|
11493
|
-
|
|
11494
|
-
process.exit(1);
|
|
11528
|
+
throw new CommandError("DEPLOYMENT_UNAVAILABLE", `Deployment not found: ${cfg.active_account?.target?.deployment_id}`);
|
|
11495
11529
|
}
|
|
11496
11530
|
if (opts.json) {
|
|
11497
11531
|
printResult(deployment, opts);
|
|
@@ -11514,12 +11548,10 @@ ${import_picocolors15.default.dim(`Current: ${cfg.active_account?.target?.deploy
|
|
|
11514
11548
|
const id = await resolveDeploymentId(client, cfg.active_account?.target?.org_id, rawId);
|
|
11515
11549
|
const deployment = await client.workspaces.get.query(id);
|
|
11516
11550
|
if (!deployment) {
|
|
11517
|
-
|
|
11518
|
-
process.exit(1);
|
|
11551
|
+
throw new CommandError("DEPLOYMENT_NOT_FOUND", `Deployment not found: ${id}`);
|
|
11519
11552
|
}
|
|
11520
11553
|
if (deployment.provider_slug !== MCP_PROVIDER_SLUG) {
|
|
11521
|
-
|
|
11522
|
-
process.exit(1);
|
|
11554
|
+
throw new CommandError("NOT_MCP_DEPLOYMENT", `Not a Dosu MCP deployment: ${id}`);
|
|
11523
11555
|
}
|
|
11524
11556
|
const apiKey = await new Client(cfg).createAPIKey(deployment.deployment_id, "dosu-cli");
|
|
11525
11557
|
updateTarget(cfg, {
|
|
@@ -11535,12 +11567,14 @@ ${import_picocolors15.default.dim(`Current: ${cfg.active_account?.target?.deploy
|
|
|
11535
11567
|
return;
|
|
11536
11568
|
}
|
|
11537
11569
|
console.log(import_picocolors15.default.green(`Switched to deployment: ${deployment.name}`));
|
|
11570
|
+
console.log(import_picocolors15.default.dim("This changes the CLI's saved selection. An AI tool with a running Dosu MCP connection " + "keeps its previous deployment until you run 'dosu mcp refresh' and restart or " + "reconnect it."));
|
|
11538
11571
|
});
|
|
11539
11572
|
return cmd;
|
|
11540
11573
|
}
|
|
11541
11574
|
var import_picocolors15, MCP_PROVIDER_SLUG = "dosu_mcp";
|
|
11542
11575
|
var init_deployments = __esm(() => {
|
|
11543
11576
|
init_commander();
|
|
11577
|
+
init_command_error();
|
|
11544
11578
|
init_client();
|
|
11545
11579
|
init_trpc();
|
|
11546
11580
|
init_config();
|
|
@@ -14289,7 +14323,7 @@ var init_conflicts = __esm(() => {
|
|
|
14289
14323
|
});
|
|
14290
14324
|
|
|
14291
14325
|
// src/telemetry/debug-id.ts
|
|
14292
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
14326
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "152ccbaa-13cc-83fc-6475-6e2164756e21";
|
|
14293
14327
|
|
|
14294
14328
|
// src/telemetry/telemetry.ts
|
|
14295
14329
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -15088,10 +15122,11 @@ function createCommandTelemetry(settings, dependencies = {}) {
|
|
|
15088
15122
|
};
|
|
15089
15123
|
}
|
|
15090
15124
|
function shouldSendToSentry(error) {
|
|
15091
|
-
return !
|
|
15125
|
+
return !EXPECTED_STATE_ERROR_CODES.has(error.code ?? "");
|
|
15092
15126
|
}
|
|
15093
|
-
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;
|
|
15127
|
+
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, EXPECTED_STATE_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;
|
|
15094
15128
|
var init_telemetry = __esm(() => {
|
|
15129
|
+
init_command_error();
|
|
15095
15130
|
init_conflicts();
|
|
15096
15131
|
MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
15097
15132
|
CLI_PACKAGE_ROOT = detectCliPackageRoot();
|
|
@@ -15172,7 +15207,13 @@ var init_telemetry = __esm(() => {
|
|
|
15172
15207
|
"commander.missingMandatoryOptionValue",
|
|
15173
15208
|
"commander.optionMissingArgument",
|
|
15174
15209
|
"commander.unknownCommand",
|
|
15175
|
-
"commander.unknownOption"
|
|
15210
|
+
"commander.unknownOption",
|
|
15211
|
+
...COMMAND_ERROR_CODES
|
|
15212
|
+
]);
|
|
15213
|
+
EXPECTED_STATE_ERROR_CODES = new Set([
|
|
15214
|
+
"SESSION_EXPIRED",
|
|
15215
|
+
"SESSION_PERSISTENCE_ERROR",
|
|
15216
|
+
...COMMAND_ERROR_CODES
|
|
15176
15217
|
]);
|
|
15177
15218
|
SYNC_TRIGGERS = new Set(["hook", "manual", "bootstrap"]);
|
|
15178
15219
|
SYNC_STATUSES = new Set([
|
|
@@ -60316,25 +60357,27 @@ function bareMessageId(id) {
|
|
|
60316
60357
|
function truncateId(id) {
|
|
60317
60358
|
return (isDraftId(id) ? bareMessageId(id) : id).slice(0, 8);
|
|
60318
60359
|
}
|
|
60360
|
+
function reviewItemNotFound(id) {
|
|
60361
|
+
return new CommandError("REVIEW_ITEM_NOT_FOUND", `No review item found for '${id}'. Run 'dosu review list' to see pending items.`);
|
|
60362
|
+
}
|
|
60319
60363
|
async function requireChange(client, id) {
|
|
60320
60364
|
try {
|
|
60321
60365
|
return await client.review.getChange.query({ id });
|
|
60322
60366
|
} catch (err) {
|
|
60323
|
-
if (isNotFound(err) || isInvalidId(err))
|
|
60324
|
-
|
|
60325
|
-
process.exit(1);
|
|
60326
|
-
}
|
|
60367
|
+
if (isNotFound(err) || isInvalidId(err))
|
|
60368
|
+
throw reviewItemNotFound(id);
|
|
60327
60369
|
throw err;
|
|
60328
60370
|
}
|
|
60329
60371
|
}
|
|
60330
60372
|
async function requireDraft(client, id) {
|
|
60331
60373
|
const draft = await client.messages.getMessage.query(bareMessageId(id));
|
|
60332
|
-
if (!draft)
|
|
60333
|
-
|
|
60334
|
-
process.exit(1);
|
|
60335
|
-
}
|
|
60374
|
+
if (!draft)
|
|
60375
|
+
throw reviewItemNotFound(id);
|
|
60336
60376
|
return draft;
|
|
60337
60377
|
}
|
|
60378
|
+
function invalidArgument(message) {
|
|
60379
|
+
return new CommandError("INVALID_ARGUMENT", message);
|
|
60380
|
+
}
|
|
60338
60381
|
function humanizeSource(origin, version) {
|
|
60339
60382
|
switch (origin) {
|
|
60340
60383
|
case "manual_update":
|
|
@@ -60386,46 +60429,95 @@ function printDraftPreview(draft) {
|
|
|
60386
60429
|
console.log();
|
|
60387
60430
|
console.log(draft.body ?? "");
|
|
60388
60431
|
}
|
|
60389
|
-
|
|
60390
|
-
|
|
60391
|
-
|
|
60392
|
-
|
|
60393
|
-
|
|
60432
|
+
function failScope(code, message, hint = SELECT_LIBRARY_HINT) {
|
|
60433
|
+
throw new CommandError(code, message, [hint]);
|
|
60434
|
+
}
|
|
60435
|
+
async function lookupLibrary(client, spaceId) {
|
|
60436
|
+
try {
|
|
60437
|
+
const library = await client.libraries.info.query(spaceId);
|
|
60438
|
+
return { found: true, name: library.name || null };
|
|
60439
|
+
} catch (err) {
|
|
60440
|
+
if (isNotFound(err))
|
|
60441
|
+
return { found: false };
|
|
60442
|
+
return { found: true, name: null };
|
|
60394
60443
|
}
|
|
60395
|
-
|
|
60444
|
+
}
|
|
60445
|
+
async function resolveReviewScope(client, spaceId, deploymentId) {
|
|
60446
|
+
const [store, library, deployment] = await Promise.all([
|
|
60447
|
+
client.knowledgeStore.getBySpaceId.query({ space_id: spaceId }),
|
|
60448
|
+
lookupLibrary(client, spaceId),
|
|
60449
|
+
deploymentId ? client.workspaces.get.query(deploymentId) : Promise.resolve(undefined)
|
|
60450
|
+
]);
|
|
60451
|
+
if (deploymentId && !deployment) {
|
|
60452
|
+
failScope("DEPLOYMENT_UNAVAILABLE", `The selected MCP deployment (${deploymentId}) is unavailable: it was deleted, or the ` + "signed-in account cannot access it.");
|
|
60453
|
+
}
|
|
60454
|
+
if (deployment && deployment.space_id !== spaceId) {
|
|
60455
|
+
failScope("SCOPE_MISMATCH", `The saved Library (${spaceId}) does not match the Library of the selected MCP ` + `deployment (${deployment.space_id}).`, `Run 'dosu deployments switch ${deployment.deployment_id}' to save that deployment's ` + "Library again, or choose another MCP deployment with 'dosu deployments list'.");
|
|
60456
|
+
}
|
|
60457
|
+
if (!library.found || !store) {
|
|
60458
|
+
failScope("LIBRARY_UNAVAILABLE", `The selected Library (${spaceId}) is unavailable: it was deleted, or the signed-in ` + "account cannot access it.");
|
|
60459
|
+
}
|
|
60460
|
+
return {
|
|
60461
|
+
knowledgeStoreId: store.id,
|
|
60462
|
+
library: { id: spaceId, name: library.name },
|
|
60463
|
+
deployment: deployment ? { id: deployment.deployment_id, name: deployment.name || null } : null
|
|
60464
|
+
};
|
|
60465
|
+
}
|
|
60466
|
+
function describeScopeEntry(entry) {
|
|
60467
|
+
return entry.name ? `${entry.name} (${entry.id})` : entry.id;
|
|
60468
|
+
}
|
|
60469
|
+
function printScope(scope) {
|
|
60470
|
+
printInfo([
|
|
60471
|
+
["Library", describeScopeEntry(scope.library)],
|
|
60472
|
+
[
|
|
60473
|
+
"MCP deployment",
|
|
60474
|
+
scope.deployment ? describeScopeEntry(scope.deployment) : "none selected (draft replies not listed)"
|
|
60475
|
+
]
|
|
60476
|
+
]);
|
|
60477
|
+
console.log();
|
|
60396
60478
|
}
|
|
60397
60479
|
function reviewCommand() {
|
|
60398
60480
|
const cmd = new Command("review").description("Review workflow (doc changes and draft replies)");
|
|
60399
|
-
cmd.command("list").description("List pending review items (doc changes and draft replies)").addOption(new Option("--since <when>", "Only items created at or after <when>: a duration back from now (24h, 7d, 2w), " + "a UTC date (2026-09-01), or an ISO-8601 datetime").argParser(timeBound)).addOption(new Option("--until <when>", "Only items created before <when> (same forms; a date includes that whole day)").argParser(timeBound)).option("--json", "Output as JSON").action(async (opts) => {
|
|
60481
|
+
cmd.command("list").description("List pending review items in the selected Library (doc changes and draft replies)").addOption(new Option("--since <when>", "Only items created at or after <when>: a duration back from now (24h, 7d, 2w), " + "a UTC date (2026-09-01), or an ISO-8601 datetime").argParser(timeBound)).addOption(new Option("--until <when>", "Only items created before <when> (same forms; a date includes that whole day)").argParser(timeBound)).option("--json", "Output as JSON").action(async (opts) => {
|
|
60400
60482
|
let range;
|
|
60401
60483
|
try {
|
|
60402
60484
|
range = resolveTimeRange(opts.since, opts.until);
|
|
60403
60485
|
} catch (err) {
|
|
60404
|
-
|
|
60405
|
-
process.exit(1);
|
|
60486
|
+
throw invalidArgument(`${err.message}.`);
|
|
60406
60487
|
}
|
|
60407
60488
|
const rangeLabel = describeTimeRange(range);
|
|
60408
60489
|
const inRange = rangeLabel ? ` ${rangeLabel}` : "";
|
|
60409
60490
|
const cfg = requireConfig10();
|
|
60410
|
-
|
|
60411
|
-
|
|
60412
|
-
|
|
60491
|
+
const target = cfg.active_account?.target;
|
|
60492
|
+
if (!target?.space_id) {
|
|
60493
|
+
failScope("NO_LIBRARY_SELECTED", "No Library selected. The review list reads the Library of the selected MCP deployment.");
|
|
60413
60494
|
}
|
|
60414
60495
|
const client = createTypedClient(cfg);
|
|
60415
|
-
const
|
|
60496
|
+
const scope = await resolveReviewScope(client, target.space_id, target.deployment_id);
|
|
60416
60497
|
const result = await client.review.listPending.query({
|
|
60417
|
-
knowledgeStoreId:
|
|
60418
|
-
deploymentId:
|
|
60498
|
+
knowledgeStoreId: scope.knowledgeStoreId,
|
|
60499
|
+
...scope.deployment && { deploymentId: scope.deployment.id },
|
|
60419
60500
|
...range.since && { since: range.since.toISOString() },
|
|
60420
60501
|
...range.until && { until: range.until.toISOString() }
|
|
60421
60502
|
});
|
|
60422
60503
|
const { items, truncated, total } = result;
|
|
60423
60504
|
if (opts.json) {
|
|
60424
|
-
printResult(
|
|
60505
|
+
printResult({
|
|
60506
|
+
...result,
|
|
60507
|
+
scope: {
|
|
60508
|
+
library: scope.library,
|
|
60509
|
+
deployment: scope.deployment,
|
|
60510
|
+
kinds: scope.deployment ? ["doc_change", "draft_message"] : ["doc_change"],
|
|
60511
|
+
since: range.since?.toISOString() ?? null,
|
|
60512
|
+
until: range.until?.toISOString() ?? null
|
|
60513
|
+
}
|
|
60514
|
+
}, opts);
|
|
60425
60515
|
return;
|
|
60426
60516
|
}
|
|
60517
|
+
printScope(scope);
|
|
60427
60518
|
if (!items || items.length === 0) {
|
|
60428
|
-
console.log(import_picocolors27.default.dim(`No pending review items${inRange}.`));
|
|
60519
|
+
console.log(import_picocolors27.default.dim(`No pending review items in this scope${inRange}.`));
|
|
60520
|
+
console.log(import_picocolors27.default.dim("Only the selected Library is listed. To review another Library, find its MCP " + "deployment with 'dosu deployments list' and select it with " + "'dosu deployments switch <deployment-id>'."));
|
|
60429
60521
|
return;
|
|
60430
60522
|
}
|
|
60431
60523
|
if (rangeLabel)
|
|
@@ -60479,30 +60571,22 @@ function reviewCommand() {
|
|
|
60479
60571
|
const cfg = requireConfig10();
|
|
60480
60572
|
const client = createTypedClient(cfg);
|
|
60481
60573
|
if (opts.body !== undefined && opts.bodyFile !== undefined) {
|
|
60482
|
-
|
|
60483
|
-
process.exit(1);
|
|
60574
|
+
throw invalidArgument("Pass only one of --body or --body-file.");
|
|
60484
60575
|
}
|
|
60485
60576
|
let body = opts.body;
|
|
60486
60577
|
if (opts.bodyFile) {
|
|
60487
60578
|
try {
|
|
60488
60579
|
body = readFileSync19(opts.bodyFile, "utf-8");
|
|
60489
60580
|
} catch (err) {
|
|
60490
|
-
|
|
60491
|
-
process.exit(1);
|
|
60581
|
+
throw invalidArgument(`Failed to read --body-file: ${err.message}`);
|
|
60492
60582
|
}
|
|
60493
60583
|
}
|
|
60494
60584
|
if (body === undefined && opts.title === undefined) {
|
|
60495
|
-
|
|
60496
|
-
process.exit(1);
|
|
60585
|
+
throw invalidArgument("Nothing to edit. Pass --title and/or --body/--body-file.");
|
|
60497
60586
|
}
|
|
60498
60587
|
if (isDraftId(id)) {
|
|
60499
|
-
if (opts.title !== undefined) {
|
|
60500
|
-
|
|
60501
|
-
process.exit(1);
|
|
60502
|
-
}
|
|
60503
|
-
if (body === undefined) {
|
|
60504
|
-
console.error(import_picocolors27.default.red("Draft replies require --body or --body-file."));
|
|
60505
|
-
process.exit(1);
|
|
60588
|
+
if (opts.title !== undefined || body === undefined) {
|
|
60589
|
+
throw invalidArgument("Draft replies support --body only (no --title).");
|
|
60506
60590
|
}
|
|
60507
60591
|
await requireDraft(client, id);
|
|
60508
60592
|
await client.messages.saveDraft.mutate({
|
|
@@ -60518,8 +60602,7 @@ function reviewCommand() {
|
|
|
60518
60602
|
});
|
|
60519
60603
|
} catch (err) {
|
|
60520
60604
|
if (isNotFound(err)) {
|
|
60521
|
-
|
|
60522
|
-
process.exit(1);
|
|
60605
|
+
throw new CommandError("REVIEW_ITEM_NOT_FOUND", `No pending review item found for '${id}'. Run 'dosu review list' to see editable items.`);
|
|
60523
60606
|
}
|
|
60524
60607
|
throw err;
|
|
60525
60608
|
}
|
|
@@ -60600,8 +60683,7 @@ function reviewCommand() {
|
|
|
60600
60683
|
const client = createTypedClient(cfg);
|
|
60601
60684
|
if (isDraftId(id)) {
|
|
60602
60685
|
await requireDraft(client, id);
|
|
60603
|
-
|
|
60604
|
-
process.exit(1);
|
|
60686
|
+
throw invalidArgument("Revert is not supported for draft replies. A rejected draft is regenerated on the next agent run.");
|
|
60605
60687
|
}
|
|
60606
60688
|
await requireChange(client, id);
|
|
60607
60689
|
await client.page.updatePublicationStatus.mutate({
|
|
@@ -60617,10 +60699,11 @@ function reviewCommand() {
|
|
|
60617
60699
|
cmd.addCommand(reviewNotificationsCommand());
|
|
60618
60700
|
return cmd;
|
|
60619
60701
|
}
|
|
60620
|
-
var import_picocolors27, DRAFT_MESSAGE_ID_PREFIX = "draft_message:";
|
|
60702
|
+
var import_picocolors27, DRAFT_MESSAGE_ID_PREFIX = "draft_message:", SELECT_LIBRARY_HINT;
|
|
60621
60703
|
var init_review = __esm(() => {
|
|
60622
60704
|
init_dist();
|
|
60623
60705
|
init_commander();
|
|
60706
|
+
init_command_error();
|
|
60624
60707
|
init_trpc();
|
|
60625
60708
|
init_auth();
|
|
60626
60709
|
init_confirmation();
|
|
@@ -60628,6 +60711,7 @@ var init_review = __esm(() => {
|
|
|
60628
60711
|
init_review_notifications();
|
|
60629
60712
|
init_time_range();
|
|
60630
60713
|
import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
60714
|
+
SELECT_LIBRARY_HINT = "Run 'dosu deployments list' to see the MCP deployments you can select, then " + "'dosu deployments switch <deployment-id>' for the Library to review, or run 'dosu setup' " + "to choose the organization and Library again.";
|
|
60631
60715
|
});
|
|
60632
60716
|
|
|
60633
60717
|
// src/generated/skills.ts
|
|
@@ -60713,7 +60797,7 @@ Use [commands.md](references/commands.md) as the sole detailed command and flag
|
|
|
60713
60797
|
## Handle failures literally
|
|
60714
60798
|
|
|
60715
60799
|
- \`Not logged in\` or an unrecoverable expired session: run \`dosu login\` (agent setup may instead return a ticket flow).
|
|
60716
|
-
- Missing organization, Library, deployment, or API-key context:
|
|
60800
|
+
- Missing or unavailable organization, Library, deployment, or API-key context: tell the user which \`dosu setup\` flow fixes it. Plain \`dosu setup\` is interactive, so don't start it for them unless they ask.
|
|
60717
60801
|
- Wrong or unexpected Library context: read \`dosu status --json\` and \`dosu deployments info --json\` before changing anything. Switch only to an MCP deployment the user named or confirmed; never pick the first one listed, and never switch just because a list came back empty.
|
|
60718
60802
|
- Skill guidance out of date: \`dosu skill update\` rewrites the installed skill from the running CLI version. Some agents read skills only when a session starts, so start a new session if the change does not appear. Installed files show the skill is on disk, not that the agent loaded it.
|
|
60719
60803
|
- \`confirmRequired\`: no write occurred.
|
|
@@ -61089,7 +61173,7 @@ dosu review notifications set (--library <library-id> | --agent <agent-id>)
|
|
|
61089
61173
|
dosu review notifications clear (--library <library-id> | --agent <agent-id>) [--confirm] [--json]
|
|
61090
61174
|
\`\`\`
|
|
61091
61175
|
|
|
61092
|
-
- \`list\` reads the selected Library's pending doc changes plus the selected MCP deployment's draft replies. JSON is \`{items, truncated, total}\`: at most 50 items, newest first; \`total\` is a lower bound when \`truncated\` is true. \`--since\`/\`--until\` take \`24h\`/\`7d\`/\`2w\`, a UTC date, or an ISO-8601 datetime.
|
|
61176
|
+
- \`list\` reads the selected Library's pending doc changes plus the selected MCP deployment's draft replies. JSON is \`{items, truncated, total, scope}\`: at most 50 items, newest first; \`total\` is a lower bound when \`truncated\` is true; \`scope\` names the Library and MCP deployment searched (see [review-workflow.md](review-workflow.md)). A missing, deleted, or inaccessible Library or deployment is an error, not an empty list. \`--since\`/\`--until\` take \`24h\`/\`7d\`/\`2w\`, a UTC date, or an ISO-8601 datetime.
|
|
61093
61177
|
- IDs are opaque: pass each \`id\` from \`list\` verbatim (draft replies carry a \`draft_message:\` prefix). \`revert\` takes a decided doc change's page-version ID and does not apply to drafts.
|
|
61094
61178
|
- \`edit\` requires at least one field; drafts accept only \`--body\`/\`--body-file\`. \`approve\` and \`reject\` do not write without interactive confirmation or \`--confirm\`.
|
|
61095
61179
|
- \`notifications\` manages the Slack channel that receives review notifications for one Library (doc reviews) or one Agent (its draft replies). Unlike the queue commands it takes an explicit target, not the selected MCP deployment. Pass exactly one of \`--library\`/\`--agent\` (UUID v4; Agent IDs come from \`dosu agents list\`).
|
|
@@ -61169,6 +61253,7 @@ dosu deployments switch <id> [--json]
|
|
|
61169
61253
|
|
|
61170
61254
|
dosu mcp list
|
|
61171
61255
|
dosu mcp add <agent> [--global] [--show-secret]
|
|
61256
|
+
dosu mcp refresh
|
|
61172
61257
|
dosu skill install | remove | update
|
|
61173
61258
|
dosu telemetry status [--json]
|
|
61174
61259
|
dosu telemetry enable | disable | reset
|
|
@@ -61177,7 +61262,7 @@ dosu upgrade [--auto on|off]
|
|
|
61177
61262
|
dosu logs [--tail [n]] [--clear]
|
|
61178
61263
|
\`\`\`
|
|
61179
61264
|
|
|
61180
|
-
\`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. The CLI updates itself in the background by default; a \`[dosu:update] Installing ...\` notice on stderr needs no action. \`upgrade --auto off\` turns that off.
|
|
61265
|
+
\`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`deployments switch\` does not repoint an AI tool's running MCP connection; \`mcp refresh\` rewrites the global Dosu MCP entry of each configured tool from the current selection (project-level entries change on the next \`dosu setup\` or \`dosu mcp add\`), and the tool then needs a restart or reconnect. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file. The CLI updates itself in the background by default; a \`[dosu:update] Installing ...\` notice on stderr needs no action. \`upgrade --auto off\` turns that off.
|
|
61181
61266
|
|
|
61182
61267
|
## Codebase audit
|
|
61183
61268
|
|
|
@@ -61192,7 +61277,7 @@ The coding agent writes the findings; Dosu generates the selected docs. Follow [
|
|
|
61192
61277
|
},
|
|
61193
61278
|
{
|
|
61194
61279
|
path: "references/review-workflow.md",
|
|
61195
|
-
content: '# Review workflow\n\nHow to work Dosu\'s review queue from the CLI: triage pending items, read the\ndiff, optionally edit, and apply a decision — safely.\n\nThe queue holds **document versions** (AI-generated, user-edited, synced from\nsource, or API-created) and **draft messages**, all surfaced through the same\n`dosu review` commands. Doc changes come from the selected Library; draft\nreplies come only from threads of the selected MCP deployment.\n\n## Read the list result\n\n`dosu review list --json` returns
|
|
61280
|
+
content: '# Review workflow\n\nHow to work Dosu\'s review queue from the CLI: triage pending items, read the\ndiff, optionally edit, and apply a decision — safely.\n\nThe queue holds **document versions** (AI-generated, user-edited, synced from\nsource, or API-created) and **draft messages**, all surfaced through the same\n`dosu review` commands. Doc changes come from the selected Library; draft\nreplies come only from threads of the selected MCP deployment.\n\n## Read the list result\n\n`dosu review list --json` returns\n`{ "items": [...], "truncated": <bool>, "total": <n>, "scope": {...} }`.\n\n- `items` holds at most 50 entries, newest first, doc changes and draft\n replies merged.\n- `truncated: true` means more pending items may exist than `items` shows.\n- `total` counts what the server found before that cap. When `truncated` is\n true it is a lower bound: report "at least `total`", never an exact backlog.\n- Each `id` is opaque. A doc change\'s `id` is its page-version UUID; a draft\n reply\'s `id` looks like `draft_message:<uuid>` and has `kind: "draft_message"`.\n Pass the `id` exactly as listed to `diff`, `edit`, `approve`, and `reject`;\n do not strip the prefix or shorten it.\n- `--since <when>` and `--until <when>` narrow the list by creation time. Each\n takes a duration back from now (`24h`, `7d`, `2w`), a UTC date\n (`2026-09-01`; an `--until` date includes that whole day), or an ISO-8601\n datetime. When `truncated` is true, `--until` reaches older items.\n\n`scope` says what was searched. It was added alongside the older fields,\nwhich keep their meaning:\n\n- `library`: `{ "id", "name" }` of the Library whose pending doc changes are\n listed.\n- `deployment`: `{ "id", "name" }` of the MCP deployment whose draft replies\n are listed, or `null` when none is saved. Then drafts are not listed.\n- `kinds`: the item kinds searched, `["doc_change", "draft_message"]` or\n `["doc_change"]`.\n- `since` / `until`: the resolved ISO-8601 bounds, or `null` when unbounded.\n\nA `name` is `null` when the server could not provide one; report the ID then\nand do not guess a name. Tell the user which Library the list covers.\n\nAn empty `items` array means no pending items in this scope. It is not a\nreason to switch deployments.\n\n`review list` checks the saved context before listing and fails (exit 1,\nnothing on stdout) instead of returning an empty list when:\n\n- `Not logged in`: run `dosu login`.\n- `No Library selected`: no Library is saved. Follow the context check below.\n- `... is unavailable`: the saved MCP deployment or Library was deleted, or\n the signed-in account cannot access it. Follow the context check below; if\n `dosu deployments list --json` returns nothing, the saved organization may\n be the inaccessible one, and `dosu setup` chooses it again.\n- `... does not match ...`: the saved Library is not the MCP deployment\'s\n Library. The message names the `dosu deployments switch` command that saves\n them together again; run it only after the user confirms.\n\n## Check the context when the scope looks wrong\n\nRun this only when the user says the list is for the wrong Library, names a\ndifferent Library, or a command reports missing context:\n\n1. `dosu status --json`: login state and the selected MCP deployment.\n2. `dosu deployments info --json`: the selected MCP deployment. The list reads\n the Library saved in the CLI\'s config, which `dosu setup` and\n `dosu deployments switch` set to this deployment\'s `space_id`\n (`dosu libraries info <space_id> --json` gives its name). A successful list\n already reports both in `scope`, and a saved Library that does not match\n the deployment\'s is an error.\n3. If that is not the Library the user means, run\n `dosu deployments list --json` and find the MCP deployment whose `space_id`\n matches it (`dosu libraries list --json` maps names to IDs).\n4. Switch only to a deployment the user named or confirmed:\n `dosu deployments switch <deployment-id> --json`. It changes the CLI\'s\n selection for later commands and mints a new API key, so say that it did.\n Never pick the first deployment, and ask when several match or none does.\n5. Run `dosu review list --json` again.\n\n`deployments switch` changes only the CLI\'s saved selection. An AI tool with a\nrunning Dosu MCP connection still points at its previous deployment until\n`dosu mcp refresh` rewrites its MCP entry and the tool restarts or reconnects.\nSay so after a switch; do not run `dosu mcp refresh` unless the user asks.\n\n## Draft reply limits\n\n- `edit` on a draft accepts `--body` or `--body-file` only (no `--title`).\n- `approve` publishes the draft to its thread; `reject` discards it.\n- Drafts have no `revert`. A rejected draft is regenerated on the next agent run.\n\n## Scope tool access for a review session\n\nApproving and rejecting are destructive and outward-facing. When you spin up an\nagent session dedicated to reviewing, scope it to just the review commands:\n\n```yaml\nallowed-tools: Bash(dosu review:*)\n```\n\nThis lets the agent triage, diff, and edit, but keeps it from running unrelated\nCLI commands during a review pass.\n\n## The flow\n\n```bash\n# 1. Triage — what\'s pending? Columns: ID, Kind, Title, Source, Status, Created.\ndosu review list --json\ndosu review list --since 7d --json # optional creation-time window\n\n# 2. Inspect — read the exact change before deciding anything.\ndosu review diff <id> --json\n\n# 3. (optional) Edit in place instead of rejecting a near-miss.\ndosu review edit <id> --body-file ./revised.md # or --body / --title (docs only)\n\n# 4. Decide — only on the item the user named, only after they OK it.\ndosu review approve <id> --confirm --json\ndosu review reject <id> --confirm --json\n\n# Undo a doc-change decision — back to pending (not for draft replies).\ndosu review revert <page-version-id> --json\n```\n\n### `--confirm` is mandatory for agents\n\n`approve` and `reject` only prompt interactively in a TTY *without* `--json`.\nThe skill always passes `--json`, which suppresses both the diff preview and\nthe prompt — so without `--confirm` the command changes nothing and returns\n`{ "applied": false, "confirmRequired": true }`. Run `dosu review diff <id>` to\nsee the change, then pass `--confirm` to apply — only after the user has\napproved that specific item.\n\n## Reading the `Source` column\n\n`Source` is the humanized `origin` field:\n\n| `origin` | Source | Meaning |\n|---|---|---|\n| `manual_update` | User created / User updated | A teammate authored or edited the doc |\n| `llm_generated` | AI generated | Dosu drafted the change |\n| `sync_upstream` | Synced from source | Came in from a connected source (Notion/Confluence/GitHub) |\n| `api_update` | Created via API | Pushed in programmatically |\n\n## Feeding PR / thread context\n\nA review often originates from a conversation thread (a GitHub issue, a Slack\nmessage, a sync-back PR). Pull that context before deciding:\n\n```bash\ndosu review context <thread-id> --json\n```\n\nIt returns the review `type`, the review/published page IDs, and — when the\nchange round-trips to an external system — a **Sync PR URL**. Use it to:\n\n- show the user where the change came from and where approval will land, and\n- read the originating discussion so the decision matches intent.\n\n## Safety rules\n\n- **Explicit item only.** Decide on the `id` the user named. "Review my queue"\n → run `list` and show it; never decide on their behalf.\n- **Listing is read-only.** A request to show the list authorizes no approve,\n reject, edit, API-key creation, or deployment switch.\n- **Diff before deciding.** Always `diff` and surface the change first.\n- **Never batch-accept.** No loop over `list` that approves everything. One\n item, one confirmation.\n- **Extra care for sync/PR origins.** `Synced from source` items and anything\n with a Sync PR URL push back to an upstream system on approval. Call it out\n and get explicit sign-off.\n',
|
|
61196
61281
|
executable: false
|
|
61197
61282
|
},
|
|
61198
61283
|
{
|
|
@@ -62328,7 +62413,7 @@ function requireConfig13() {
|
|
|
62328
62413
|
}
|
|
62329
62414
|
return cfg;
|
|
62330
62415
|
}
|
|
62331
|
-
async function
|
|
62416
|
+
async function getKnowledgeStoreId2(client, spaceId) {
|
|
62332
62417
|
const store = await client.knowledgeStore.getBySpaceId.query({
|
|
62333
62418
|
space_id: spaceId
|
|
62334
62419
|
});
|
|
@@ -62343,7 +62428,7 @@ function topicsCommand() {
|
|
|
62343
62428
|
cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
|
|
62344
62429
|
const cfg = requireConfig13();
|
|
62345
62430
|
const client = createTypedClient(cfg);
|
|
62346
|
-
const ksId = await
|
|
62431
|
+
const ksId = await getKnowledgeStoreId2(client, cfg.active_account.target.space_id);
|
|
62347
62432
|
const topics = await client.topic.listTopicsByKnowledgeStore.query({
|
|
62348
62433
|
knowledge_store_id: ksId
|
|
62349
62434
|
});
|
|
@@ -62364,7 +62449,7 @@ function topicsCommand() {
|
|
|
62364
62449
|
cmd.command("pages").description("List pages with a specific topic").argument("<topic-id>", "Topic ID").option("--search <query>", "Search within the topic's pages").addOption(new Option("--limit <n>", "Maximum results").argParser(positiveInteger).default(10)).option("--json", "Output as JSON").action(async (topicId, opts) => {
|
|
62365
62450
|
const cfg = requireConfig13();
|
|
62366
62451
|
const client = createTypedClient(cfg);
|
|
62367
|
-
const ksId = await
|
|
62452
|
+
const ksId = await getKnowledgeStoreId2(client, cfg.active_account.target.space_id);
|
|
62368
62453
|
const result = await client.topic.getPagesByTopicId.query({
|
|
62369
62454
|
knowledge_store_id: ksId,
|
|
62370
62455
|
topic_id: topicId,
|
|
@@ -66640,6 +66725,63 @@ var init_incognito_backfill_check = __esm(() => {
|
|
|
66640
66725
|
import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
66641
66726
|
});
|
|
66642
66727
|
|
|
66728
|
+
// src/cli/fatal-error.ts
|
|
66729
|
+
function read2(value, key) {
|
|
66730
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
66731
|
+
return;
|
|
66732
|
+
}
|
|
66733
|
+
try {
|
|
66734
|
+
return Reflect.get(value, key);
|
|
66735
|
+
} catch {
|
|
66736
|
+
return;
|
|
66737
|
+
}
|
|
66738
|
+
}
|
|
66739
|
+
function tokenOf2(data, key) {
|
|
66740
|
+
const value = read2(data, key);
|
|
66741
|
+
if (typeof value !== "string")
|
|
66742
|
+
return;
|
|
66743
|
+
const trimmed = value.trim();
|
|
66744
|
+
return REQUEST_ID_PATTERN2.test(trimmed) ? trimmed : undefined;
|
|
66745
|
+
}
|
|
66746
|
+
function statusOf2(data) {
|
|
66747
|
+
const value = read2(data, "httpStatus");
|
|
66748
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
|
|
66749
|
+
}
|
|
66750
|
+
function fatalErrorDiagnostics2(err) {
|
|
66751
|
+
const data = read2(err, "data");
|
|
66752
|
+
if (!data)
|
|
66753
|
+
return;
|
|
66754
|
+
const code = tokenOf2(data, "code");
|
|
66755
|
+
const path = tokenOf2(data, "path");
|
|
66756
|
+
const status = statusOf2(data);
|
|
66757
|
+
const requestId = tokenOf2(data, "requestId");
|
|
66758
|
+
const parts = [
|
|
66759
|
+
code && `code=${code}`,
|
|
66760
|
+
path && `path=${path}`,
|
|
66761
|
+
status && `status=${status}`,
|
|
66762
|
+
requestId && `request_id=${requestId}`
|
|
66763
|
+
].filter(Boolean);
|
|
66764
|
+
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
66765
|
+
}
|
|
66766
|
+
function printFatalError2(err) {
|
|
66767
|
+
if (isCommandError(err)) {
|
|
66768
|
+
console.error(import_picocolors39.default.red(err.message));
|
|
66769
|
+
for (const line of err.details)
|
|
66770
|
+
console.error(import_picocolors39.default.dim(line));
|
|
66771
|
+
return;
|
|
66772
|
+
}
|
|
66773
|
+
console.error(read2(err, "message") ?? err);
|
|
66774
|
+
const diagnostics = fatalErrorDiagnostics2(err);
|
|
66775
|
+
if (diagnostics)
|
|
66776
|
+
console.error(diagnostics);
|
|
66777
|
+
}
|
|
66778
|
+
var import_picocolors39, REQUEST_ID_PATTERN2;
|
|
66779
|
+
var init_fatal_error = __esm(() => {
|
|
66780
|
+
init_command_error();
|
|
66781
|
+
import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
66782
|
+
REQUEST_ID_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,127}$/;
|
|
66783
|
+
});
|
|
66784
|
+
|
|
66643
66785
|
// src/tui/analytics-view.ts
|
|
66644
66786
|
function analyticsListHeight(rows) {
|
|
66645
66787
|
const room = frameMaxLines(rows) - ANALYTICS_VIEW_CHROME_LINES;
|
|
@@ -66758,7 +66900,7 @@ function renderAnalyticsFrame(state, tab, scroll, pageStats = null, pagesPending
|
|
|
66758
66900
|
const rows = analyticsTabRows(tab, state, pageStats);
|
|
66759
66901
|
const { visible, above, below } = windowReport(rows, scroll, height);
|
|
66760
66902
|
const empty = tab === "overview" ? "No analytics yet. They appear after the first study run." : tab === "projects" ? "No per-project history yet. It fills in as sessions are studied." : pagesPending ? "Loading page analytics..." : "No page analytics yet.";
|
|
66761
|
-
const listRows = visible.length > 0 ? visible.map((row) =>
|
|
66903
|
+
const listRows = visible.length > 0 ? visible.map((row) => import_picocolors40.default.dim(row)) : [import_picocolors40.default.dim(empty)];
|
|
66762
66904
|
const scrollParts = [];
|
|
66763
66905
|
if (above > 0)
|
|
66764
66906
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -66774,9 +66916,9 @@ function renderAnalyticsFrame(state, tab, scroll, pageStats = null, pagesPending
|
|
|
66774
66916
|
], tab, width, { spread: false }),
|
|
66775
66917
|
"",
|
|
66776
66918
|
...listRows,
|
|
66777
|
-
...scrollParts.length > 0 ? [
|
|
66919
|
+
...scrollParts.length > 0 ? [import_picocolors40.default.dim(scrollParts.join(" · "))] : [],
|
|
66778
66920
|
"",
|
|
66779
|
-
|
|
66921
|
+
import_picocolors40.default.dim("tab switch · ↑↓ scroll · esc back")
|
|
66780
66922
|
];
|
|
66781
66923
|
return lines.join(`
|
|
66782
66924
|
`);
|
|
@@ -66873,7 +67015,7 @@ ${CLEAR_BELOW2}`);
|
|
|
66873
67015
|
input.on("data", onData);
|
|
66874
67016
|
});
|
|
66875
67017
|
}
|
|
66876
|
-
var
|
|
67018
|
+
var import_picocolors40, ESC8, HIDE_CURSOR4, SHOW_CURSOR4, CTRL_C5, KEY_UP5, KEY_DOWN5, KEY_RIGHT4, KEY_LEFT4, CURSOR_HOME2, CLEAR_BELOW2, CLEAR_EOL2, ANALYTICS_VIEW_POLL_MS = 1000, ANALYTICS_VIEW_LINES = 14, ANALYTICS_VIEW_CHROME_LINES = 8, ANALYTICS_VIEW_TABS, TOP_PAGES_LIMIT = 5, TOP_CITED_DAYS = 30, label = (text) => text.padEnd(26);
|
|
66877
67019
|
var init_analytics_view = __esm(() => {
|
|
66878
67020
|
init_trpc();
|
|
66879
67021
|
init_config();
|
|
@@ -66881,7 +67023,7 @@ var init_analytics_view = __esm(() => {
|
|
|
66881
67023
|
init_alt_screen();
|
|
66882
67024
|
init_layout();
|
|
66883
67025
|
init_menu();
|
|
66884
|
-
|
|
67026
|
+
import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
66885
67027
|
ESC8 = String.fromCharCode(27);
|
|
66886
67028
|
HIDE_CURSOR4 = `${ESC8}[?25l`;
|
|
66887
67029
|
SHOW_CURSOR4 = `${ESC8}[?25h`;
|
|
@@ -66899,7 +67041,7 @@ var init_analytics_view = __esm(() => {
|
|
|
66899
67041
|
// src/tui/banner.ts
|
|
66900
67042
|
function paintLogoRow(row) {
|
|
66901
67043
|
return row.map(([tone, art]) => {
|
|
66902
|
-
if (!
|
|
67044
|
+
if (!import_picocolors41.default.isColorSupported)
|
|
66903
67045
|
return art;
|
|
66904
67046
|
const { fg, fallback } = LOGO_TONES[tone];
|
|
66905
67047
|
return hasTruecolor() ? `${fg}${art}\x1B[39m` : fallback(art);
|
|
@@ -66930,14 +67072,14 @@ function wrapValue(text, room) {
|
|
|
66930
67072
|
}
|
|
66931
67073
|
function checklistRows(ctx, width) {
|
|
66932
67074
|
const on = brand(CHECK2);
|
|
66933
|
-
const off =
|
|
67075
|
+
const off = import_picocolors41.default.dim(CIRCLE);
|
|
66934
67076
|
const rows = [["workspace", ctx.directory]];
|
|
66935
67077
|
rows.push([
|
|
66936
67078
|
"account",
|
|
66937
|
-
ctx.sessionExpired ? `${off} ${
|
|
67079
|
+
ctx.sessionExpired ? `${off} ${import_picocolors41.default.yellow("session expired")} ${import_picocolors41.default.dim(`${DOT3} run Log in`)}` : ctx.signedIn ? `${on} signed in` : `${off} ${import_picocolors41.default.dim(`not signed in ${DOT3} run Setup`)}`
|
|
66938
67080
|
]);
|
|
66939
67081
|
const missing = new Set(ctx.setupMissing ?? []);
|
|
66940
|
-
const warnRow = `${off} ${
|
|
67082
|
+
const warnRow = `${off} ${import_picocolors41.default.yellow("not configured")} ${import_picocolors41.default.dim(`${DOT3} run Setup`)}`;
|
|
66941
67083
|
if (missing.has("MCP"))
|
|
66942
67084
|
rows.push(["mcp", warnRow]);
|
|
66943
67085
|
else if (ctx.deploymentName)
|
|
@@ -66949,7 +67091,7 @@ function checklistRows(ctx, width) {
|
|
|
66949
67091
|
if (ctx.repoAgentsMd) {
|
|
66950
67092
|
rows.push([
|
|
66951
67093
|
"repo",
|
|
66952
|
-
ctx.repoAgentsMd === "current" ? `${on} AGENTS.md has the Dosu section` : `${off} ${
|
|
67094
|
+
ctx.repoAgentsMd === "current" ? `${on} AGENTS.md has the Dosu section` : `${off} ${import_picocolors41.default.yellow(ctx.repoAgentsMd === "outdated" ? "AGENTS.md Dosu section outdated" : "AGENTS.md missing the Dosu section")} ${import_picocolors41.default.dim(`${DOT3} run Setup`)}`
|
|
66953
67095
|
]);
|
|
66954
67096
|
}
|
|
66955
67097
|
if (missing.has("agents"))
|
|
@@ -66961,20 +67103,20 @@ function checklistRows(ctx, width) {
|
|
|
66961
67103
|
if (ctx.studying) {
|
|
66962
67104
|
rows.push([
|
|
66963
67105
|
"sync",
|
|
66964
|
-
`\uD83D\uDCDA ${brand("studying sessions...")} ${
|
|
67106
|
+
`\uD83D\uDCDA ${brand("studying sessions...")} ${import_picocolors41.default.dim(`${DOT3} see activity`)}`
|
|
66965
67107
|
]);
|
|
66966
67108
|
}
|
|
66967
67109
|
if (ctx.update) {
|
|
66968
67110
|
rows.push([
|
|
66969
67111
|
"update",
|
|
66970
|
-
`${
|
|
67112
|
+
`${import_picocolors41.default.yellow(`↑ ${ctx.update.version} available`)} ${import_picocolors41.default.dim(`${DOT3} ${ctx.update.hint}`)}`
|
|
66971
67113
|
]);
|
|
66972
67114
|
}
|
|
66973
67115
|
const labelWidth = Math.max(...rows.map(([label]) => label.length));
|
|
66974
67116
|
const valueColumn = LOGO_WIDTH + COLUMN_GAP.length + labelWidth + LABEL_GAP.length;
|
|
66975
67117
|
const room = Math.max(1, width - valueColumn);
|
|
66976
67118
|
const indent = " ".repeat(labelWidth + LABEL_GAP.length);
|
|
66977
|
-
return rows.flatMap(([label, value]) => wrapValue(value, room).map((line, i) => i === 0 ? `${
|
|
67119
|
+
return rows.flatMap(([label, value]) => wrapValue(value, room).map((line, i) => i === 0 ? `${import_picocolors41.default.dim(label.padEnd(labelWidth))}${LABEL_GAP}${line}` : `${indent}${line}`));
|
|
66978
67120
|
}
|
|
66979
67121
|
function bannerWidth(columns = process.stdout.columns ?? 80) {
|
|
66980
67122
|
return columns - layoutMargin(columns) - 1;
|
|
@@ -66984,7 +67126,7 @@ function renderBanner(ctx, width = bannerWidth()) {
|
|
|
66984
67126
|
const text = [
|
|
66985
67127
|
...checklistRows(ctx, width),
|
|
66986
67128
|
"",
|
|
66987
|
-
`${brandBadge("dosu-cli")} ${
|
|
67129
|
+
`${brandBadge("dosu-cli")} ${import_picocolors41.default.dim(`${ctx.version} ${DOT3} ${ctx.webAppHost}`)}`
|
|
66988
67130
|
];
|
|
66989
67131
|
const height = Math.max(logo.length, text.length);
|
|
66990
67132
|
const combined = [];
|
|
@@ -66997,11 +67139,11 @@ function renderBanner(ctx, width = bannerWidth()) {
|
|
|
66997
67139
|
return ["", ...combined, ""].join(`
|
|
66998
67140
|
`);
|
|
66999
67141
|
}
|
|
67000
|
-
var
|
|
67142
|
+
var import_picocolors41, CHECK2 = "✔", CIRCLE = "○", DOT3 = "·", LOGO_ROWS, LOGO_MARK, LOGO_WIDTH, LOGO_TONES, COLUMN_GAP = " ", LABEL_GAP = " ", LIST_SEP;
|
|
67001
67143
|
var init_banner = __esm(() => {
|
|
67002
67144
|
init_styles();
|
|
67003
67145
|
init_layout();
|
|
67004
|
-
|
|
67146
|
+
import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
67005
67147
|
LOGO_ROWS = [
|
|
67006
67148
|
[["sage", "▄▄▄▄▄▄"]],
|
|
67007
67149
|
[["sage", "██ ▀▄"]],
|
|
@@ -67012,8 +67154,8 @@ var init_banner = __esm(() => {
|
|
|
67012
67154
|
LOGO_MARK = LOGO_ROWS.map((row) => row.map(([, art]) => art).join(""));
|
|
67013
67155
|
LOGO_WIDTH = Math.max(...LOGO_MARK.map((row) => row.length));
|
|
67014
67156
|
LOGO_TONES = {
|
|
67015
|
-
sage: { fg: "\x1B[38;2;180;187;145m", fallback:
|
|
67016
|
-
moss: { fg: "\x1B[38;2;119;133;97m", fallback: (art) =>
|
|
67157
|
+
sage: { fg: "\x1B[38;2;180;187;145m", fallback: import_picocolors41.default.green },
|
|
67158
|
+
moss: { fg: "\x1B[38;2;119;133;97m", fallback: (art) => import_picocolors41.default.dim(import_picocolors41.default.green(art)) }
|
|
67017
67159
|
};
|
|
67018
67160
|
LIST_SEP = ` ${DOT3} `;
|
|
67019
67161
|
});
|
|
@@ -67126,16 +67268,16 @@ function renderPagesFrame(model, width, selected) {
|
|
|
67126
67268
|
const body = [];
|
|
67127
67269
|
let scrollHint = "";
|
|
67128
67270
|
if (model.phase === "loading") {
|
|
67129
|
-
body.push(
|
|
67271
|
+
body.push(import_picocolors42.default.dim("Loading pages…"));
|
|
67130
67272
|
} else if (model.phase === "error") {
|
|
67131
|
-
body.push(
|
|
67273
|
+
body.push(import_picocolors42.default.yellow(clip3(model.message, width)));
|
|
67132
67274
|
} else if (model.pages.length === 0) {
|
|
67133
|
-
body.push(
|
|
67275
|
+
body.push(import_picocolors42.default.dim("No pages in this Library yet."));
|
|
67134
67276
|
} else {
|
|
67135
67277
|
const rows = pageRows2(model.pages, width - 2);
|
|
67136
67278
|
const { start, above } = windowSelection(rows.length, selected);
|
|
67137
67279
|
const visible = rows.slice(start, start + PAGES_VIEW_LINES);
|
|
67138
|
-
body.push(...visible.map((row, i) => start + i === selected ? `${brand("▸")} ${
|
|
67280
|
+
body.push(...visible.map((row, i) => start + i === selected ? `${brand("▸")} ${import_picocolors42.default.bold(row)}` : ` ${import_picocolors42.default.dim(row)}`));
|
|
67139
67281
|
const below = Math.max(0, Math.max(model.total, rows.length) - start - PAGES_VIEW_LINES);
|
|
67140
67282
|
const parts = [];
|
|
67141
67283
|
if (above > 0)
|
|
@@ -67144,14 +67286,14 @@ function renderPagesFrame(model, width, selected) {
|
|
|
67144
67286
|
parts.push(`↓ ${below} more`);
|
|
67145
67287
|
scrollHint = parts.join(" · ");
|
|
67146
67288
|
}
|
|
67147
|
-
const count = model.phase === "ready" ? ` ${
|
|
67289
|
+
const count = model.phase === "ready" ? ` ${import_picocolors42.default.dim(model.pages.length < model.total ? `(${model.pages.length} of ${model.total})` : `(${model.pages.length})`)}` : "";
|
|
67148
67290
|
const lines = [
|
|
67149
67291
|
`${breadcrumb(["home", "pages"], width)}${count}`,
|
|
67150
67292
|
"",
|
|
67151
67293
|
...body,
|
|
67152
|
-
...scrollHint ? [
|
|
67294
|
+
...scrollHint ? [import_picocolors42.default.dim(scrollHint)] : [],
|
|
67153
67295
|
"",
|
|
67154
|
-
|
|
67296
|
+
import_picocolors42.default.dim("↑↓ move · enter open · esc back")
|
|
67155
67297
|
];
|
|
67156
67298
|
return lines.join(`
|
|
67157
67299
|
`);
|
|
@@ -67160,9 +67302,9 @@ function renderPageFrame(page, content, width, scroll) {
|
|
|
67160
67302
|
const body = [];
|
|
67161
67303
|
let scrollHint = "";
|
|
67162
67304
|
if (content.phase === "loading") {
|
|
67163
|
-
body.push(
|
|
67305
|
+
body.push(import_picocolors42.default.dim("Loading page…"));
|
|
67164
67306
|
} else if (content.phase === "error") {
|
|
67165
|
-
body.push(
|
|
67307
|
+
body.push(import_picocolors42.default.yellow(clip3(content.message, width)));
|
|
67166
67308
|
} else {
|
|
67167
67309
|
const rows = wrapBody(content.body, width);
|
|
67168
67310
|
const { visible, above, below } = windowReport(rows, scroll, PAGE_BODY_LINES);
|
|
@@ -67177,12 +67319,12 @@ function renderPageFrame(page, content, width, scroll) {
|
|
|
67177
67319
|
const meta = `${page.type} · ${page.published ? "published" : "draft"} · updated ${page.updated_at.slice(0, 10)}`;
|
|
67178
67320
|
const lines = [
|
|
67179
67321
|
breadcrumb(["home", "pages", page.title], width),
|
|
67180
|
-
|
|
67322
|
+
import_picocolors42.default.dim(clip3(meta, width)),
|
|
67181
67323
|
"",
|
|
67182
67324
|
...body,
|
|
67183
|
-
...scrollHint ? [
|
|
67325
|
+
...scrollHint ? [import_picocolors42.default.dim(scrollHint)] : [],
|
|
67184
67326
|
"",
|
|
67185
|
-
|
|
67327
|
+
import_picocolors42.default.dim("↑↓ scroll · esc back to pages")
|
|
67186
67328
|
];
|
|
67187
67329
|
return lines.join(`
|
|
67188
67330
|
`);
|
|
@@ -67331,7 +67473,7 @@ ${CLEAR_BELOW3}`);
|
|
|
67331
67473
|
input.on("data", onData);
|
|
67332
67474
|
});
|
|
67333
67475
|
}
|
|
67334
|
-
var
|
|
67476
|
+
var import_picocolors42, ESC9, HIDE_CURSOR5, SHOW_CURSOR5, CTRL_C6, KEY_UP6, KEY_DOWN6, CURSOR_HOME3, CLEAR_BELOW3, CLEAR_EOL3, PAGES_VIEW_LINES = 12, PAGE_BODY_LINES = 14, PAGES_FETCH_BATCH = 100;
|
|
67335
67477
|
var init_pages_view = __esm(() => {
|
|
67336
67478
|
init_trpc();
|
|
67337
67479
|
init_config();
|
|
@@ -67341,7 +67483,7 @@ var init_pages_view = __esm(() => {
|
|
|
67341
67483
|
init_analytics_view();
|
|
67342
67484
|
init_layout();
|
|
67343
67485
|
init_menu();
|
|
67344
|
-
|
|
67486
|
+
import_picocolors42 = __toESM(require_picocolors(), 1);
|
|
67345
67487
|
ESC9 = String.fromCharCode(27);
|
|
67346
67488
|
HIDE_CURSOR5 = `${ESC9}[?25l`;
|
|
67347
67489
|
SHOW_CURSOR5 = `${ESC9}[?25h`;
|
|
@@ -67454,7 +67596,7 @@ function isSetUp(cfg) {
|
|
|
67454
67596
|
}
|
|
67455
67597
|
function setupHint(cfg) {
|
|
67456
67598
|
const started = Boolean(cfg.active_account?.target);
|
|
67457
|
-
return
|
|
67599
|
+
return import_picocolors43.default.yellow(started ? `incomplete · missing ${missingSetupSteps(cfg).join(" + ")}` : "not set up yet");
|
|
67458
67600
|
}
|
|
67459
67601
|
function isStudying() {
|
|
67460
67602
|
try {
|
|
@@ -67699,7 +67841,7 @@ function handleLogout(cfg) {
|
|
|
67699
67841
|
saveConfig(cfg);
|
|
67700
67842
|
log2.success("Credentials cleared.");
|
|
67701
67843
|
}
|
|
67702
|
-
var
|
|
67844
|
+
var import_picocolors43, ESC10, CLEAR_SCREEN;
|
|
67703
67845
|
var init_tui = __esm(() => {
|
|
67704
67846
|
init_client();
|
|
67705
67847
|
init_config();
|
|
@@ -67723,7 +67865,7 @@ var init_tui = __esm(() => {
|
|
|
67723
67865
|
init_menu();
|
|
67724
67866
|
init_pages_view();
|
|
67725
67867
|
init_prompts();
|
|
67726
|
-
|
|
67868
|
+
import_picocolors43 = __toESM(require_picocolors(), 1);
|
|
67727
67869
|
ESC10 = String.fromCharCode(27);
|
|
67728
67870
|
CLEAR_SCREEN = `${ESC10}[2J${ESC10}[H`;
|
|
67729
67871
|
});
|
|
@@ -68826,11 +68968,20 @@ async function execute() {
|
|
|
68826
68968
|
try {
|
|
68827
68969
|
await program.parseAsync(process.argv);
|
|
68828
68970
|
} catch (err) {
|
|
68971
|
+
printFatalError2(err);
|
|
68972
|
+
logFatalError(err);
|
|
68829
68973
|
if (telemetry)
|
|
68830
68974
|
await finishTelemetry(() => telemetry.fail(err));
|
|
68831
|
-
|
|
68975
|
+
process.exit(1);
|
|
68832
68976
|
}
|
|
68833
68977
|
}
|
|
68978
|
+
function logFatalError(err) {
|
|
68979
|
+
try {
|
|
68980
|
+
const message = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
|
|
68981
|
+
const diagnostics = fatalErrorDiagnostics2(err);
|
|
68982
|
+
logger.error("cli", diagnostics ? `${message} (${diagnostics})` : message);
|
|
68983
|
+
} catch {}
|
|
68984
|
+
}
|
|
68834
68985
|
function processCommandTelemetry() {
|
|
68835
68986
|
try {
|
|
68836
68987
|
const settings = loadTelemetrySettings();
|
|
@@ -68879,8 +69030,63 @@ var init_cli = __esm(() => {
|
|
|
68879
69030
|
init_skill_update_check();
|
|
68880
69031
|
init_update_check();
|
|
68881
69032
|
init_errors();
|
|
69033
|
+
init_fatal_error();
|
|
68882
69034
|
});
|
|
68883
69035
|
|
|
69036
|
+
// src/cli/fatal-error.ts
|
|
69037
|
+
init_command_error();
|
|
69038
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
69039
|
+
var REQUEST_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,127}$/;
|
|
69040
|
+
function read(value, key) {
|
|
69041
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
69042
|
+
return;
|
|
69043
|
+
}
|
|
69044
|
+
try {
|
|
69045
|
+
return Reflect.get(value, key);
|
|
69046
|
+
} catch {
|
|
69047
|
+
return;
|
|
69048
|
+
}
|
|
69049
|
+
}
|
|
69050
|
+
function tokenOf(data, key) {
|
|
69051
|
+
const value = read(data, key);
|
|
69052
|
+
if (typeof value !== "string")
|
|
69053
|
+
return;
|
|
69054
|
+
const trimmed = value.trim();
|
|
69055
|
+
return REQUEST_ID_PATTERN.test(trimmed) ? trimmed : undefined;
|
|
69056
|
+
}
|
|
69057
|
+
function statusOf(data) {
|
|
69058
|
+
const value = read(data, "httpStatus");
|
|
69059
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
|
|
69060
|
+
}
|
|
69061
|
+
function fatalErrorDiagnostics(err) {
|
|
69062
|
+
const data = read(err, "data");
|
|
69063
|
+
if (!data)
|
|
69064
|
+
return;
|
|
69065
|
+
const code = tokenOf(data, "code");
|
|
69066
|
+
const path = tokenOf(data, "path");
|
|
69067
|
+
const status = statusOf(data);
|
|
69068
|
+
const requestId = tokenOf(data, "requestId");
|
|
69069
|
+
const parts = [
|
|
69070
|
+
code && `code=${code}`,
|
|
69071
|
+
path && `path=${path}`,
|
|
69072
|
+
status && `status=${status}`,
|
|
69073
|
+
requestId && `request_id=${requestId}`
|
|
69074
|
+
].filter(Boolean);
|
|
69075
|
+
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
69076
|
+
}
|
|
69077
|
+
function printFatalError(err) {
|
|
69078
|
+
if (isCommandError(err)) {
|
|
69079
|
+
console.error(import_picocolors.default.red(err.message));
|
|
69080
|
+
for (const line of err.details)
|
|
69081
|
+
console.error(import_picocolors.default.dim(line));
|
|
69082
|
+
return;
|
|
69083
|
+
}
|
|
69084
|
+
console.error(read(err, "message") ?? err);
|
|
69085
|
+
const diagnostics = fatalErrorDiagnostics(err);
|
|
69086
|
+
if (diagnostics)
|
|
69087
|
+
console.error(diagnostics);
|
|
69088
|
+
}
|
|
69089
|
+
|
|
68884
69090
|
// src/statusline/argv.ts
|
|
68885
69091
|
var RENDER_ARGV = ["knowledge", "statusline", "render"];
|
|
68886
69092
|
function isStatuslineRenderArgv(argv) {
|
|
@@ -68899,17 +69105,8 @@ async function main() {
|
|
|
68899
69105
|
await execute();
|
|
68900
69106
|
}
|
|
68901
69107
|
main().catch((err) => {
|
|
68902
|
-
|
|
68903
|
-
const data = err?.data;
|
|
68904
|
-
if (data && (data.code || data.path || data.httpStatus)) {
|
|
68905
|
-
const parts = [
|
|
68906
|
-
data.code && `code=${data.code}`,
|
|
68907
|
-
data.path && `path=${data.path}`,
|
|
68908
|
-
data.httpStatus && `status=${data.httpStatus}`
|
|
68909
|
-
].filter(Boolean);
|
|
68910
|
-
console.error(parts.join(" "));
|
|
68911
|
-
}
|
|
69108
|
+
printFatalError(err);
|
|
68912
69109
|
process.exit(1);
|
|
68913
69110
|
});
|
|
68914
69111
|
|
|
68915
|
-
//# debugId=
|
|
69112
|
+
//# debugId=152ccbaa-13cc-83fc-6475-6e2164756e21
|