@hasna/coders 0.1.8 → 0.2.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/dist/cli.mjs +2042 -397
- package/dist/cli.mjs.map +4 -4
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -7548,7 +7548,7 @@ var init_settings = __esm({
|
|
|
7548
7548
|
alwaysThinkingEnabled: external_exports.boolean().optional(),
|
|
7549
7549
|
// Permissions
|
|
7550
7550
|
permissions: external_exports.object({
|
|
7551
|
-
defaultMode: external_exports.enum(["default", "plan", "acceptEdits", "dontAsk", "auto"]).optional(),
|
|
7551
|
+
defaultMode: external_exports.enum(["default", "plan", "acceptEdits", "dontAsk", "auto", "bypassPermissions"]).optional(),
|
|
7552
7552
|
allow: external_exports.array(PermissionRuleSchema).optional(),
|
|
7553
7553
|
deny: external_exports.array(PermissionRuleSchema).optional()
|
|
7554
7554
|
}).optional(),
|
|
@@ -7598,13 +7598,19 @@ var init_settings = __esm({
|
|
|
7598
7598
|
// Teammate mode
|
|
7599
7599
|
teammateMode: external_exports.enum(["auto", "tmux", "in-process"]).optional(),
|
|
7600
7600
|
// Remote control
|
|
7601
|
-
remoteControlAtStartup: external_exports.boolean().optional()
|
|
7601
|
+
remoteControlAtStartup: external_exports.boolean().optional(),
|
|
7602
|
+
// Custom status line — run an external command to render the status bar
|
|
7603
|
+
statusLine: external_exports.object({
|
|
7604
|
+
type: external_exports.literal("command"),
|
|
7605
|
+
command: external_exports.string(),
|
|
7606
|
+
padding: external_exports.number().optional()
|
|
7607
|
+
}).optional()
|
|
7602
7608
|
}).passthrough();
|
|
7603
7609
|
DEFAULT_SETTINGS = {
|
|
7604
7610
|
model: null,
|
|
7605
7611
|
alwaysThinkingEnabled: void 0,
|
|
7606
7612
|
permissions: {
|
|
7607
|
-
defaultMode: "
|
|
7613
|
+
defaultMode: "bypassPermissions",
|
|
7608
7614
|
allow: [],
|
|
7609
7615
|
deny: []
|
|
7610
7616
|
},
|
|
@@ -7653,16 +7659,6 @@ function getUserSettingsPath() {
|
|
|
7653
7659
|
function getUserConfigPath() {
|
|
7654
7660
|
return join(getConfigDir(), ".config.json");
|
|
7655
7661
|
}
|
|
7656
|
-
function getTeamsDir() {
|
|
7657
|
-
const dir = join(getConfigDir(), "teams");
|
|
7658
|
-
ensureDir(dir);
|
|
7659
|
-
return dir;
|
|
7660
|
-
}
|
|
7661
|
-
function getTasksDir() {
|
|
7662
|
-
const dir = join(getConfigDir(), "tasks");
|
|
7663
|
-
ensureDir(dir);
|
|
7664
|
-
return dir;
|
|
7665
|
-
}
|
|
7666
7662
|
function getPluginsDir() {
|
|
7667
7663
|
const dir = join(getConfigDir(), "plugins");
|
|
7668
7664
|
ensureDir(dir);
|
|
@@ -10168,7 +10164,7 @@ var require_react_development = __commonJS({
|
|
|
10168
10164
|
var dispatcher = resolveDispatcher();
|
|
10169
10165
|
return dispatcher.useReducer(reducer, initialArg, init);
|
|
10170
10166
|
}
|
|
10171
|
-
function
|
|
10167
|
+
function useRef2(initialValue) {
|
|
10172
10168
|
var dispatcher = resolveDispatcher();
|
|
10173
10169
|
return dispatcher.useRef(initialValue);
|
|
10174
10170
|
}
|
|
@@ -10962,7 +10958,7 @@ var require_react_development = __commonJS({
|
|
|
10962
10958
|
exports.useLayoutEffect = useLayoutEffect2;
|
|
10963
10959
|
exports.useMemo = useMemo3;
|
|
10964
10960
|
exports.useReducer = useReducer;
|
|
10965
|
-
exports.useRef =
|
|
10961
|
+
exports.useRef = useRef2;
|
|
10966
10962
|
exports.useState = useState3;
|
|
10967
10963
|
exports.useSyncExternalStore = useSyncExternalStore;
|
|
10968
10964
|
exports.useTransition = useTransition;
|
|
@@ -39039,7 +39035,7 @@ var require_backend = __commonJS({
|
|
|
39039
39035
|
return [initialArg, function() {
|
|
39040
39036
|
}];
|
|
39041
39037
|
},
|
|
39042
|
-
useRef: function
|
|
39038
|
+
useRef: function useRef2(initialValue) {
|
|
39043
39039
|
var hook = nextHook();
|
|
39044
39040
|
initialValue = null !== hook ? hook.memoizedState : {
|
|
39045
39041
|
current: initialValue
|
|
@@ -59191,6 +59187,73 @@ var init_models = __esm({
|
|
|
59191
59187
|
maxOutput: 32768,
|
|
59192
59188
|
supportsThinking: true,
|
|
59193
59189
|
supportsVision: true
|
|
59190
|
+
},
|
|
59191
|
+
// ── xAI Grok models ──────────────────────────────────────────────
|
|
59192
|
+
grok3: {
|
|
59193
|
+
alias: "grok3",
|
|
59194
|
+
variants: {
|
|
59195
|
+
firstParty: "grok-3",
|
|
59196
|
+
bedrock: "grok-3",
|
|
59197
|
+
vertex: "grok-3",
|
|
59198
|
+
xai: "grok-3"
|
|
59199
|
+
},
|
|
59200
|
+
contextWindow: 131072,
|
|
59201
|
+
maxOutput: 16384,
|
|
59202
|
+
supportsThinking: true,
|
|
59203
|
+
supportsVision: false
|
|
59204
|
+
},
|
|
59205
|
+
grok3mini: {
|
|
59206
|
+
alias: "grok3mini",
|
|
59207
|
+
variants: {
|
|
59208
|
+
firstParty: "grok-3-mini",
|
|
59209
|
+
bedrock: "grok-3-mini",
|
|
59210
|
+
vertex: "grok-3-mini",
|
|
59211
|
+
xai: "grok-3-mini"
|
|
59212
|
+
},
|
|
59213
|
+
contextWindow: 131072,
|
|
59214
|
+
maxOutput: 16384,
|
|
59215
|
+
supportsThinking: true,
|
|
59216
|
+
supportsVision: false
|
|
59217
|
+
},
|
|
59218
|
+
grok2: {
|
|
59219
|
+
alias: "grok2",
|
|
59220
|
+
variants: {
|
|
59221
|
+
firstParty: "grok-2",
|
|
59222
|
+
bedrock: "grok-2",
|
|
59223
|
+
vertex: "grok-2",
|
|
59224
|
+
xai: "grok-2"
|
|
59225
|
+
},
|
|
59226
|
+
contextWindow: 131072,
|
|
59227
|
+
maxOutput: 8192,
|
|
59228
|
+
supportsThinking: false,
|
|
59229
|
+
supportsVision: true
|
|
59230
|
+
},
|
|
59231
|
+
// ── Google Gemini models ──────────────────────────────────────────
|
|
59232
|
+
gemini25pro: {
|
|
59233
|
+
alias: "gemini25pro",
|
|
59234
|
+
variants: {
|
|
59235
|
+
firstParty: "gemini-2.5-pro",
|
|
59236
|
+
bedrock: "gemini-2.5-pro",
|
|
59237
|
+
vertex: "gemini-2.5-pro",
|
|
59238
|
+
gemini: "gemini-2.5-pro"
|
|
59239
|
+
},
|
|
59240
|
+
contextWindow: 1e6,
|
|
59241
|
+
maxOutput: 65536,
|
|
59242
|
+
supportsThinking: true,
|
|
59243
|
+
supportsVision: true
|
|
59244
|
+
},
|
|
59245
|
+
gemini25flash: {
|
|
59246
|
+
alias: "gemini25flash",
|
|
59247
|
+
variants: {
|
|
59248
|
+
firstParty: "gemini-2.5-flash",
|
|
59249
|
+
bedrock: "gemini-2.5-flash",
|
|
59250
|
+
vertex: "gemini-2.5-flash",
|
|
59251
|
+
gemini: "gemini-2.5-flash"
|
|
59252
|
+
},
|
|
59253
|
+
contextWindow: 1e6,
|
|
59254
|
+
maxOutput: 65536,
|
|
59255
|
+
supportsThinking: true,
|
|
59256
|
+
supportsVision: true
|
|
59194
59257
|
}
|
|
59195
59258
|
};
|
|
59196
59259
|
USER_ALIASES = {
|
|
@@ -59198,7 +59261,18 @@ var init_models = __esm({
|
|
|
59198
59261
|
sonnet: "sonnet46",
|
|
59199
59262
|
opus: "opus46",
|
|
59200
59263
|
"sonnet[1m]": "sonnet46",
|
|
59201
|
-
"opus[1m]": "opus46"
|
|
59264
|
+
"opus[1m]": "opus46",
|
|
59265
|
+
// xAI Grok aliases
|
|
59266
|
+
grok: "grok3",
|
|
59267
|
+
"grok-3": "grok3",
|
|
59268
|
+
"grok-3-mini": "grok3mini",
|
|
59269
|
+
"grok-2": "grok2",
|
|
59270
|
+
// Gemini aliases
|
|
59271
|
+
gemini: "gemini25pro",
|
|
59272
|
+
"gemini-pro": "gemini25pro",
|
|
59273
|
+
"gemini-flash": "gemini25flash",
|
|
59274
|
+
"gemini-2.5-pro": "gemini25pro",
|
|
59275
|
+
"gemini-2.5-flash": "gemini25flash"
|
|
59202
59276
|
};
|
|
59203
59277
|
}
|
|
59204
59278
|
});
|
|
@@ -59893,6 +59967,151 @@ var init_session = __esm({
|
|
|
59893
59967
|
}
|
|
59894
59968
|
});
|
|
59895
59969
|
|
|
59970
|
+
// src/core/background-tasks.ts
|
|
59971
|
+
var background_tasks_exports = {};
|
|
59972
|
+
__export(background_tasks_exports, {
|
|
59973
|
+
completeTask: () => completeTask,
|
|
59974
|
+
createTask: () => createTask,
|
|
59975
|
+
failTask: () => failTask,
|
|
59976
|
+
getAllTasks: () => getAllTasks,
|
|
59977
|
+
getOutputPath: () => getOutputPath,
|
|
59978
|
+
getRecentlyCompletedTasks: () => getRecentlyCompletedTasks,
|
|
59979
|
+
getRunningTasks: () => getRunningTasks,
|
|
59980
|
+
getTask: () => getTask,
|
|
59981
|
+
killTask: () => killTask,
|
|
59982
|
+
readTaskOutput: () => readTaskOutput,
|
|
59983
|
+
updateTask: () => updateTask,
|
|
59984
|
+
writeTaskOutput: () => writeTaskOutput
|
|
59985
|
+
});
|
|
59986
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4, appendFileSync, readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
|
|
59987
|
+
import { join as join6 } from "path";
|
|
59988
|
+
import { homedir as homedir2 } from "os";
|
|
59989
|
+
function ensureTasksDir() {
|
|
59990
|
+
try {
|
|
59991
|
+
mkdirSync5(TASKS_DIR, { recursive: true });
|
|
59992
|
+
} catch {
|
|
59993
|
+
}
|
|
59994
|
+
}
|
|
59995
|
+
function createTask(type, description) {
|
|
59996
|
+
const id = type === "bash" ? `bg-${nextBashId++}` : `agent-${nextAgentId++}`;
|
|
59997
|
+
ensureTasksDir();
|
|
59998
|
+
const outputPath = getOutputPath(id);
|
|
59999
|
+
const task = {
|
|
60000
|
+
id,
|
|
60001
|
+
type,
|
|
60002
|
+
description,
|
|
60003
|
+
status: "running",
|
|
60004
|
+
startTime: Date.now(),
|
|
60005
|
+
output: "",
|
|
60006
|
+
outputPath
|
|
60007
|
+
};
|
|
60008
|
+
if (type === "agent") {
|
|
60009
|
+
task.progress = { tokenCount: 0 };
|
|
60010
|
+
}
|
|
60011
|
+
tasks.set(id, task);
|
|
60012
|
+
try {
|
|
60013
|
+
writeFileSync4(outputPath, "", "utf-8");
|
|
60014
|
+
} catch {
|
|
60015
|
+
}
|
|
60016
|
+
return task;
|
|
60017
|
+
}
|
|
60018
|
+
function updateTask(id, updates) {
|
|
60019
|
+
const task = tasks.get(id);
|
|
60020
|
+
if (!task) return;
|
|
60021
|
+
Object.assign(task, updates);
|
|
60022
|
+
}
|
|
60023
|
+
function completeTask(id, output, exitCode) {
|
|
60024
|
+
const task = tasks.get(id);
|
|
60025
|
+
if (!task) return;
|
|
60026
|
+
task.status = "completed";
|
|
60027
|
+
task.output = output;
|
|
60028
|
+
task.exitCode = exitCode ?? null;
|
|
60029
|
+
task.endTime = Date.now();
|
|
60030
|
+
if (task.outputPath) {
|
|
60031
|
+
try {
|
|
60032
|
+
writeFileSync4(task.outputPath, output, "utf-8");
|
|
60033
|
+
} catch {
|
|
60034
|
+
}
|
|
60035
|
+
}
|
|
60036
|
+
}
|
|
60037
|
+
function failTask(id, error2) {
|
|
60038
|
+
const task = tasks.get(id);
|
|
60039
|
+
if (!task) return;
|
|
60040
|
+
task.status = "failed";
|
|
60041
|
+
task.error = error2;
|
|
60042
|
+
task.endTime = Date.now();
|
|
60043
|
+
if (task.outputPath) {
|
|
60044
|
+
try {
|
|
60045
|
+
appendFileSync(task.outputPath, `
|
|
60046
|
+
|
|
60047
|
+
--- ERROR ---
|
|
60048
|
+
${error2}
|
|
60049
|
+
`, "utf-8");
|
|
60050
|
+
} catch {
|
|
60051
|
+
}
|
|
60052
|
+
}
|
|
60053
|
+
}
|
|
60054
|
+
function killTask(id) {
|
|
60055
|
+
const task = tasks.get(id);
|
|
60056
|
+
if (!task) return;
|
|
60057
|
+
task.status = "killed";
|
|
60058
|
+
task.endTime = Date.now();
|
|
60059
|
+
}
|
|
60060
|
+
function getTask(id) {
|
|
60061
|
+
return tasks.get(id);
|
|
60062
|
+
}
|
|
60063
|
+
function getAllTasks() {
|
|
60064
|
+
return [...tasks.values()];
|
|
60065
|
+
}
|
|
60066
|
+
function getRunningTasks() {
|
|
60067
|
+
return [...tasks.values()].filter((t) => t.status === "running");
|
|
60068
|
+
}
|
|
60069
|
+
function getRecentlyCompletedTasks(withinMs = 6e4) {
|
|
60070
|
+
const cutoff = Date.now() - withinMs;
|
|
60071
|
+
return [...tasks.values()].filter(
|
|
60072
|
+
(t) => t.status !== "running" && t.endTime != null && t.endTime >= cutoff
|
|
60073
|
+
);
|
|
60074
|
+
}
|
|
60075
|
+
function getOutputPath(taskId) {
|
|
60076
|
+
return join6(TASKS_DIR, `${taskId}.output`);
|
|
60077
|
+
}
|
|
60078
|
+
function writeTaskOutput(taskId, chunk) {
|
|
60079
|
+
const task = tasks.get(taskId);
|
|
60080
|
+
if (!task) return;
|
|
60081
|
+
task.output += chunk;
|
|
60082
|
+
if (task.outputPath) {
|
|
60083
|
+
try {
|
|
60084
|
+
appendFileSync(task.outputPath, chunk, "utf-8");
|
|
60085
|
+
} catch {
|
|
60086
|
+
}
|
|
60087
|
+
}
|
|
60088
|
+
}
|
|
60089
|
+
function readTaskOutput(taskId) {
|
|
60090
|
+
const task = tasks.get(taskId);
|
|
60091
|
+
if (task?.output) {
|
|
60092
|
+
return task.output;
|
|
60093
|
+
}
|
|
60094
|
+
const path = getOutputPath(taskId);
|
|
60095
|
+
if (existsSync8(path)) {
|
|
60096
|
+
try {
|
|
60097
|
+
return readFileSync7(path, "utf-8");
|
|
60098
|
+
} catch {
|
|
60099
|
+
return "";
|
|
60100
|
+
}
|
|
60101
|
+
}
|
|
60102
|
+
return "";
|
|
60103
|
+
}
|
|
60104
|
+
var tasks, nextBashId, nextAgentId, TASKS_DIR;
|
|
60105
|
+
var init_background_tasks = __esm({
|
|
60106
|
+
"src/core/background-tasks.ts"() {
|
|
60107
|
+
"use strict";
|
|
60108
|
+
tasks = /* @__PURE__ */ new Map();
|
|
60109
|
+
nextBashId = 1;
|
|
60110
|
+
nextAgentId = 1;
|
|
60111
|
+
TASKS_DIR = join6(homedir2(), ".coders", "tasks");
|
|
60112
|
+
}
|
|
60113
|
+
});
|
|
60114
|
+
|
|
59896
60115
|
// src/ui/screen/terminal.ts
|
|
59897
60116
|
var terminal_exports = {};
|
|
59898
60117
|
__export(terminal_exports, {
|
|
@@ -60018,8 +60237,82 @@ var init_terminal = __esm({
|
|
|
60018
60237
|
}
|
|
60019
60238
|
});
|
|
60020
60239
|
|
|
60240
|
+
// src/ui/themes.ts
|
|
60241
|
+
var themes_exports = {};
|
|
60242
|
+
__export(themes_exports, {
|
|
60243
|
+
DARK_THEME: () => DARK_THEME,
|
|
60244
|
+
DEFAULT_THEME: () => DEFAULT_THEME,
|
|
60245
|
+
LIGHT_THEME: () => LIGHT_THEME,
|
|
60246
|
+
getAvailableThemes: () => getAvailableThemes,
|
|
60247
|
+
getTheme: () => getTheme
|
|
60248
|
+
});
|
|
60249
|
+
function getTheme(name) {
|
|
60250
|
+
return THEMES[name] ?? DEFAULT_THEME;
|
|
60251
|
+
}
|
|
60252
|
+
function getAvailableThemes() {
|
|
60253
|
+
return Object.keys(THEMES);
|
|
60254
|
+
}
|
|
60255
|
+
var DEFAULT_THEME, DARK_THEME, LIGHT_THEME, THEMES;
|
|
60256
|
+
var init_themes = __esm({
|
|
60257
|
+
"src/ui/themes.ts"() {
|
|
60258
|
+
"use strict";
|
|
60259
|
+
DEFAULT_THEME = {
|
|
60260
|
+
name: "default",
|
|
60261
|
+
colors: {
|
|
60262
|
+
primary: "cyan",
|
|
60263
|
+
secondary: "blue",
|
|
60264
|
+
success: "green",
|
|
60265
|
+
error: "red",
|
|
60266
|
+
warning: "yellow",
|
|
60267
|
+
info: "blue",
|
|
60268
|
+
muted: "gray",
|
|
60269
|
+
plan: "magenta",
|
|
60270
|
+
tool: "yellow",
|
|
60271
|
+
thinking: "gray"
|
|
60272
|
+
}
|
|
60273
|
+
};
|
|
60274
|
+
DARK_THEME = {
|
|
60275
|
+
name: "dark",
|
|
60276
|
+
colors: {
|
|
60277
|
+
primary: "#61afef",
|
|
60278
|
+
secondary: "#c678dd",
|
|
60279
|
+
success: "#98c379",
|
|
60280
|
+
error: "#e06c75",
|
|
60281
|
+
warning: "#e5c07b",
|
|
60282
|
+
info: "#56b6c2",
|
|
60283
|
+
muted: "#5c6370",
|
|
60284
|
+
plan: "#c678dd",
|
|
60285
|
+
tool: "#e5c07b",
|
|
60286
|
+
thinking: "#5c6370"
|
|
60287
|
+
}
|
|
60288
|
+
};
|
|
60289
|
+
LIGHT_THEME = {
|
|
60290
|
+
name: "light",
|
|
60291
|
+
colors: {
|
|
60292
|
+
primary: "#0184bc",
|
|
60293
|
+
secondary: "#a626a4",
|
|
60294
|
+
success: "#50a14f",
|
|
60295
|
+
error: "#e45649",
|
|
60296
|
+
warning: "#c18401",
|
|
60297
|
+
info: "#0184bc",
|
|
60298
|
+
muted: "#a0a1a7",
|
|
60299
|
+
plan: "#a626a4",
|
|
60300
|
+
tool: "#c18401",
|
|
60301
|
+
thinking: "#a0a1a7"
|
|
60302
|
+
}
|
|
60303
|
+
};
|
|
60304
|
+
THEMES = {
|
|
60305
|
+
default: DEFAULT_THEME,
|
|
60306
|
+
dark: DARK_THEME,
|
|
60307
|
+
light: LIGHT_THEME
|
|
60308
|
+
};
|
|
60309
|
+
}
|
|
60310
|
+
});
|
|
60311
|
+
|
|
60021
60312
|
// src/core/slash-commands.ts
|
|
60022
|
-
import { writeFileSync as
|
|
60313
|
+
import { writeFileSync as writeFileSync5, existsSync as existsSync9, readdirSync as readdirSync2 } from "fs";
|
|
60314
|
+
import { join as join7 } from "path";
|
|
60315
|
+
import { execSync as execSync3 } from "child_process";
|
|
60023
60316
|
function registerSlashCommand(cmd) {
|
|
60024
60317
|
commands.set(cmd.name, cmd);
|
|
60025
60318
|
if (cmd.aliases) {
|
|
@@ -60070,8 +60363,12 @@ ${lines.join("\n")}` };
|
|
|
60070
60363
|
registerSlashCommand({
|
|
60071
60364
|
name: "compact",
|
|
60072
60365
|
category: "core",
|
|
60073
|
-
description: "Compact conversation context",
|
|
60074
|
-
handler: () => ({
|
|
60366
|
+
description: "Compact conversation context [instructions]",
|
|
60367
|
+
handler: (args) => ({
|
|
60368
|
+
action: "compact",
|
|
60369
|
+
data: args.trim() || void 0,
|
|
60370
|
+
output: args.trim() ? `Context compacted with instructions: ${args.trim()}` : "Context compacted."
|
|
60371
|
+
})
|
|
60075
60372
|
});
|
|
60076
60373
|
registerSlashCommand({
|
|
60077
60374
|
name: "exit",
|
|
@@ -60091,15 +60388,15 @@ ${lines.join("\n")}` };
|
|
|
60091
60388
|
category: "mode",
|
|
60092
60389
|
description: "View or change the current model",
|
|
60093
60390
|
handler: (args) => {
|
|
60094
|
-
if (args) return { action: "
|
|
60391
|
+
if (args) return { action: "model", data: args.trim(), output: `Model set to: ${args.trim()}` };
|
|
60095
60392
|
return { output: "Current model \u2014 use /model <name> to change." };
|
|
60096
60393
|
}
|
|
60097
60394
|
});
|
|
60098
60395
|
registerSlashCommand({
|
|
60099
60396
|
name: "fast",
|
|
60100
60397
|
category: "mode",
|
|
60101
|
-
description: "Toggle fast mode",
|
|
60102
|
-
handler: () => ({ output: "Fast mode toggled." })
|
|
60398
|
+
description: "Toggle fast mode (switch between current model and haiku)",
|
|
60399
|
+
handler: () => ({ action: "fast", output: "Fast mode toggled." })
|
|
60103
60400
|
});
|
|
60104
60401
|
registerSlashCommand({
|
|
60105
60402
|
name: "verbose",
|
|
@@ -60135,14 +60432,44 @@ ${lines.join("\n")}` };
|
|
|
60135
60432
|
name: "tasks",
|
|
60136
60433
|
aliases: ["todo", "todos"],
|
|
60137
60434
|
category: "task",
|
|
60138
|
-
description: "
|
|
60139
|
-
handler: () =>
|
|
60435
|
+
description: "List all background tasks with their status",
|
|
60436
|
+
handler: () => {
|
|
60437
|
+
try {
|
|
60438
|
+
const { getAllTasks: getAllTasks2 } = (init_background_tasks(), __toCommonJS(background_tasks_exports));
|
|
60439
|
+
const tasks2 = getAllTasks2();
|
|
60440
|
+
if (tasks2.length === 0) return { output: "No background tasks." };
|
|
60441
|
+
const lines = tasks2.map((t) => {
|
|
60442
|
+
const elapsed = t.endTime ? `${((t.endTime - t.startTime) / 1e3).toFixed(1)}s` : `${((Date.now() - t.startTime) / 1e3).toFixed(1)}s`;
|
|
60443
|
+
const status = t.status === "running" ? "running" : t.status === "completed" ? "done" : t.status;
|
|
60444
|
+
return ` ${t.id.padEnd(12)} ${status.padEnd(10)} ${elapsed.padEnd(8)} ${t.description}`;
|
|
60445
|
+
});
|
|
60446
|
+
return { output: `Background tasks:
|
|
60447
|
+
${"ID".padEnd(12)} ${"Status".padEnd(10)} ${"Time".padEnd(8)} Description
|
|
60448
|
+
${lines.join("\n")}` };
|
|
60449
|
+
} catch {
|
|
60450
|
+
return { output: "No background tasks." };
|
|
60451
|
+
}
|
|
60452
|
+
}
|
|
60140
60453
|
});
|
|
60141
60454
|
registerSlashCommand({
|
|
60142
60455
|
name: "diff",
|
|
60143
60456
|
category: "git",
|
|
60144
|
-
description: "Show git
|
|
60145
|
-
handler: () =>
|
|
60457
|
+
description: "Show uncommitted git changes",
|
|
60458
|
+
handler: () => {
|
|
60459
|
+
try {
|
|
60460
|
+
const unstaged = execSync3("git diff", { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
60461
|
+
const staged = execSync3("git diff --cached", { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
60462
|
+
const parts = [];
|
|
60463
|
+
if (staged) parts.push(`\u2500\u2500 Staged changes \u2500\u2500
|
|
60464
|
+
${staged}`);
|
|
60465
|
+
if (unstaged) parts.push(`\u2500\u2500 Unstaged changes \u2500\u2500
|
|
60466
|
+
${unstaged}`);
|
|
60467
|
+
if (parts.length === 0) return { output: "No uncommitted changes." };
|
|
60468
|
+
return { output: parts.join("\n\n") };
|
|
60469
|
+
} catch (e) {
|
|
60470
|
+
return { output: `Failed to get diff: ${e instanceof Error ? e.message : String(e)}` };
|
|
60471
|
+
}
|
|
60472
|
+
}
|
|
60146
60473
|
});
|
|
60147
60474
|
registerSlashCommand({
|
|
60148
60475
|
name: "pr",
|
|
@@ -60207,7 +60534,7 @@ ${lines.join("\n")}` };
|
|
|
60207
60534
|
if (!isNaN(choice) && choice >= 1 && choice <= checkpoints.length) {
|
|
60208
60535
|
const cp = checkpoints[choice - 1];
|
|
60209
60536
|
try {
|
|
60210
|
-
|
|
60537
|
+
writeFileSync5(cp.file_path, cp.original_content, "utf-8");
|
|
60211
60538
|
const op = cp.edit_operation ? JSON.parse(cp.edit_operation) : null;
|
|
60212
60539
|
const summary = op?.old_string ? `Reverted edit: "${truncate(op.old_string, 40)}" -> "${truncate(op.new_string, 40)}"` : "Restored original content";
|
|
60213
60540
|
return { output: `Restored checkpoint #${choice}: ${cp.file_path}
|
|
@@ -60306,6 +60633,181 @@ Use /restore latest or /restore <number> or /restore <id-prefix>`
|
|
|
60306
60633
|
return { output: `No checkpoint found matching "${arg}". Use /restore to list available checkpoints.` };
|
|
60307
60634
|
}
|
|
60308
60635
|
});
|
|
60636
|
+
registerSlashCommand({
|
|
60637
|
+
name: "cost",
|
|
60638
|
+
category: "system",
|
|
60639
|
+
description: "Show session cost, token usage, and duration",
|
|
60640
|
+
handler: () => {
|
|
60641
|
+
const sessionId = getCurrentSessionId();
|
|
60642
|
+
if (!sessionId) return { output: "No active session." };
|
|
60643
|
+
try {
|
|
60644
|
+
const row = dbGet(
|
|
60645
|
+
`SELECT created_at,
|
|
60646
|
+
COALESCE(SUM(tokens_in), 0) AS total_in,
|
|
60647
|
+
COALESCE(SUM(tokens_out), 0) AS total_out,
|
|
60648
|
+
COALESCE(SUM(cost_usd), 0) AS total_cost
|
|
60649
|
+
FROM messages WHERE session_id = ?`,
|
|
60650
|
+
[sessionId]
|
|
60651
|
+
);
|
|
60652
|
+
const session = dbGet(`SELECT created_at FROM sessions WHERE id = ?`, [sessionId]);
|
|
60653
|
+
const startTime = session?.created_at ? new Date(session.created_at).getTime() : Date.now();
|
|
60654
|
+
const durationMs = Date.now() - startTime;
|
|
60655
|
+
const durationMin = Math.floor(durationMs / 6e4);
|
|
60656
|
+
const durationSec = Math.floor(durationMs % 6e4 / 1e3);
|
|
60657
|
+
const totalIn = row?.total_in ?? 0;
|
|
60658
|
+
const totalOut = row?.total_out ?? 0;
|
|
60659
|
+
const totalCost = row?.total_cost ?? 0;
|
|
60660
|
+
const lines = [
|
|
60661
|
+
`Session cost:`,
|
|
60662
|
+
` Duration: ${durationMin}m ${durationSec}s`,
|
|
60663
|
+
` Input tokens: ${totalIn.toLocaleString()}`,
|
|
60664
|
+
` Output tokens: ${totalOut.toLocaleString()}`,
|
|
60665
|
+
` Total tokens: ${(totalIn + totalOut).toLocaleString()}`,
|
|
60666
|
+
` Total cost: $${totalCost.toFixed(4)}`
|
|
60667
|
+
];
|
|
60668
|
+
return { output: lines.join("\n") };
|
|
60669
|
+
} catch (e) {
|
|
60670
|
+
return { output: `Failed to get cost info: ${e instanceof Error ? e.message : String(e)}` };
|
|
60671
|
+
}
|
|
60672
|
+
}
|
|
60673
|
+
});
|
|
60674
|
+
registerSlashCommand({
|
|
60675
|
+
name: "files",
|
|
60676
|
+
category: "system",
|
|
60677
|
+
description: "List files read/written in this session",
|
|
60678
|
+
handler: () => {
|
|
60679
|
+
const sessionId = getCurrentSessionId();
|
|
60680
|
+
if (!sessionId) return { output: "No active session." };
|
|
60681
|
+
try {
|
|
60682
|
+
const rows = dbAll(
|
|
60683
|
+
`SELECT DISTINCT file_path, edit_operation FROM checkpoints WHERE session_id = ? OR 1=1 ORDER BY created_at DESC LIMIT 50`
|
|
60684
|
+
);
|
|
60685
|
+
const msgRows = dbAll(
|
|
60686
|
+
`SELECT tool_uses FROM messages WHERE session_id = ? AND tool_uses IS NOT NULL`,
|
|
60687
|
+
[sessionId]
|
|
60688
|
+
);
|
|
60689
|
+
const filesRead = /* @__PURE__ */ new Set();
|
|
60690
|
+
const filesWritten = /* @__PURE__ */ new Set();
|
|
60691
|
+
for (const r of msgRows) {
|
|
60692
|
+
try {
|
|
60693
|
+
const uses = JSON.parse(r.tool_uses);
|
|
60694
|
+
if (Array.isArray(uses)) {
|
|
60695
|
+
for (const u of uses) {
|
|
60696
|
+
if (u.name === "Read" && u.input?.file_path) filesRead.add(u.input.file_path);
|
|
60697
|
+
if ((u.name === "Edit" || u.name === "Write") && u.input?.file_path) filesWritten.add(u.input.file_path);
|
|
60698
|
+
}
|
|
60699
|
+
}
|
|
60700
|
+
} catch {
|
|
60701
|
+
}
|
|
60702
|
+
}
|
|
60703
|
+
const parts = [];
|
|
60704
|
+
if (filesRead.size > 0) {
|
|
60705
|
+
parts.push(`Files read (${filesRead.size}):
|
|
60706
|
+
${Array.from(filesRead).map((f) => ` ${f}`).join("\n")}`);
|
|
60707
|
+
}
|
|
60708
|
+
if (filesWritten.size > 0) {
|
|
60709
|
+
parts.push(`Files written (${filesWritten.size}):
|
|
60710
|
+
${Array.from(filesWritten).map((f) => ` ${f}`).join("\n")}`);
|
|
60711
|
+
}
|
|
60712
|
+
if (parts.length === 0) return { output: "No files tracked in this session." };
|
|
60713
|
+
return { output: parts.join("\n\n") };
|
|
60714
|
+
} catch (e) {
|
|
60715
|
+
return { output: `Failed to list files: ${e instanceof Error ? e.message : String(e)}` };
|
|
60716
|
+
}
|
|
60717
|
+
}
|
|
60718
|
+
});
|
|
60719
|
+
registerSlashCommand({
|
|
60720
|
+
name: "export",
|
|
60721
|
+
category: "core",
|
|
60722
|
+
description: "Export conversation to a file [path]",
|
|
60723
|
+
handler: (args) => {
|
|
60724
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
60725
|
+
const path = args.trim() || join7(process.cwd(), `coders-export-${timestamp}.md`);
|
|
60726
|
+
return { action: "export", data: path, output: `Exporting conversation to: ${path}` };
|
|
60727
|
+
}
|
|
60728
|
+
});
|
|
60729
|
+
registerSlashCommand({
|
|
60730
|
+
name: "theme",
|
|
60731
|
+
category: "mode",
|
|
60732
|
+
description: "Change UI theme [name]",
|
|
60733
|
+
handler: (args) => {
|
|
60734
|
+
if (!args.trim()) {
|
|
60735
|
+
try {
|
|
60736
|
+
const { getAvailableThemes: getAvailableThemes2 } = (init_themes(), __toCommonJS(themes_exports));
|
|
60737
|
+
const themes = getAvailableThemes2();
|
|
60738
|
+
return { output: `Available themes: ${themes.join(", ")}
|
|
60739
|
+
Use /theme <name> to switch.` };
|
|
60740
|
+
} catch {
|
|
60741
|
+
return { output: "Available themes: default, dark, light\nUse /theme <name> to switch." };
|
|
60742
|
+
}
|
|
60743
|
+
}
|
|
60744
|
+
return { action: "theme", data: args.trim(), output: `Theme set to: ${args.trim()}` };
|
|
60745
|
+
}
|
|
60746
|
+
});
|
|
60747
|
+
registerSlashCommand({
|
|
60748
|
+
name: "effort",
|
|
60749
|
+
category: "mode",
|
|
60750
|
+
description: "Set effort level [low|medium|high]",
|
|
60751
|
+
handler: (args) => {
|
|
60752
|
+
const level = args.trim().toLowerCase();
|
|
60753
|
+
if (!level) return { output: "Usage: /effort <low|medium|high>" };
|
|
60754
|
+
if (!["low", "medium", "high"].includes(level)) {
|
|
60755
|
+
return { output: `Invalid effort level: "${level}". Must be one of: low, medium, high` };
|
|
60756
|
+
}
|
|
60757
|
+
return { action: "effort", data: level, output: `Effort level set to: ${level}` };
|
|
60758
|
+
}
|
|
60759
|
+
});
|
|
60760
|
+
registerSlashCommand({
|
|
60761
|
+
name: "skills",
|
|
60762
|
+
category: "system",
|
|
60763
|
+
description: "List available skills from .coders/skills/ and .claude/skills/",
|
|
60764
|
+
handler: () => {
|
|
60765
|
+
const skillDirs = [
|
|
60766
|
+
join7(process.cwd(), ".coders", "skills"),
|
|
60767
|
+
join7(process.cwd(), ".claude", "skills")
|
|
60768
|
+
];
|
|
60769
|
+
const skills = [];
|
|
60770
|
+
for (const dir of skillDirs) {
|
|
60771
|
+
if (!existsSync9(dir)) continue;
|
|
60772
|
+
try {
|
|
60773
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
60774
|
+
for (const entry of entries) {
|
|
60775
|
+
if (entry.isDirectory()) {
|
|
60776
|
+
const skillMd = join7(dir, entry.name, "SKILL.md");
|
|
60777
|
+
if (existsSync9(skillMd)) {
|
|
60778
|
+
skills.push(` ${entry.name} (${dir}/${entry.name}/SKILL.md)`);
|
|
60779
|
+
}
|
|
60780
|
+
}
|
|
60781
|
+
}
|
|
60782
|
+
} catch {
|
|
60783
|
+
}
|
|
60784
|
+
}
|
|
60785
|
+
if (skills.length === 0) return { output: "No skills found. Place SKILL.md files in .coders/skills/<name>/ or .claude/skills/<name>/." };
|
|
60786
|
+
return { output: `Available skills (${skills.length}):
|
|
60787
|
+
${skills.join("\n")}` };
|
|
60788
|
+
}
|
|
60789
|
+
});
|
|
60790
|
+
registerSlashCommand({
|
|
60791
|
+
name: "rename",
|
|
60792
|
+
category: "core",
|
|
60793
|
+
description: "Rename the current session [name]",
|
|
60794
|
+
handler: (args) => {
|
|
60795
|
+
if (!args.trim()) return { output: "Usage: /rename <name>" };
|
|
60796
|
+
return { action: "rename", data: args.trim(), output: `Session renamed to: ${args.trim()}` };
|
|
60797
|
+
}
|
|
60798
|
+
});
|
|
60799
|
+
registerSlashCommand({
|
|
60800
|
+
name: "resume",
|
|
60801
|
+
category: "navigation",
|
|
60802
|
+
description: "Resume the last session",
|
|
60803
|
+
handler: () => ({ action: "resume", output: "Resuming last session..." })
|
|
60804
|
+
});
|
|
60805
|
+
registerSlashCommand({
|
|
60806
|
+
name: "vim",
|
|
60807
|
+
category: "mode",
|
|
60808
|
+
description: "Toggle vim keybinding mode",
|
|
60809
|
+
handler: () => ({ action: "vim", output: "Vim mode toggled." })
|
|
60810
|
+
});
|
|
60309
60811
|
registerSlashCommand({
|
|
60310
60812
|
name: "undo",
|
|
60311
60813
|
category: "core",
|
|
@@ -60318,7 +60820,7 @@ Use /restore latest or /restore <number> or /restore <id-prefix>`
|
|
|
60318
60820
|
return { output: "No checkpoints found. Nothing to undo." };
|
|
60319
60821
|
}
|
|
60320
60822
|
try {
|
|
60321
|
-
|
|
60823
|
+
writeFileSync5(cp.file_path, cp.original_content, "utf-8");
|
|
60322
60824
|
const op = cp.edit_operation ? JSON.parse(cp.edit_operation) : null;
|
|
60323
60825
|
const summary = op?.old_string ? `Reverted: "${truncate(op.old_string, 50)}" -> "${truncate(op.new_string, 50)}"` : op?.type === "write_overwrite" ? "Restored file before overwrite" : "Restored original content";
|
|
60324
60826
|
return { output: `Undo successful: ${cp.file_path}
|
|
@@ -62587,29 +63089,40 @@ function renderBlockquote(token) {
|
|
|
62587
63089
|
}
|
|
62588
63090
|
function renderTable(token, maxWidth) {
|
|
62589
63091
|
const lines = [];
|
|
62590
|
-
const
|
|
63092
|
+
const stripMd = (s) => s.replace(/\*\*(.+?)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
|
|
63093
|
+
const colWidths = token.header.map((h) => stripMd(h.text).length);
|
|
62591
63094
|
for (const row of token.rows) {
|
|
62592
63095
|
for (let i = 0; i < row.length; i++) {
|
|
62593
|
-
colWidths[i] = Math.max(colWidths[i] ?? 0, row[i].text.length);
|
|
63096
|
+
colWidths[i] = Math.max(colWidths[i] ?? 0, stripMd(row[i].text).length);
|
|
62594
63097
|
}
|
|
62595
63098
|
}
|
|
62596
|
-
const
|
|
62597
|
-
|
|
62598
|
-
|
|
63099
|
+
const overhead = colWidths.length * 3 + 1;
|
|
63100
|
+
const maxTable = maxWidth - 4;
|
|
63101
|
+
const totalWidth = colWidths.reduce((a, b) => a + b, 0) + overhead;
|
|
63102
|
+
if (totalWidth > maxTable) {
|
|
63103
|
+
const available = maxTable - overhead;
|
|
63104
|
+
const total = colWidths.reduce((a, b) => a + b, 0);
|
|
62599
63105
|
for (let i = 0; i < colWidths.length; i++) {
|
|
62600
|
-
colWidths[i] = Math.max(
|
|
63106
|
+
colWidths[i] = Math.max(4, Math.floor(colWidths[i] / total * available));
|
|
62601
63107
|
}
|
|
62602
63108
|
}
|
|
62603
|
-
const headerLine = token.header.map((h, i) =>
|
|
63109
|
+
const headerLine = token.header.map((h, i) => padRendered(renderInline(h.text), stripMd(h.text), colWidths[i])).join(` ${FG_GRAY}\u2502${FG_DEFAULT} `);
|
|
62604
63110
|
lines.push(`${BOLD}${headerLine}${BOLD_OFF}`);
|
|
62605
63111
|
const sepLine = colWidths.map((w) => "\u2500".repeat(w)).join(`\u2500\u253C\u2500`);
|
|
62606
63112
|
lines.push(`${FG_GRAY}${sepLine}${FG_DEFAULT}`);
|
|
62607
63113
|
for (const row of token.rows) {
|
|
62608
|
-
const rowLine = row.map((cell, i) =>
|
|
63114
|
+
const rowLine = row.map((cell, i) => padRendered(renderInline(cell.text), stripMd(cell.text), colWidths[i])).join(` ${FG_GRAY}\u2502${FG_DEFAULT} `);
|
|
62609
63115
|
lines.push(rowLine);
|
|
62610
63116
|
}
|
|
62611
63117
|
return lines;
|
|
62612
63118
|
}
|
|
63119
|
+
function padRendered(rendered, plain, width) {
|
|
63120
|
+
if (plain.length >= width) {
|
|
63121
|
+
const truncPlain = plain.slice(0, width - 1) + "\u2026";
|
|
63122
|
+
return renderInline(truncPlain);
|
|
63123
|
+
}
|
|
63124
|
+
return rendered + " ".repeat(width - plain.length);
|
|
63125
|
+
}
|
|
62613
63126
|
function renderInline(text) {
|
|
62614
63127
|
return renderInlineWithRestore(text, "");
|
|
62615
63128
|
}
|
|
@@ -62641,10 +63154,6 @@ function highlightSyntax(line, lang) {
|
|
|
62641
63154
|
result = result.replace(/\b(\d+\.?\d*)\b/g, `${FG_YELLOW}$1${FG_DEFAULT}`);
|
|
62642
63155
|
return result;
|
|
62643
63156
|
}
|
|
62644
|
-
function pad(text, width) {
|
|
62645
|
-
if (text.length >= width) return text.slice(0, width);
|
|
62646
|
-
return text + " ".repeat(width - text.length);
|
|
62647
|
-
}
|
|
62648
63157
|
var ESC2, RESET, BOLD, BOLD_OFF, DIM, DIM_OFF, ITALIC, ITALIC_OFF, UNDERLINE, UNDERLINE_OFF, STRIKETHROUGH, STRIKE_OFF, FG_CYAN, FG_YELLOW, FG_GREEN, FG_BLUE, FG_MAGENTA, FG_GRAY, FG_DEFAULT, BG_GRAY, BG_DEFAULT;
|
|
62649
63158
|
var init_markdown = __esm({
|
|
62650
63159
|
"src/ui/components/markdown.tsx"() {
|
|
@@ -63016,8 +63525,8 @@ var init_permissions = __esm({
|
|
|
63016
63525
|
});
|
|
63017
63526
|
|
|
63018
63527
|
// src/memory/files.ts
|
|
63019
|
-
import { readFileSync as
|
|
63020
|
-
import { join as
|
|
63528
|
+
import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
|
|
63529
|
+
import { join as join8 } from "path";
|
|
63021
63530
|
function getInstructionsContent(projectDir) {
|
|
63022
63531
|
const cached2 = _cache.get(projectDir);
|
|
63023
63532
|
if (cached2 !== void 0) return cached2 || null;
|
|
@@ -63027,7 +63536,7 @@ function getInstructionsContent(projectDir) {
|
|
|
63027
63536
|
return null;
|
|
63028
63537
|
}
|
|
63029
63538
|
try {
|
|
63030
|
-
let content =
|
|
63539
|
+
let content = readFileSync8(filePath, "utf-8");
|
|
63031
63540
|
content = stripHtmlComments(content);
|
|
63032
63541
|
_cache.set(projectDir, content);
|
|
63033
63542
|
return content;
|
|
@@ -63038,11 +63547,11 @@ function getInstructionsContent(projectDir) {
|
|
|
63038
63547
|
}
|
|
63039
63548
|
function getGlobalInstructions() {
|
|
63040
63549
|
const configDir = getConfigDir();
|
|
63041
|
-
const primary =
|
|
63042
|
-
const path =
|
|
63550
|
+
const primary = join8(configDir, "CODERS.md");
|
|
63551
|
+
const path = existsSync10(primary) ? primary : null;
|
|
63043
63552
|
if (!path) return null;
|
|
63044
63553
|
try {
|
|
63045
|
-
return stripHtmlComments(
|
|
63554
|
+
return stripHtmlComments(readFileSync8(path, "utf-8"));
|
|
63046
63555
|
} catch {
|
|
63047
63556
|
return null;
|
|
63048
63557
|
}
|
|
@@ -63057,13 +63566,13 @@ ${global2}`);
|
|
|
63057
63566
|
if (project) parts.push(`# Project Instructions
|
|
63058
63567
|
|
|
63059
63568
|
${project}`);
|
|
63060
|
-
const rulesDir =
|
|
63061
|
-
if (
|
|
63569
|
+
const rulesDir = join8(projectDir, ".coders", "rules");
|
|
63570
|
+
if (existsSync10(rulesDir)) {
|
|
63062
63571
|
try {
|
|
63063
|
-
const { readdirSync:
|
|
63064
|
-
for (const file of
|
|
63572
|
+
const { readdirSync: readdirSync4 } = __require("fs");
|
|
63573
|
+
for (const file of readdirSync4(rulesDir)) {
|
|
63065
63574
|
if (!file.endsWith(".md")) continue;
|
|
63066
|
-
const content =
|
|
63575
|
+
const content = readFileSync8(join8(rulesDir, file), "utf-8");
|
|
63067
63576
|
parts.push(`# Rule: ${file}
|
|
63068
63577
|
|
|
63069
63578
|
${stripHtmlComments(content)}`);
|
|
@@ -63085,6 +63594,257 @@ var init_files = __esm({
|
|
|
63085
63594
|
}
|
|
63086
63595
|
});
|
|
63087
63596
|
|
|
63597
|
+
// src/core/constants.ts
|
|
63598
|
+
var BASH_TOOL, READ_TOOL, EDIT_TOOL, WRITE_TOOL, GLOB_TOOL, GREP_TOOL, AGENT_TOOL, WEB_FETCH_TOOL, WEB_SEARCH_TOOL, NOTEBOOK_EDIT_TOOL, LSP_TOOL, TASK_CREATE_TOOL, TASK_GET_TOOL, TASK_LIST_TOOL, TASK_UPDATE_TOOL, TASK_STOP_TOOL, TASK_OUTPUT_TOOL, ENTER_PLAN_MODE_TOOL, EXIT_PLAN_MODE_TOOL, ASK_USER_QUESTION_TOOL, CRON_CREATE_TOOL, CRON_DELETE_TOOL, CRON_LIST_TOOL, ENTER_WORKTREE_TOOL, EXIT_WORKTREE_TOOL, TOOL_SEARCH_TOOL, SEND_MESSAGE_TOOL, CONFIG_TOOL, LIST_MCP_RESOURCES_TOOL, READ_MCP_RESOURCE_TOOL, DEFAULT_BASH_TIMEOUT_MS, MAX_BASH_TIMEOUT_MS, DEFAULT_READ_LINE_LIMIT, DEFAULT_MAX_RESULT_SIZE_CHARS;
|
|
63599
|
+
var init_constants = __esm({
|
|
63600
|
+
"src/core/constants.ts"() {
|
|
63601
|
+
"use strict";
|
|
63602
|
+
BASH_TOOL = "Bash";
|
|
63603
|
+
READ_TOOL = "Read";
|
|
63604
|
+
EDIT_TOOL = "Edit";
|
|
63605
|
+
WRITE_TOOL = "Write";
|
|
63606
|
+
GLOB_TOOL = "Glob";
|
|
63607
|
+
GREP_TOOL = "Grep";
|
|
63608
|
+
AGENT_TOOL = "Agent";
|
|
63609
|
+
WEB_FETCH_TOOL = "WebFetch";
|
|
63610
|
+
WEB_SEARCH_TOOL = "WebSearch";
|
|
63611
|
+
NOTEBOOK_EDIT_TOOL = "NotebookEdit";
|
|
63612
|
+
LSP_TOOL = "LSP";
|
|
63613
|
+
TASK_CREATE_TOOL = "TaskCreate";
|
|
63614
|
+
TASK_GET_TOOL = "TaskGet";
|
|
63615
|
+
TASK_LIST_TOOL = "TaskList";
|
|
63616
|
+
TASK_UPDATE_TOOL = "TaskUpdate";
|
|
63617
|
+
TASK_STOP_TOOL = "TaskStop";
|
|
63618
|
+
TASK_OUTPUT_TOOL = "TaskOutput";
|
|
63619
|
+
ENTER_PLAN_MODE_TOOL = "EnterPlanMode";
|
|
63620
|
+
EXIT_PLAN_MODE_TOOL = "ExitPlanMode";
|
|
63621
|
+
ASK_USER_QUESTION_TOOL = "AskUserQuestion";
|
|
63622
|
+
CRON_CREATE_TOOL = "CronCreate";
|
|
63623
|
+
CRON_DELETE_TOOL = "CronDelete";
|
|
63624
|
+
CRON_LIST_TOOL = "CronList";
|
|
63625
|
+
ENTER_WORKTREE_TOOL = "EnterWorktree";
|
|
63626
|
+
EXIT_WORKTREE_TOOL = "ExitWorktree";
|
|
63627
|
+
TOOL_SEARCH_TOOL = "ToolSearch";
|
|
63628
|
+
SEND_MESSAGE_TOOL = "SendMessage";
|
|
63629
|
+
CONFIG_TOOL = "Config";
|
|
63630
|
+
LIST_MCP_RESOURCES_TOOL = "ListMcpResourcesTool";
|
|
63631
|
+
READ_MCP_RESOURCE_TOOL = "ReadMcpResourceTool";
|
|
63632
|
+
DEFAULT_BASH_TIMEOUT_MS = 12e4;
|
|
63633
|
+
MAX_BASH_TIMEOUT_MS = 6e5;
|
|
63634
|
+
DEFAULT_READ_LINE_LIMIT = 2e3;
|
|
63635
|
+
DEFAULT_MAX_RESULT_SIZE_CHARS = 1e5;
|
|
63636
|
+
}
|
|
63637
|
+
});
|
|
63638
|
+
|
|
63639
|
+
// src/tools/builtin/skill.ts
|
|
63640
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync3, existsSync as existsSync11, statSync } from "fs";
|
|
63641
|
+
import { join as join9 } from "path";
|
|
63642
|
+
import { homedir as homedir3 } from "os";
|
|
63643
|
+
function parseFrontmatter(content) {
|
|
63644
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
63645
|
+
if (!match) {
|
|
63646
|
+
return { frontmatter: {}, body: content };
|
|
63647
|
+
}
|
|
63648
|
+
const rawYaml = match[1];
|
|
63649
|
+
const body = match[2];
|
|
63650
|
+
const frontmatter = {};
|
|
63651
|
+
for (const line of rawYaml.split("\n")) {
|
|
63652
|
+
const trimmed = line.trim();
|
|
63653
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
63654
|
+
const colonIdx = trimmed.indexOf(":");
|
|
63655
|
+
if (colonIdx === -1) continue;
|
|
63656
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
63657
|
+
let value = trimmed.slice(colonIdx + 1).trim();
|
|
63658
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
63659
|
+
value = value.slice(1, -1);
|
|
63660
|
+
}
|
|
63661
|
+
frontmatter[key] = value;
|
|
63662
|
+
}
|
|
63663
|
+
return { frontmatter, body };
|
|
63664
|
+
}
|
|
63665
|
+
function parseSkillFile(filePath, dirName) {
|
|
63666
|
+
try {
|
|
63667
|
+
const content = readFileSync9(filePath, "utf-8");
|
|
63668
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
63669
|
+
return {
|
|
63670
|
+
name: frontmatter.name || dirName,
|
|
63671
|
+
description: frontmatter.description || "",
|
|
63672
|
+
body: body.trim()
|
|
63673
|
+
};
|
|
63674
|
+
} catch {
|
|
63675
|
+
return null;
|
|
63676
|
+
}
|
|
63677
|
+
}
|
|
63678
|
+
function scanSkillsDir(baseDir, source) {
|
|
63679
|
+
if (!existsSync11(baseDir)) return [];
|
|
63680
|
+
const skills = [];
|
|
63681
|
+
try {
|
|
63682
|
+
const entries = readdirSync3(baseDir);
|
|
63683
|
+
for (const entry of entries) {
|
|
63684
|
+
const entryPath = join9(baseDir, entry);
|
|
63685
|
+
try {
|
|
63686
|
+
if (!statSync(entryPath).isDirectory()) continue;
|
|
63687
|
+
} catch {
|
|
63688
|
+
continue;
|
|
63689
|
+
}
|
|
63690
|
+
const skillFile = join9(entryPath, "SKILL.md");
|
|
63691
|
+
if (!existsSync11(skillFile)) continue;
|
|
63692
|
+
const parsed = parseSkillFile(skillFile, entry);
|
|
63693
|
+
if (!parsed) continue;
|
|
63694
|
+
skills.push({
|
|
63695
|
+
name: parsed.name,
|
|
63696
|
+
description: parsed.description,
|
|
63697
|
+
path: skillFile,
|
|
63698
|
+
source
|
|
63699
|
+
});
|
|
63700
|
+
}
|
|
63701
|
+
} catch {
|
|
63702
|
+
}
|
|
63703
|
+
return skills;
|
|
63704
|
+
}
|
|
63705
|
+
function discoverSkills(cwd2) {
|
|
63706
|
+
const projectDir = cwd2 ?? process.cwd();
|
|
63707
|
+
const home = homedir3();
|
|
63708
|
+
const projectCoders = scanSkillsDir(join9(projectDir, ".coders", "skills"), "project");
|
|
63709
|
+
const projectClaude = scanSkillsDir(join9(projectDir, ".claude", "skills"), "project");
|
|
63710
|
+
const userCoders = scanSkillsDir(join9(home, ".coders", "skills"), "user");
|
|
63711
|
+
const userClaude = scanSkillsDir(join9(home, ".claude", "skills"), "user");
|
|
63712
|
+
const seen = /* @__PURE__ */ new Set();
|
|
63713
|
+
const all = [];
|
|
63714
|
+
for (const list2 of [projectCoders, projectClaude, userCoders, userClaude]) {
|
|
63715
|
+
for (const skill of list2) {
|
|
63716
|
+
const key = skill.name.toLowerCase();
|
|
63717
|
+
if (seen.has(key)) continue;
|
|
63718
|
+
seen.add(key);
|
|
63719
|
+
all.push(skill);
|
|
63720
|
+
}
|
|
63721
|
+
}
|
|
63722
|
+
return all;
|
|
63723
|
+
}
|
|
63724
|
+
var SKILL_TOOL, skillInputSchema, skillTool;
|
|
63725
|
+
var init_skill = __esm({
|
|
63726
|
+
"src/tools/builtin/skill.ts"() {
|
|
63727
|
+
"use strict";
|
|
63728
|
+
init_zod();
|
|
63729
|
+
init_constants();
|
|
63730
|
+
SKILL_TOOL = "Skill";
|
|
63731
|
+
skillInputSchema = external_exports.strictObject({
|
|
63732
|
+
skill: external_exports.string().describe("The skill name to invoke (e.g. 'commit', 'review-pr', 'test')"),
|
|
63733
|
+
args: external_exports.string().optional().describe("Optional arguments to pass to the skill prompt")
|
|
63734
|
+
});
|
|
63735
|
+
skillTool = {
|
|
63736
|
+
name: SKILL_TOOL,
|
|
63737
|
+
searchHint: "invoke user-defined skill from SKILL.md",
|
|
63738
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
63739
|
+
shouldDefer: false,
|
|
63740
|
+
strict: false,
|
|
63741
|
+
async description() {
|
|
63742
|
+
return "Execute a skill within the main conversation. Skills are user-defined prompts in .coders/skills/ or .claude/skills/ directories.";
|
|
63743
|
+
},
|
|
63744
|
+
async prompt() {
|
|
63745
|
+
return `Invoke a user-defined skill from .coders/skills/ or .claude/skills/ directories.
|
|
63746
|
+
Skills are directories containing a SKILL.md file with YAML frontmatter (name, description) and a markdown prompt body.
|
|
63747
|
+
When invoked, the skill's prompt is returned with {{args}} replaced by the provided args.
|
|
63748
|
+
Use this tool when the user references a skill by name or uses a "/<skill-name>" slash command pattern.`;
|
|
63749
|
+
},
|
|
63750
|
+
get inputSchema() {
|
|
63751
|
+
return skillInputSchema;
|
|
63752
|
+
},
|
|
63753
|
+
get outputSchema() {
|
|
63754
|
+
return external_exports.any();
|
|
63755
|
+
},
|
|
63756
|
+
userFacingName() {
|
|
63757
|
+
return SKILL_TOOL;
|
|
63758
|
+
},
|
|
63759
|
+
isEnabled() {
|
|
63760
|
+
return true;
|
|
63761
|
+
},
|
|
63762
|
+
isConcurrencySafe() {
|
|
63763
|
+
return true;
|
|
63764
|
+
},
|
|
63765
|
+
isReadOnly() {
|
|
63766
|
+
return true;
|
|
63767
|
+
},
|
|
63768
|
+
toAutoClassifierInput(input) {
|
|
63769
|
+
return `skill:${input.skill}${input.args ? ` ${input.args}` : ""}`;
|
|
63770
|
+
},
|
|
63771
|
+
getActivityDescription(input) {
|
|
63772
|
+
return `Running skill: ${input.skill}`;
|
|
63773
|
+
},
|
|
63774
|
+
getToolUseSummary(input) {
|
|
63775
|
+
return input.skill;
|
|
63776
|
+
},
|
|
63777
|
+
async checkPermissions(input) {
|
|
63778
|
+
return { behavior: "allow", updatedInput: input };
|
|
63779
|
+
},
|
|
63780
|
+
async validateInput(input) {
|
|
63781
|
+
if (!input.skill || typeof input.skill !== "string") {
|
|
63782
|
+
return { result: false, message: "skill name is required" };
|
|
63783
|
+
}
|
|
63784
|
+
return { result: true };
|
|
63785
|
+
},
|
|
63786
|
+
async call(input) {
|
|
63787
|
+
const skillName = input.skill.trim().toLowerCase();
|
|
63788
|
+
const skills = discoverSkills();
|
|
63789
|
+
const match = skills.find((s) => s.name.toLowerCase() === skillName);
|
|
63790
|
+
if (!match) {
|
|
63791
|
+
const available = skills.map((s) => s.name).join(", ");
|
|
63792
|
+
const errorMsg = available ? `Skill "${input.skill}" not found. Available skills: ${available}` : `Skill "${input.skill}" not found. No skills are installed. Create a skill directory with a SKILL.md file in .coders/skills/ or .claude/skills/.`;
|
|
63793
|
+
return {
|
|
63794
|
+
data: {
|
|
63795
|
+
skill: input.skill,
|
|
63796
|
+
prompt: "",
|
|
63797
|
+
source: "project",
|
|
63798
|
+
error: errorMsg
|
|
63799
|
+
}
|
|
63800
|
+
};
|
|
63801
|
+
}
|
|
63802
|
+
const parsed = parseSkillFile(match.path, match.name);
|
|
63803
|
+
if (!parsed || !parsed.body) {
|
|
63804
|
+
return {
|
|
63805
|
+
data: {
|
|
63806
|
+
skill: input.skill,
|
|
63807
|
+
prompt: "",
|
|
63808
|
+
source: match.source,
|
|
63809
|
+
error: `Skill "${match.name}" has an empty or invalid SKILL.md file at ${match.path}`
|
|
63810
|
+
}
|
|
63811
|
+
};
|
|
63812
|
+
}
|
|
63813
|
+
let prompt = parsed.body;
|
|
63814
|
+
if (input.args) {
|
|
63815
|
+
prompt = prompt.replace(/\{\{args\}\}/g, input.args);
|
|
63816
|
+
} else {
|
|
63817
|
+
prompt = prompt.replace(/\{\{args\}\}/g, "");
|
|
63818
|
+
}
|
|
63819
|
+
return {
|
|
63820
|
+
data: {
|
|
63821
|
+
skill: match.name,
|
|
63822
|
+
prompt: prompt.trim(),
|
|
63823
|
+
source: match.source
|
|
63824
|
+
}
|
|
63825
|
+
};
|
|
63826
|
+
},
|
|
63827
|
+
mapToolResultToToolResultBlockParam(result, toolUseId) {
|
|
63828
|
+
if (result.error) {
|
|
63829
|
+
return {
|
|
63830
|
+
type: "tool_result",
|
|
63831
|
+
tool_use_id: toolUseId,
|
|
63832
|
+
content: result.error,
|
|
63833
|
+
is_error: true
|
|
63834
|
+
};
|
|
63835
|
+
}
|
|
63836
|
+
return {
|
|
63837
|
+
type: "tool_result",
|
|
63838
|
+
tool_use_id: toolUseId,
|
|
63839
|
+
content: `<command-name>${result.skill}</command-name>
|
|
63840
|
+
|
|
63841
|
+
${result.prompt}`
|
|
63842
|
+
};
|
|
63843
|
+
}
|
|
63844
|
+
};
|
|
63845
|
+
}
|
|
63846
|
+
});
|
|
63847
|
+
|
|
63088
63848
|
// src/core/system-prompt.ts
|
|
63089
63849
|
function buildSystemPrompt(ctx) {
|
|
63090
63850
|
const sections = [];
|
|
@@ -63113,6 +63873,28 @@ ${t.prompt}`).join("\n\n");
|
|
|
63113
63873
|
${toolSection}`);
|
|
63114
63874
|
}
|
|
63115
63875
|
}
|
|
63876
|
+
if (ctx.deferredTools && ctx.deferredTools.length > 0) {
|
|
63877
|
+
const deferredList = ctx.deferredTools.map((t) => `- **${t.name}**: ${t.description}`).join("\n");
|
|
63878
|
+
sections.push(`
|
|
63879
|
+
# Deferred Tools
|
|
63880
|
+
|
|
63881
|
+
The following tools are available but not loaded by default. Use the ToolSearch tool to fetch their full schemas before calling them. Once you call ToolSearch for a tool, you can use it normally.
|
|
63882
|
+
|
|
63883
|
+
${deferredList}`);
|
|
63884
|
+
}
|
|
63885
|
+
try {
|
|
63886
|
+
const skills = discoverSkills(ctx.projectDir);
|
|
63887
|
+
if (skills.length > 0) {
|
|
63888
|
+
const skillList = skills.map((s) => `- **${s.name}**${s.description ? `: ${s.description}` : ""} _(${s.source})_`).join("\n");
|
|
63889
|
+
sections.push(`
|
|
63890
|
+
# Available Skills
|
|
63891
|
+
|
|
63892
|
+
The following skills are available via the Skill tool. When a user references a skill by name or uses "/<skill-name>", invoke it with the Skill tool.
|
|
63893
|
+
|
|
63894
|
+
${skillList}`);
|
|
63895
|
+
}
|
|
63896
|
+
} catch {
|
|
63897
|
+
}
|
|
63116
63898
|
const ctxParts = [];
|
|
63117
63899
|
ctxParts.push(`Working directory: ${ctx.projectDir}`);
|
|
63118
63900
|
ctxParts.push(`Model: ${ctx.model}`);
|
|
@@ -63140,6 +63922,7 @@ var init_system_prompt = __esm({
|
|
|
63140
63922
|
"src/core/system-prompt.ts"() {
|
|
63141
63923
|
"use strict";
|
|
63142
63924
|
init_files();
|
|
63925
|
+
init_skill();
|
|
63143
63926
|
CORE_INSTRUCTIONS = `You are Coders, an open-source interactive CLI agent built by Hasna for software engineering.
|
|
63144
63927
|
You are an interactive agent that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
|
|
63145
63928
|
|
|
@@ -63183,44 +63966,6 @@ You are an interactive agent that helps users with software engineering tasks. U
|
|
|
63183
63966
|
}
|
|
63184
63967
|
});
|
|
63185
63968
|
|
|
63186
|
-
// src/core/constants.ts
|
|
63187
|
-
var BASH_TOOL, READ_TOOL, EDIT_TOOL, WRITE_TOOL, GLOB_TOOL, GREP_TOOL, AGENT_TOOL, WEB_FETCH_TOOL, WEB_SEARCH_TOOL, NOTEBOOK_EDIT_TOOL, LSP_TOOL, TASK_CREATE_TOOL, TASK_GET_TOOL, TASK_LIST_TOOL, TASK_UPDATE_TOOL, ENTER_PLAN_MODE_TOOL, EXIT_PLAN_MODE_TOOL, ASK_USER_QUESTION_TOOL, CRON_CREATE_TOOL, CRON_DELETE_TOOL, CRON_LIST_TOOL, ENTER_WORKTREE_TOOL, EXIT_WORKTREE_TOOL, TOOL_SEARCH_TOOL, SEND_MESSAGE_TOOL, CONFIG_TOOL, DEFAULT_BASH_TIMEOUT_MS, MAX_BASH_TIMEOUT_MS, DEFAULT_READ_LINE_LIMIT, DEFAULT_MAX_RESULT_SIZE_CHARS;
|
|
63188
|
-
var init_constants = __esm({
|
|
63189
|
-
"src/core/constants.ts"() {
|
|
63190
|
-
"use strict";
|
|
63191
|
-
BASH_TOOL = "Bash";
|
|
63192
|
-
READ_TOOL = "Read";
|
|
63193
|
-
EDIT_TOOL = "Edit";
|
|
63194
|
-
WRITE_TOOL = "Write";
|
|
63195
|
-
GLOB_TOOL = "Glob";
|
|
63196
|
-
GREP_TOOL = "Grep";
|
|
63197
|
-
AGENT_TOOL = "Agent";
|
|
63198
|
-
WEB_FETCH_TOOL = "WebFetch";
|
|
63199
|
-
WEB_SEARCH_TOOL = "WebSearch";
|
|
63200
|
-
NOTEBOOK_EDIT_TOOL = "NotebookEdit";
|
|
63201
|
-
LSP_TOOL = "LSP";
|
|
63202
|
-
TASK_CREATE_TOOL = "TaskCreate";
|
|
63203
|
-
TASK_GET_TOOL = "TaskGet";
|
|
63204
|
-
TASK_LIST_TOOL = "TaskList";
|
|
63205
|
-
TASK_UPDATE_TOOL = "TaskUpdate";
|
|
63206
|
-
ENTER_PLAN_MODE_TOOL = "EnterPlanMode";
|
|
63207
|
-
EXIT_PLAN_MODE_TOOL = "ExitPlanMode";
|
|
63208
|
-
ASK_USER_QUESTION_TOOL = "AskUserQuestion";
|
|
63209
|
-
CRON_CREATE_TOOL = "CronCreate";
|
|
63210
|
-
CRON_DELETE_TOOL = "CronDelete";
|
|
63211
|
-
CRON_LIST_TOOL = "CronList";
|
|
63212
|
-
ENTER_WORKTREE_TOOL = "EnterWorktree";
|
|
63213
|
-
EXIT_WORKTREE_TOOL = "ExitWorktree";
|
|
63214
|
-
TOOL_SEARCH_TOOL = "ToolSearch";
|
|
63215
|
-
SEND_MESSAGE_TOOL = "SendMessage";
|
|
63216
|
-
CONFIG_TOOL = "Config";
|
|
63217
|
-
DEFAULT_BASH_TIMEOUT_MS = 12e4;
|
|
63218
|
-
MAX_BASH_TIMEOUT_MS = 6e5;
|
|
63219
|
-
DEFAULT_READ_LINE_LIMIT = 2e3;
|
|
63220
|
-
DEFAULT_MAX_RESULT_SIZE_CHARS = 1e5;
|
|
63221
|
-
}
|
|
63222
|
-
});
|
|
63223
|
-
|
|
63224
63969
|
// src/tools/builtin/bash.ts
|
|
63225
63970
|
import { spawn } from "child_process";
|
|
63226
63971
|
function isDangerousCommand(command) {
|
|
@@ -63335,13 +64080,14 @@ function truncateOutput(output, maxChars = DEFAULT_MAX_RESULT_SIZE_CHARS) {
|
|
|
63335
64080
|
|
|
63336
64081
|
` + output.slice(-half);
|
|
63337
64082
|
}
|
|
63338
|
-
var DANGEROUS_PATTERNS, BashInputSchema, BashOutputSchema, READ_ONLY_COMMANDS, READ_ONLY_KEYWORDS, GIT_READ_ONLY_SUBCOMMANDS, NPM_READ_ONLY_SUBCOMMANDS, DOCKER_READ_ONLY_SUBCOMMANDS, backgroundTasks,
|
|
64083
|
+
var DANGEROUS_PATTERNS, BashInputSchema, BashOutputSchema, READ_ONLY_COMMANDS, READ_ONLY_KEYWORDS, GIT_READ_ONLY_SUBCOMMANDS, NPM_READ_ONLY_SUBCOMMANDS, DOCKER_READ_ONLY_SUBCOMMANDS, backgroundTasks, bashTool, BASH_PROMPT;
|
|
63339
64084
|
var init_bash = __esm({
|
|
63340
64085
|
"src/tools/builtin/bash.ts"() {
|
|
63341
64086
|
"use strict";
|
|
63342
64087
|
init_zod();
|
|
63343
64088
|
init_constants();
|
|
63344
64089
|
init_db();
|
|
64090
|
+
init_background_tasks();
|
|
63345
64091
|
DANGEROUS_PATTERNS = [
|
|
63346
64092
|
{ pattern: /\brm\s+-rf\s+\/\s*$/, reason: "Recursive delete of root filesystem" },
|
|
63347
64093
|
{ pattern: /\brm\s+-rf\s+~\//, reason: "Recursive delete of home directory" },
|
|
@@ -63534,7 +64280,6 @@ var init_bash = __esm({
|
|
|
63534
64280
|
"version"
|
|
63535
64281
|
]);
|
|
63536
64282
|
backgroundTasks = /* @__PURE__ */ new Map();
|
|
63537
|
-
nextBgId = 1;
|
|
63538
64283
|
bashTool = {
|
|
63539
64284
|
name: BASH_TOOL,
|
|
63540
64285
|
searchHint: "execute shell commands in the terminal",
|
|
@@ -63605,7 +64350,8 @@ var init_bash = __esm({
|
|
|
63605
64350
|
const timeoutMs = timeout ?? getDefaultTimeout();
|
|
63606
64351
|
const startTime = performance.now();
|
|
63607
64352
|
if (run_in_background) {
|
|
63608
|
-
const
|
|
64353
|
+
const bgTask = createTask("bash", command);
|
|
64354
|
+
const taskId = bgTask.id;
|
|
63609
64355
|
const child = spawn(command, [], {
|
|
63610
64356
|
shell: getShell(),
|
|
63611
64357
|
cwd: process.cwd(),
|
|
@@ -63614,10 +64360,14 @@ var init_bash = __esm({
|
|
|
63614
64360
|
});
|
|
63615
64361
|
let output = "";
|
|
63616
64362
|
child.stdout?.on("data", (data) => {
|
|
63617
|
-
|
|
64363
|
+
const chunk = data.toString();
|
|
64364
|
+
output += chunk;
|
|
64365
|
+
writeTaskOutput(taskId, chunk);
|
|
63618
64366
|
});
|
|
63619
64367
|
child.stderr?.on("data", (data) => {
|
|
63620
|
-
|
|
64368
|
+
const chunk = data.toString();
|
|
64369
|
+
output += chunk;
|
|
64370
|
+
writeTaskOutput(taskId, chunk);
|
|
63621
64371
|
});
|
|
63622
64372
|
const task = { process: child, output: "", done: false, exitCode: null };
|
|
63623
64373
|
backgroundTasks.set(taskId, task);
|
|
@@ -63625,10 +64375,16 @@ var init_bash = __esm({
|
|
|
63625
64375
|
task.output = output;
|
|
63626
64376
|
task.done = true;
|
|
63627
64377
|
task.exitCode = code;
|
|
64378
|
+
completeTask(taskId, output, code ?? void 0);
|
|
64379
|
+
});
|
|
64380
|
+
child.on("error", (err) => {
|
|
64381
|
+
task.done = true;
|
|
64382
|
+
task.exitCode = 1;
|
|
64383
|
+
failTask(taskId, err.message);
|
|
63628
64384
|
});
|
|
63629
64385
|
return {
|
|
63630
64386
|
data: {
|
|
63631
|
-
stdout: `Background task started with ID: ${taskId}
|
|
64387
|
+
stdout: `Background task started with ID: ${taskId}. Use TaskOutput to check its status.`,
|
|
63632
64388
|
stderr: "",
|
|
63633
64389
|
exitCode: null,
|
|
63634
64390
|
interrupted: false,
|
|
@@ -63741,7 +64497,7 @@ Instructions:
|
|
|
63741
64497
|
});
|
|
63742
64498
|
|
|
63743
64499
|
// src/tools/builtin/read.ts
|
|
63744
|
-
import { readFileSync as
|
|
64500
|
+
import { readFileSync as readFileSync10, statSync as statSync2, existsSync as existsSync12 } from "fs";
|
|
63745
64501
|
import { extname, isAbsolute, resolve as resolve2 } from "path";
|
|
63746
64502
|
function hasFileBeenRead(filePath) {
|
|
63747
64503
|
return readFiles.has(resolve2(filePath));
|
|
@@ -63750,7 +64506,7 @@ function markFileAsRead(filePath) {
|
|
|
63750
64506
|
readFiles.add(resolve2(filePath));
|
|
63751
64507
|
}
|
|
63752
64508
|
function readTextFile(filePath, input) {
|
|
63753
|
-
const rawContent =
|
|
64509
|
+
const rawContent = readFileSync10(filePath, "utf-8");
|
|
63754
64510
|
const allLines = rawContent.split("\n");
|
|
63755
64511
|
const totalLines = allLines.length;
|
|
63756
64512
|
const startLine = input.offset ?? 1;
|
|
@@ -63773,7 +64529,7 @@ function readTextFile(filePath, input) {
|
|
|
63773
64529
|
};
|
|
63774
64530
|
}
|
|
63775
64531
|
function readImageFile(filePath, input) {
|
|
63776
|
-
const stat =
|
|
64532
|
+
const stat = statSync2(filePath);
|
|
63777
64533
|
const ext = extname(filePath).toLowerCase();
|
|
63778
64534
|
const content = `[Image file: ${filePath} (${ext}, ${formatBytes(stat.size)})]`;
|
|
63779
64535
|
return {
|
|
@@ -63787,7 +64543,7 @@ function readImageFile(filePath, input) {
|
|
|
63787
64543
|
};
|
|
63788
64544
|
}
|
|
63789
64545
|
function readPdfFile(filePath, input) {
|
|
63790
|
-
const stat =
|
|
64546
|
+
const stat = statSync2(filePath);
|
|
63791
64547
|
const pages = input.pages ?? "1-5";
|
|
63792
64548
|
const content = `[PDF file: ${filePath} (${formatBytes(stat.size)}, requested pages: ${pages}). PDF reading requires pdf-parse library \u2014 install to enable.]`;
|
|
63793
64549
|
return {
|
|
@@ -63802,7 +64558,7 @@ function readPdfFile(filePath, input) {
|
|
|
63802
64558
|
}
|
|
63803
64559
|
function readNotebookFile(filePath, input) {
|
|
63804
64560
|
try {
|
|
63805
|
-
const rawContent =
|
|
64561
|
+
const rawContent = readFileSync10(filePath, "utf-8");
|
|
63806
64562
|
const notebook = JSON.parse(rawContent);
|
|
63807
64563
|
if (!notebook.cells || !Array.isArray(notebook.cells)) {
|
|
63808
64564
|
return {
|
|
@@ -63922,11 +64678,11 @@ var init_read = __esm({
|
|
|
63922
64678
|
return { result: false, message: "file_path is required", errorCode: 1 };
|
|
63923
64679
|
}
|
|
63924
64680
|
const resolved = resolvePath(input.file_path);
|
|
63925
|
-
if (!
|
|
64681
|
+
if (!existsSync12(resolved)) {
|
|
63926
64682
|
return { result: false, message: `File does not exist: ${input.file_path}`, errorCode: 2 };
|
|
63927
64683
|
}
|
|
63928
64684
|
try {
|
|
63929
|
-
const stat =
|
|
64685
|
+
const stat = statSync2(resolved);
|
|
63930
64686
|
if (stat.isDirectory()) {
|
|
63931
64687
|
return { result: false, message: `Path is a directory, not a file: ${input.file_path}. Use Bash with ls to list directory contents.`, errorCode: 3 };
|
|
63932
64688
|
}
|
|
@@ -63979,7 +64735,7 @@ Usage:
|
|
|
63979
64735
|
});
|
|
63980
64736
|
|
|
63981
64737
|
// src/tools/builtin/edit.ts
|
|
63982
|
-
import { readFileSync as
|
|
64738
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, existsSync as existsSync13, statSync as statSync3 } from "fs";
|
|
63983
64739
|
import { resolve as resolve3, isAbsolute as isAbsolute2 } from "path";
|
|
63984
64740
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
63985
64741
|
function resolvePath2(filePath) {
|
|
@@ -64119,7 +64875,7 @@ var init_edit = __esm({
|
|
|
64119
64875
|
return { result: false, message: "old_string and new_string must be different", errorCode: 2 };
|
|
64120
64876
|
}
|
|
64121
64877
|
const resolved = resolvePath2(input.file_path);
|
|
64122
|
-
if (!
|
|
64878
|
+
if (!existsSync13(resolved)) {
|
|
64123
64879
|
return { result: false, message: `File does not exist: ${input.file_path}`, errorCode: 3 };
|
|
64124
64880
|
}
|
|
64125
64881
|
if (!hasFileBeenRead(resolved)) {
|
|
@@ -64129,7 +64885,7 @@ var init_edit = __esm({
|
|
|
64129
64885
|
errorCode: 4
|
|
64130
64886
|
};
|
|
64131
64887
|
}
|
|
64132
|
-
const content =
|
|
64888
|
+
const content = readFileSync11(resolved, "utf-8");
|
|
64133
64889
|
const count = countOccurrences(content, input.old_string);
|
|
64134
64890
|
if (count === 0) {
|
|
64135
64891
|
return {
|
|
@@ -64160,7 +64916,7 @@ var init_edit = __esm({
|
|
|
64160
64916
|
const resolved = resolvePath2(input.file_path);
|
|
64161
64917
|
const MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
64162
64918
|
try {
|
|
64163
|
-
const fileSize =
|
|
64919
|
+
const fileSize = statSync3(resolved).size;
|
|
64164
64920
|
if (fileSize > MAX_FILE_SIZE) {
|
|
64165
64921
|
return {
|
|
64166
64922
|
data: {
|
|
@@ -64175,7 +64931,7 @@ var init_edit = __esm({
|
|
|
64175
64931
|
}
|
|
64176
64932
|
} catch {
|
|
64177
64933
|
}
|
|
64178
|
-
const originalContent =
|
|
64934
|
+
const originalContent = readFileSync11(resolved, "utf-8");
|
|
64179
64935
|
let newContent;
|
|
64180
64936
|
let replacements;
|
|
64181
64937
|
if (input.replace_all) {
|
|
@@ -64206,7 +64962,7 @@ var init_edit = __esm({
|
|
|
64206
64962
|
);
|
|
64207
64963
|
} catch {
|
|
64208
64964
|
}
|
|
64209
|
-
|
|
64965
|
+
writeFileSync6(resolved, newContent, "utf-8");
|
|
64210
64966
|
markFileAsRead(resolved);
|
|
64211
64967
|
const gitDiff = generateUnifiedDiff(originalContent, newContent, input.file_path);
|
|
64212
64968
|
return {
|
|
@@ -64244,7 +65000,7 @@ Usage:
|
|
|
64244
65000
|
});
|
|
64245
65001
|
|
|
64246
65002
|
// src/tools/builtin/write.ts
|
|
64247
|
-
import { writeFileSync as
|
|
65003
|
+
import { writeFileSync as writeFileSync7, readFileSync as readFileSync12, existsSync as existsSync14, mkdirSync as mkdirSync6 } from "fs";
|
|
64248
65004
|
import { dirname as dirname3, resolve as resolve4, isAbsolute as isAbsolute3 } from "path";
|
|
64249
65005
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
64250
65006
|
function resolvePath3(filePath) {
|
|
@@ -64317,14 +65073,14 @@ var init_write = __esm({
|
|
|
64317
65073
|
return { data: { filePath: "", bytesWritten: 0, created: false } };
|
|
64318
65074
|
}
|
|
64319
65075
|
const resolved = resolvePath3(input.file_path);
|
|
64320
|
-
const created = !
|
|
65076
|
+
const created = !existsSync14(resolved);
|
|
64321
65077
|
const dir = dirname3(resolved);
|
|
64322
|
-
if (!
|
|
64323
|
-
|
|
65078
|
+
if (!existsSync14(dir)) {
|
|
65079
|
+
mkdirSync6(dir, { recursive: true });
|
|
64324
65080
|
}
|
|
64325
65081
|
if (!created) {
|
|
64326
65082
|
try {
|
|
64327
|
-
const originalContent =
|
|
65083
|
+
const originalContent = readFileSync12(resolved, "utf-8");
|
|
64328
65084
|
const cpId = randomUUID3().slice(0, 8);
|
|
64329
65085
|
dbRun(
|
|
64330
65086
|
"INSERT INTO checkpoints (id, session_id, file_path, original_content, edit_operation) VALUES (?, ?, ?, ?, ?)",
|
|
@@ -64333,7 +65089,7 @@ var init_write = __esm({
|
|
|
64333
65089
|
} catch {
|
|
64334
65090
|
}
|
|
64335
65091
|
}
|
|
64336
|
-
|
|
65092
|
+
writeFileSync7(resolved, input.content, "utf-8");
|
|
64337
65093
|
markFileAsRead(resolved);
|
|
64338
65094
|
return {
|
|
64339
65095
|
data: {
|
|
@@ -65026,7 +65782,7 @@ var require_fill_range = __commonJS({
|
|
|
65026
65782
|
}
|
|
65027
65783
|
return options2.stringify === true;
|
|
65028
65784
|
};
|
|
65029
|
-
var
|
|
65785
|
+
var pad = (input, maxLength, toNumber) => {
|
|
65030
65786
|
if (maxLength > 0) {
|
|
65031
65787
|
let dash = input[0] === "-" ? "-" : "";
|
|
65032
65788
|
if (dash) input = input.slice(1);
|
|
@@ -65128,7 +65884,7 @@ var require_fill_range = __commonJS({
|
|
|
65128
65884
|
if (options2.toRegex === true && step > 1) {
|
|
65129
65885
|
push(a);
|
|
65130
65886
|
} else {
|
|
65131
|
-
range.push(
|
|
65887
|
+
range.push(pad(format(a, index), maxLen, toNumber));
|
|
65132
65888
|
}
|
|
65133
65889
|
a = descending ? a - step : a + step;
|
|
65134
65890
|
index++;
|
|
@@ -67798,18 +68554,18 @@ var require_tasks = __commonJS({
|
|
|
67798
68554
|
return patterns.map((pattern) => utils.pattern.removeDuplicateSlashes(pattern));
|
|
67799
68555
|
}
|
|
67800
68556
|
function convertPatternsToTasks(positive, negative, dynamic) {
|
|
67801
|
-
const
|
|
68557
|
+
const tasks2 = [];
|
|
67802
68558
|
const patternsOutsideCurrentDirectory = utils.pattern.getPatternsOutsideCurrentDirectory(positive);
|
|
67803
68559
|
const patternsInsideCurrentDirectory = utils.pattern.getPatternsInsideCurrentDirectory(positive);
|
|
67804
68560
|
const outsideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsOutsideCurrentDirectory);
|
|
67805
68561
|
const insideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsInsideCurrentDirectory);
|
|
67806
|
-
|
|
68562
|
+
tasks2.push(...convertPatternGroupsToTasks(outsideCurrentDirectoryGroup, negative, dynamic));
|
|
67807
68563
|
if ("." in insideCurrentDirectoryGroup) {
|
|
67808
|
-
|
|
68564
|
+
tasks2.push(convertPatternGroupToTask(".", patternsInsideCurrentDirectory, negative, dynamic));
|
|
67809
68565
|
} else {
|
|
67810
|
-
|
|
68566
|
+
tasks2.push(...convertPatternGroupsToTasks(insideCurrentDirectoryGroup, negative, dynamic));
|
|
67811
68567
|
}
|
|
67812
|
-
return
|
|
68568
|
+
return tasks2;
|
|
67813
68569
|
}
|
|
67814
68570
|
exports.convertPatternsToTasks = convertPatternsToTasks;
|
|
67815
68571
|
function getPositivePatterns(patterns) {
|
|
@@ -67987,11 +68743,11 @@ var require_out = __commonJS({
|
|
|
67987
68743
|
async.read(path, getSettings2(optionsOrSettingsOrCallback), callback);
|
|
67988
68744
|
}
|
|
67989
68745
|
exports.stat = stat;
|
|
67990
|
-
function
|
|
68746
|
+
function statSync5(path, optionsOrSettings) {
|
|
67991
68747
|
const settings = getSettings2(optionsOrSettings);
|
|
67992
68748
|
return sync.read(path, settings);
|
|
67993
68749
|
}
|
|
67994
|
-
exports.statSync =
|
|
68750
|
+
exports.statSync = statSync5;
|
|
67995
68751
|
function getSettings2(settingsOrOptions = {}) {
|
|
67996
68752
|
if (settingsOrOptions instanceof settings_1.default) {
|
|
67997
68753
|
return settingsOrOptions;
|
|
@@ -68016,14 +68772,14 @@ var require_run_parallel = __commonJS({
|
|
|
68016
68772
|
"node_modules/run-parallel/index.js"(exports, module) {
|
|
68017
68773
|
module.exports = runParallel;
|
|
68018
68774
|
var queueMicrotask2 = require_queue_microtask();
|
|
68019
|
-
function runParallel(
|
|
68775
|
+
function runParallel(tasks2, cb) {
|
|
68020
68776
|
let results, pending, keys;
|
|
68021
68777
|
let isSync = true;
|
|
68022
|
-
if (Array.isArray(
|
|
68778
|
+
if (Array.isArray(tasks2)) {
|
|
68023
68779
|
results = [];
|
|
68024
|
-
pending =
|
|
68780
|
+
pending = tasks2.length;
|
|
68025
68781
|
} else {
|
|
68026
|
-
keys = Object.keys(
|
|
68782
|
+
keys = Object.keys(tasks2);
|
|
68027
68783
|
results = {};
|
|
68028
68784
|
pending = keys.length;
|
|
68029
68785
|
}
|
|
@@ -68045,12 +68801,12 @@ var require_run_parallel = __commonJS({
|
|
|
68045
68801
|
done(null);
|
|
68046
68802
|
} else if (keys) {
|
|
68047
68803
|
keys.forEach(function(key) {
|
|
68048
|
-
|
|
68804
|
+
tasks2[key](function(err, result) {
|
|
68049
68805
|
each(key, err, result);
|
|
68050
68806
|
});
|
|
68051
68807
|
});
|
|
68052
68808
|
} else {
|
|
68053
|
-
|
|
68809
|
+
tasks2.forEach(function(task, i) {
|
|
68054
68810
|
task(function(err, result) {
|
|
68055
68811
|
each(i, err, result);
|
|
68056
68812
|
});
|
|
@@ -68167,8 +68923,8 @@ var require_async2 = __commonJS({
|
|
|
68167
68923
|
callSuccessCallback(callback, entries);
|
|
68168
68924
|
return;
|
|
68169
68925
|
}
|
|
68170
|
-
const
|
|
68171
|
-
rpl(
|
|
68926
|
+
const tasks2 = entries.map((entry) => makeRplTaskEntry(entry, settings));
|
|
68927
|
+
rpl(tasks2, (rplError, rplEntries) => {
|
|
68172
68928
|
if (rplError !== null) {
|
|
68173
68929
|
callFailureCallback(callback, rplError);
|
|
68174
68930
|
return;
|
|
@@ -68204,7 +68960,7 @@ var require_async2 = __commonJS({
|
|
|
68204
68960
|
callFailureCallback(callback, readdirError);
|
|
68205
68961
|
return;
|
|
68206
68962
|
}
|
|
68207
|
-
const
|
|
68963
|
+
const tasks2 = names.map((name) => {
|
|
68208
68964
|
const path = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
|
68209
68965
|
return (done) => {
|
|
68210
68966
|
fsStat.stat(path, settings.fsStatSettings, (error2, stats) => {
|
|
@@ -68224,7 +68980,7 @@ var require_async2 = __commonJS({
|
|
|
68224
68980
|
});
|
|
68225
68981
|
};
|
|
68226
68982
|
});
|
|
68227
|
-
rpl(
|
|
68983
|
+
rpl(tasks2, (rplError, entries) => {
|
|
68228
68984
|
if (rplError !== null) {
|
|
68229
68985
|
callFailureCallback(callback, rplError);
|
|
68230
68986
|
return;
|
|
@@ -68489,12 +69245,12 @@ var require_queue = __commonJS({
|
|
|
68489
69245
|
}
|
|
68490
69246
|
function getQueue() {
|
|
68491
69247
|
var current = queueHead;
|
|
68492
|
-
var
|
|
69248
|
+
var tasks2 = [];
|
|
68493
69249
|
while (current) {
|
|
68494
|
-
|
|
69250
|
+
tasks2.push(current.value);
|
|
68495
69251
|
current = current.next;
|
|
68496
69252
|
}
|
|
68497
|
-
return
|
|
69253
|
+
return tasks2;
|
|
68498
69254
|
}
|
|
68499
69255
|
function resume() {
|
|
68500
69256
|
if (!self2.paused) return;
|
|
@@ -69860,9 +70616,9 @@ var require_out4 = __commonJS({
|
|
|
69860
70616
|
function getWorks(source, _Provider, options2) {
|
|
69861
70617
|
const patterns = [].concat(source);
|
|
69862
70618
|
const settings = new settings_1.default(options2);
|
|
69863
|
-
const
|
|
70619
|
+
const tasks2 = taskManager.generate(patterns, settings);
|
|
69864
70620
|
const provider = new _Provider(settings);
|
|
69865
|
-
return
|
|
70621
|
+
return tasks2.map(provider.read, provider);
|
|
69866
70622
|
}
|
|
69867
70623
|
function assertPatternsInput(input) {
|
|
69868
70624
|
const source = [].concat(input);
|
|
@@ -69876,7 +70632,7 @@ var require_out4 = __commonJS({
|
|
|
69876
70632
|
});
|
|
69877
70633
|
|
|
69878
70634
|
// src/tools/builtin/glob.ts
|
|
69879
|
-
import { statSync as
|
|
70635
|
+
import { statSync as statSync4, existsSync as existsSync15 } from "fs";
|
|
69880
70636
|
import { resolve as resolve5, isAbsolute as isAbsolute4 } from "path";
|
|
69881
70637
|
function resolvePath4(p) {
|
|
69882
70638
|
if (isAbsolute4(p)) return p;
|
|
@@ -69942,7 +70698,7 @@ var init_glob = __esm({
|
|
|
69942
70698
|
},
|
|
69943
70699
|
async call(input, context) {
|
|
69944
70700
|
const cwd2 = input.path ? resolvePath4(input.path) : process.cwd();
|
|
69945
|
-
if (input.path && !
|
|
70701
|
+
if (input.path && !existsSync15(cwd2)) {
|
|
69946
70702
|
return {
|
|
69947
70703
|
data: {
|
|
69948
70704
|
files: [],
|
|
@@ -69973,7 +70729,7 @@ var init_glob = __esm({
|
|
|
69973
70729
|
});
|
|
69974
70730
|
const withStats = allFiles.map((f) => {
|
|
69975
70731
|
try {
|
|
69976
|
-
const stat =
|
|
70732
|
+
const stat = statSync4(f);
|
|
69977
70733
|
return { path: f, mtime: stat.mtimeMs };
|
|
69978
70734
|
} catch {
|
|
69979
70735
|
return { path: f, mtime: 0 };
|
|
@@ -70275,7 +71031,7 @@ function filterToolsForAgentType(tools, typeDef) {
|
|
|
70275
71031
|
const excluded = new Set(typeDef.excludedTools ?? []);
|
|
70276
71032
|
return tools.filter((t) => allowed.has(t.name) && !excluded.has(t.name));
|
|
70277
71033
|
}
|
|
70278
|
-
function buildSubAgentSystemPrompt(
|
|
71034
|
+
function buildSubAgentSystemPrompt(_agentType, typeDef) {
|
|
70279
71035
|
return `You are a ${typeDef.description}
|
|
70280
71036
|
|
|
70281
71037
|
You are a sub-agent spawned to handle a specific task. Complete the task thoroughly and return your findings/results.
|
|
@@ -70294,7 +71050,7 @@ function extractText(message) {
|
|
|
70294
71050
|
}
|
|
70295
71051
|
return "(no text content)";
|
|
70296
71052
|
}
|
|
70297
|
-
function runAgentInBackground(agentId, record2, input, tools, systemPrompt, model, parentContext) {
|
|
71053
|
+
function runAgentInBackground(agentId, bgTaskId, record2, input, tools, systemPrompt, model, parentContext) {
|
|
70298
71054
|
const abortController = new AbortController();
|
|
70299
71055
|
runAgentLoop(
|
|
70300
71056
|
[{ role: "user", content: input.prompt }],
|
|
@@ -70307,22 +71063,40 @@ function runAgentInBackground(agentId, record2, input, tools, systemPrompt, mode
|
|
|
70307
71063
|
signal: abortController.signal,
|
|
70308
71064
|
permissionContext: parentContext.getAppState().toolPermissionContext,
|
|
70309
71065
|
agentId,
|
|
70310
|
-
maxTurns: 25
|
|
71066
|
+
maxTurns: 25,
|
|
71067
|
+
onTextDelta: (_text) => {
|
|
71068
|
+
updateTask(bgTaskId, {
|
|
71069
|
+
progress: {
|
|
71070
|
+
lastActivity: (/* @__PURE__ */ new Date()).toISOString()
|
|
71071
|
+
}
|
|
71072
|
+
});
|
|
71073
|
+
}
|
|
70311
71074
|
}
|
|
70312
71075
|
).then((result) => {
|
|
70313
71076
|
const lastAssistant = [...result.messages].reverse().find((m) => m.role === "assistant");
|
|
71077
|
+
const resultText = extractText(lastAssistant);
|
|
70314
71078
|
record2.status = "completed";
|
|
70315
|
-
record2.result =
|
|
71079
|
+
record2.result = resultText;
|
|
71080
|
+
const totalTokens = result.usage.totalInputTokens + result.usage.totalOutputTokens;
|
|
71081
|
+
updateTask(bgTaskId, {
|
|
71082
|
+
progress: {
|
|
71083
|
+
tokenCount: totalTokens,
|
|
71084
|
+
lastActivity: (/* @__PURE__ */ new Date()).toISOString()
|
|
71085
|
+
}
|
|
71086
|
+
});
|
|
71087
|
+
completeTask(bgTaskId, resultText);
|
|
70316
71088
|
}).catch((error2) => {
|
|
71089
|
+
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
70317
71090
|
record2.status = "failed";
|
|
70318
|
-
record2.error =
|
|
71091
|
+
record2.error = errorMsg;
|
|
71092
|
+
failTask(bgTaskId, errorMsg);
|
|
70319
71093
|
});
|
|
70320
71094
|
}
|
|
70321
71095
|
function truncate3(str, maxLen) {
|
|
70322
71096
|
if (str.length <= maxLen) return str;
|
|
70323
71097
|
return str.slice(0, maxLen - 100) + "\n\n... (truncated)";
|
|
70324
71098
|
}
|
|
70325
|
-
var BUILTIN_AGENT_TYPES, AgentInputSchema, AgentOutputSchema,
|
|
71099
|
+
var BUILTIN_AGENT_TYPES, AgentInputSchema, AgentOutputSchema, nextAgentId2, runningAgents, agentTool, AGENT_PROMPT;
|
|
70326
71100
|
var init_agent = __esm({
|
|
70327
71101
|
"src/tools/builtin/agent.ts"() {
|
|
70328
71102
|
"use strict";
|
|
@@ -70330,6 +71104,7 @@ var init_agent = __esm({
|
|
|
70330
71104
|
init_constants();
|
|
70331
71105
|
init_agent_loop();
|
|
70332
71106
|
init_client();
|
|
71107
|
+
init_background_tasks();
|
|
70333
71108
|
BUILTIN_AGENT_TYPES = {
|
|
70334
71109
|
"general-purpose": {
|
|
70335
71110
|
name: "general-purpose",
|
|
@@ -70372,7 +71147,7 @@ var init_agent = __esm({
|
|
|
70372
71147
|
usage: external_exports.object({ inputTokens: external_exports.number(), outputTokens: external_exports.number() }),
|
|
70373
71148
|
backgrounded: external_exports.boolean().optional()
|
|
70374
71149
|
});
|
|
70375
|
-
|
|
71150
|
+
nextAgentId2 = 1;
|
|
70376
71151
|
runningAgents = /* @__PURE__ */ new Map();
|
|
70377
71152
|
agentTool = {
|
|
70378
71153
|
name: AGENT_TOOL,
|
|
@@ -70420,7 +71195,7 @@ var init_agent = __esm({
|
|
|
70420
71195
|
return { behavior: "allow", updatedInput: input };
|
|
70421
71196
|
},
|
|
70422
71197
|
async call(input, context) {
|
|
70423
|
-
const agentId = `agent-${
|
|
71198
|
+
const agentId = `agent-${nextAgentId2++}`;
|
|
70424
71199
|
const agentType = input.subagent_type ?? "general-purpose";
|
|
70425
71200
|
const typeDef = BUILTIN_AGENT_TYPES[agentType] ?? BUILTIN_AGENT_TYPES["general-purpose"];
|
|
70426
71201
|
const model = input.model ?? "sonnet";
|
|
@@ -70441,17 +71216,18 @@ var init_agent = __esm({
|
|
|
70441
71216
|
inputSchema: { type: "object", properties: {} },
|
|
70442
71217
|
isReadOnly: t.isReadOnly(),
|
|
70443
71218
|
isConcurrencySafe: t.isConcurrencySafe(),
|
|
70444
|
-
call: async (toolInput,
|
|
71219
|
+
call: async (toolInput, _toolCtx) => {
|
|
70445
71220
|
const result = await t.call(toolInput, context);
|
|
70446
71221
|
return { data: result.data };
|
|
70447
71222
|
}
|
|
70448
71223
|
}));
|
|
70449
71224
|
const systemPrompt = buildSubAgentSystemPrompt(agentType, typeDef);
|
|
70450
71225
|
if (input.run_in_background) {
|
|
70451
|
-
|
|
71226
|
+
const bgTask = createTask("agent", input.prompt.slice(0, 100));
|
|
71227
|
+
runAgentInBackground(agentId, bgTask.id, agentRecord, input, toolHandlers, systemPrompt, model, context);
|
|
70452
71228
|
return {
|
|
70453
71229
|
data: {
|
|
70454
|
-
result: `Agent ${agentId} (${agentType}) started in background.
|
|
71230
|
+
result: `Agent ${agentId} (${agentType}) started in background. Task ID: ${bgTask.id}. Use TaskOutput to check its status.`,
|
|
70455
71231
|
agentId,
|
|
70456
71232
|
agentType,
|
|
70457
71233
|
model,
|
|
@@ -70487,7 +71263,10 @@ var init_agent = __esm({
|
|
|
70487
71263
|
agentType,
|
|
70488
71264
|
model,
|
|
70489
71265
|
totalTurns: loopResult.totalTurns,
|
|
70490
|
-
usage:
|
|
71266
|
+
usage: {
|
|
71267
|
+
inputTokens: loopResult.usage.totalInputTokens,
|
|
71268
|
+
outputTokens: loopResult.usage.totalOutputTokens
|
|
71269
|
+
}
|
|
70491
71270
|
}
|
|
70492
71271
|
};
|
|
70493
71272
|
} catch (error2) {
|
|
@@ -70638,11 +71417,11 @@ var init_todos = __esm({
|
|
|
70638
71417
|
});
|
|
70639
71418
|
return result.map(mapFromHasna);
|
|
70640
71419
|
}
|
|
70641
|
-
let
|
|
71420
|
+
let tasks2 = [...this.fallbackStore.values()];
|
|
70642
71421
|
if (filter?.status) {
|
|
70643
|
-
|
|
71422
|
+
tasks2 = tasks2.filter((t) => t.status === filter.status);
|
|
70644
71423
|
}
|
|
70645
|
-
return
|
|
71424
|
+
return tasks2;
|
|
70646
71425
|
}
|
|
70647
71426
|
async updateTask(id, params) {
|
|
70648
71427
|
if (this.hasnaTodos) {
|
|
@@ -70715,23 +71494,23 @@ var init_todos = __esm({
|
|
|
70715
71494
|
await this.hasnaTodos.sync({ taskListId: this.taskListId, direction: "push" });
|
|
70716
71495
|
return;
|
|
70717
71496
|
}
|
|
70718
|
-
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync9, existsSync:
|
|
70719
|
-
const { join:
|
|
70720
|
-
if (!
|
|
70721
|
-
const
|
|
70722
|
-
for (const task of
|
|
70723
|
-
const filePath =
|
|
71497
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync9, existsSync: existsSync19 } = await import("fs");
|
|
71498
|
+
const { join: join12 } = await import("path");
|
|
71499
|
+
if (!existsSync19(dir)) mkdirSync9(dir, { recursive: true });
|
|
71500
|
+
const tasks2 = await this.listTasks();
|
|
71501
|
+
for (const task of tasks2) {
|
|
71502
|
+
const filePath = join12(dir, `${task.id}.json`);
|
|
70724
71503
|
writeFileSync10(filePath, JSON.stringify(task, null, 2), "utf-8");
|
|
70725
71504
|
}
|
|
70726
71505
|
}
|
|
70727
71506
|
// ── Stats ──────────────────────────────────────────────────────
|
|
70728
71507
|
async getStats() {
|
|
70729
|
-
const
|
|
71508
|
+
const tasks2 = await this.listTasks();
|
|
70730
71509
|
return {
|
|
70731
|
-
total:
|
|
70732
|
-
pending:
|
|
70733
|
-
inProgress:
|
|
70734
|
-
completed:
|
|
71510
|
+
total: tasks2.length,
|
|
71511
|
+
pending: tasks2.filter((t) => t.status === "pending").length,
|
|
71512
|
+
inProgress: tasks2.filter((t) => t.status === "in_progress").length,
|
|
71513
|
+
completed: tasks2.filter((t) => t.status === "completed").length
|
|
70735
71514
|
};
|
|
70736
71515
|
}
|
|
70737
71516
|
};
|
|
@@ -70915,8 +71694,8 @@ var init_tasks = __esm({
|
|
|
70915
71694
|
},
|
|
70916
71695
|
async call() {
|
|
70917
71696
|
const todos = getTodosIntegration();
|
|
70918
|
-
const
|
|
70919
|
-
return { data: { tasks } };
|
|
71697
|
+
const tasks2 = await todos.listTasks();
|
|
71698
|
+
return { data: { tasks: tasks2 } };
|
|
70920
71699
|
},
|
|
70921
71700
|
mapToolResultToToolResultBlockParam(result, toolUseId) {
|
|
70922
71701
|
if (result.tasks.length === 0) {
|
|
@@ -71058,6 +71837,251 @@ var init_tasks = __esm({
|
|
|
71058
71837
|
}
|
|
71059
71838
|
});
|
|
71060
71839
|
|
|
71840
|
+
// src/tools/builtin/task-output.ts
|
|
71841
|
+
var MAX_OUTPUT_CHARS, TaskOutputInputSchema, TaskOutputOutputSchema, taskOutputTool, TaskStopInputSchema, TaskStopOutputSchema, taskStopTool, TASK_OUTPUT_PROMPT, TASK_STOP_PROMPT;
|
|
71842
|
+
var init_task_output = __esm({
|
|
71843
|
+
"src/tools/builtin/task-output.ts"() {
|
|
71844
|
+
"use strict";
|
|
71845
|
+
init_zod();
|
|
71846
|
+
init_constants();
|
|
71847
|
+
init_background_tasks();
|
|
71848
|
+
MAX_OUTPUT_CHARS = 3e4;
|
|
71849
|
+
TaskOutputInputSchema = external_exports.strictObject({
|
|
71850
|
+
task_id: external_exports.string().describe("The ID of the background task to check (e.g. 'bg-1', 'agent-2')")
|
|
71851
|
+
});
|
|
71852
|
+
TaskOutputOutputSchema = external_exports.object({
|
|
71853
|
+
task_id: external_exports.string(),
|
|
71854
|
+
status: external_exports.string(),
|
|
71855
|
+
output: external_exports.string(),
|
|
71856
|
+
exitCode: external_exports.number().nullable().optional(),
|
|
71857
|
+
durationMs: external_exports.number().optional(),
|
|
71858
|
+
error: external_exports.string().optional(),
|
|
71859
|
+
progress: external_exports.object({
|
|
71860
|
+
tokenCount: external_exports.number().optional(),
|
|
71861
|
+
lastActivity: external_exports.string().optional()
|
|
71862
|
+
}).optional()
|
|
71863
|
+
});
|
|
71864
|
+
taskOutputTool = {
|
|
71865
|
+
name: TASK_OUTPUT_TOOL,
|
|
71866
|
+
searchHint: "check status and output of a background task",
|
|
71867
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
71868
|
+
shouldDefer: true,
|
|
71869
|
+
async description() {
|
|
71870
|
+
return "Check the status and output of a background task";
|
|
71871
|
+
},
|
|
71872
|
+
async prompt() {
|
|
71873
|
+
return TASK_OUTPUT_PROMPT;
|
|
71874
|
+
},
|
|
71875
|
+
get inputSchema() {
|
|
71876
|
+
return TaskOutputInputSchema;
|
|
71877
|
+
},
|
|
71878
|
+
get outputSchema() {
|
|
71879
|
+
return TaskOutputOutputSchema;
|
|
71880
|
+
},
|
|
71881
|
+
userFacingName() {
|
|
71882
|
+
return "TaskOutput";
|
|
71883
|
+
},
|
|
71884
|
+
isEnabled() {
|
|
71885
|
+
return true;
|
|
71886
|
+
},
|
|
71887
|
+
isConcurrencySafe() {
|
|
71888
|
+
return true;
|
|
71889
|
+
},
|
|
71890
|
+
isReadOnly() {
|
|
71891
|
+
return true;
|
|
71892
|
+
},
|
|
71893
|
+
toAutoClassifierInput(input) {
|
|
71894
|
+
return input.task_id;
|
|
71895
|
+
},
|
|
71896
|
+
getActivityDescription(input) {
|
|
71897
|
+
return `Checking task ${input.task_id}`;
|
|
71898
|
+
},
|
|
71899
|
+
async validateInput(input) {
|
|
71900
|
+
if (!input.task_id || !input.task_id.trim()) {
|
|
71901
|
+
return { result: false, message: "task_id is required", errorCode: 1 };
|
|
71902
|
+
}
|
|
71903
|
+
return { result: true };
|
|
71904
|
+
},
|
|
71905
|
+
async checkPermissions(input) {
|
|
71906
|
+
return { behavior: "allow", updatedInput: input };
|
|
71907
|
+
},
|
|
71908
|
+
async call(input) {
|
|
71909
|
+
const task = getTask(input.task_id);
|
|
71910
|
+
if (!task) {
|
|
71911
|
+
return {
|
|
71912
|
+
data: {
|
|
71913
|
+
task_id: input.task_id,
|
|
71914
|
+
status: "not_found",
|
|
71915
|
+
output: `No background task found with ID "${input.task_id}". Use TaskList or check the ID returned when you started the background task.`,
|
|
71916
|
+
error: `Task "${input.task_id}" not found`
|
|
71917
|
+
}
|
|
71918
|
+
};
|
|
71919
|
+
}
|
|
71920
|
+
let output = readTaskOutput(task.id);
|
|
71921
|
+
if (!output && task.output) output = task.output;
|
|
71922
|
+
if (output.length > MAX_OUTPUT_CHARS) {
|
|
71923
|
+
const half = Math.floor(MAX_OUTPUT_CHARS / 2);
|
|
71924
|
+
output = output.slice(0, half) + `
|
|
71925
|
+
|
|
71926
|
+
... (${output.length - MAX_OUTPUT_CHARS} characters truncated) ...
|
|
71927
|
+
|
|
71928
|
+
` + output.slice(-half);
|
|
71929
|
+
}
|
|
71930
|
+
const durationMs = task.endTime ? task.endTime - task.startTime : Date.now() - task.startTime;
|
|
71931
|
+
return {
|
|
71932
|
+
data: {
|
|
71933
|
+
task_id: task.id,
|
|
71934
|
+
status: task.status,
|
|
71935
|
+
output: output || "(no output yet)",
|
|
71936
|
+
exitCode: task.exitCode,
|
|
71937
|
+
durationMs,
|
|
71938
|
+
error: task.error,
|
|
71939
|
+
progress: task.progress
|
|
71940
|
+
}
|
|
71941
|
+
};
|
|
71942
|
+
},
|
|
71943
|
+
mapToolResultToToolResultBlockParam(result, toolUseId) {
|
|
71944
|
+
const parts = [];
|
|
71945
|
+
parts.push(`Task: ${result.task_id}`);
|
|
71946
|
+
parts.push(`Status: ${result.status}`);
|
|
71947
|
+
if (result.durationMs != null) {
|
|
71948
|
+
const sec = (result.durationMs / 1e3).toFixed(1);
|
|
71949
|
+
parts.push(`Duration: ${sec}s`);
|
|
71950
|
+
}
|
|
71951
|
+
if (result.exitCode != null) {
|
|
71952
|
+
parts.push(`Exit code: ${result.exitCode}`);
|
|
71953
|
+
}
|
|
71954
|
+
if (result.progress?.tokenCount) {
|
|
71955
|
+
parts.push(`Tokens: ${result.progress.tokenCount}`);
|
|
71956
|
+
}
|
|
71957
|
+
if (result.progress?.lastActivity) {
|
|
71958
|
+
parts.push(`Last activity: ${result.progress.lastActivity}`);
|
|
71959
|
+
}
|
|
71960
|
+
if (result.error) {
|
|
71961
|
+
parts.push(`Error: ${result.error}`);
|
|
71962
|
+
}
|
|
71963
|
+
parts.push("");
|
|
71964
|
+
parts.push(result.output);
|
|
71965
|
+
return {
|
|
71966
|
+
type: "tool_result",
|
|
71967
|
+
tool_use_id: toolUseId,
|
|
71968
|
+
content: parts.join("\n"),
|
|
71969
|
+
is_error: result.status === "not_found"
|
|
71970
|
+
};
|
|
71971
|
+
}
|
|
71972
|
+
};
|
|
71973
|
+
TaskStopInputSchema = external_exports.strictObject({
|
|
71974
|
+
task_id: external_exports.string().describe("The ID of the background task to stop (e.g. 'bg-1', 'agent-2')")
|
|
71975
|
+
});
|
|
71976
|
+
TaskStopOutputSchema = external_exports.object({
|
|
71977
|
+
task_id: external_exports.string(),
|
|
71978
|
+
status: external_exports.string(),
|
|
71979
|
+
message: external_exports.string()
|
|
71980
|
+
});
|
|
71981
|
+
taskStopTool = {
|
|
71982
|
+
name: TASK_STOP_TOOL,
|
|
71983
|
+
searchHint: "stop kill a running background task",
|
|
71984
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
71985
|
+
shouldDefer: true,
|
|
71986
|
+
async description() {
|
|
71987
|
+
return "Stop a running background task";
|
|
71988
|
+
},
|
|
71989
|
+
async prompt() {
|
|
71990
|
+
return TASK_STOP_PROMPT;
|
|
71991
|
+
},
|
|
71992
|
+
get inputSchema() {
|
|
71993
|
+
return TaskStopInputSchema;
|
|
71994
|
+
},
|
|
71995
|
+
get outputSchema() {
|
|
71996
|
+
return TaskStopOutputSchema;
|
|
71997
|
+
},
|
|
71998
|
+
userFacingName() {
|
|
71999
|
+
return "TaskStop";
|
|
72000
|
+
},
|
|
72001
|
+
isEnabled() {
|
|
72002
|
+
return true;
|
|
72003
|
+
},
|
|
72004
|
+
isConcurrencySafe() {
|
|
72005
|
+
return true;
|
|
72006
|
+
},
|
|
72007
|
+
isReadOnly() {
|
|
72008
|
+
return false;
|
|
72009
|
+
},
|
|
72010
|
+
toAutoClassifierInput(input) {
|
|
72011
|
+
return input.task_id;
|
|
72012
|
+
},
|
|
72013
|
+
getActivityDescription(input) {
|
|
72014
|
+
return `Stopping task ${input.task_id}`;
|
|
72015
|
+
},
|
|
72016
|
+
async validateInput(input) {
|
|
72017
|
+
if (!input.task_id || !input.task_id.trim()) {
|
|
72018
|
+
return { result: false, message: "task_id is required", errorCode: 1 };
|
|
72019
|
+
}
|
|
72020
|
+
return { result: true };
|
|
72021
|
+
},
|
|
72022
|
+
async checkPermissions(input) {
|
|
72023
|
+
return { behavior: "allow", updatedInput: input };
|
|
72024
|
+
},
|
|
72025
|
+
async call(input) {
|
|
72026
|
+
const task = getTask(input.task_id);
|
|
72027
|
+
if (!task) {
|
|
72028
|
+
return {
|
|
72029
|
+
data: {
|
|
72030
|
+
task_id: input.task_id,
|
|
72031
|
+
status: "not_found",
|
|
72032
|
+
message: `No background task found with ID "${input.task_id}".`
|
|
72033
|
+
}
|
|
72034
|
+
};
|
|
72035
|
+
}
|
|
72036
|
+
if (task.status !== "running") {
|
|
72037
|
+
return {
|
|
72038
|
+
data: {
|
|
72039
|
+
task_id: task.id,
|
|
72040
|
+
status: task.status,
|
|
72041
|
+
message: `Task ${task.id} is already ${task.status} \u2014 cannot stop.`
|
|
72042
|
+
}
|
|
72043
|
+
};
|
|
72044
|
+
}
|
|
72045
|
+
killTask(task.id);
|
|
72046
|
+
return {
|
|
72047
|
+
data: {
|
|
72048
|
+
task_id: task.id,
|
|
72049
|
+
status: "killed",
|
|
72050
|
+
message: `Task ${task.id} has been killed.`
|
|
72051
|
+
}
|
|
72052
|
+
};
|
|
72053
|
+
},
|
|
72054
|
+
mapToolResultToToolResultBlockParam(result, toolUseId) {
|
|
72055
|
+
return {
|
|
72056
|
+
type: "tool_result",
|
|
72057
|
+
tool_use_id: toolUseId,
|
|
72058
|
+
content: result.message,
|
|
72059
|
+
is_error: result.status === "not_found"
|
|
72060
|
+
};
|
|
72061
|
+
}
|
|
72062
|
+
};
|
|
72063
|
+
TASK_OUTPUT_PROMPT = `Check the status and output of a background task.
|
|
72064
|
+
|
|
72065
|
+
Use this tool when you have previously started a bash command or agent with run_in_background:true
|
|
72066
|
+
and need to check whether it has completed, and retrieve its output.
|
|
72067
|
+
|
|
72068
|
+
The task_id is returned when you start a background task (e.g., "bg-1" for bash, "agent-1" for agents).
|
|
72069
|
+
|
|
72070
|
+
The tool returns:
|
|
72071
|
+
- status: "running", "completed", "failed", or "killed"
|
|
72072
|
+
- output: The stdout/stderr from the task (truncated to 30000 chars)
|
|
72073
|
+
- exitCode: The exit code (for bash tasks)
|
|
72074
|
+
- durationMs: How long the task has been running or ran
|
|
72075
|
+
- progress: For agents, includes tokenCount and lastActivity`;
|
|
72076
|
+
TASK_STOP_PROMPT = `Stop a running background task.
|
|
72077
|
+
|
|
72078
|
+
Use this tool to kill a background bash command or agent that is still running.
|
|
72079
|
+
The task will be marked as "killed" and its process terminated.
|
|
72080
|
+
|
|
72081
|
+
The task_id is returned when you start a background task (e.g., "bg-1" for bash, "agent-1" for agents).`;
|
|
72082
|
+
}
|
|
72083
|
+
});
|
|
72084
|
+
|
|
71061
72085
|
// src/tools/builtin/ask-user.ts
|
|
71062
72086
|
var OptionSchema, QuestionSchema, AskUserInputSchema, AskUserOutputSchema, askUserQuestionTool, ASK_USER_PROMPT;
|
|
71063
72087
|
var init_ask_user = __esm({
|
|
@@ -71464,17 +72488,17 @@ LSP servers must be configured for the file type.`;
|
|
|
71464
72488
|
});
|
|
71465
72489
|
|
|
71466
72490
|
// src/tools/builtin/plan-mode.ts
|
|
71467
|
-
import { readFileSync as
|
|
71468
|
-
import { join as
|
|
72491
|
+
import { readFileSync as readFileSync13, existsSync as existsSync16 } from "fs";
|
|
72492
|
+
import { join as join10 } from "path";
|
|
71469
72493
|
function getPlanFilePath(agentId) {
|
|
71470
72494
|
const dir = getPlansDir();
|
|
71471
72495
|
const name = agentId ? `plan-${agentId}.md` : "plan.md";
|
|
71472
|
-
return
|
|
72496
|
+
return join10(dir, name);
|
|
71473
72497
|
}
|
|
71474
72498
|
function readPlanFile(agentId) {
|
|
71475
72499
|
const path = getPlanFilePath(agentId);
|
|
71476
|
-
if (!
|
|
71477
|
-
return
|
|
72500
|
+
if (!existsSync16(path)) return null;
|
|
72501
|
+
return readFileSync13(path, "utf-8");
|
|
71478
72502
|
}
|
|
71479
72503
|
var _hasExitedPlanMode, EnterPlanInputSchema, EnterPlanOutputSchema, enterPlanModeTool, ExitPlanInputSchema, ExitPlanOutputSchema, exitPlanModeTool, ENTER_PLAN_PROMPT, EXIT_PLAN_PROMPT;
|
|
71480
72504
|
var init_plan_mode = __esm({
|
|
@@ -71702,8 +72726,43 @@ function getEnabledTools() {
|
|
|
71702
72726
|
}
|
|
71703
72727
|
return tools;
|
|
71704
72728
|
}
|
|
71705
|
-
function
|
|
71706
|
-
|
|
72729
|
+
function setDeferredToolSchemas(schemas) {
|
|
72730
|
+
for (const s of schemas) {
|
|
72731
|
+
deferredToolSchemas.set(s.name, s);
|
|
72732
|
+
}
|
|
72733
|
+
}
|
|
72734
|
+
function getAllDeferredToolSchemas() {
|
|
72735
|
+
return [...deferredToolSchemas.values()];
|
|
72736
|
+
}
|
|
72737
|
+
function searchDeferredToolSchemas(query, maxResults = 5) {
|
|
72738
|
+
const queryLower = query.toLowerCase();
|
|
72739
|
+
const queryTerms = queryLower.split(/\s+/);
|
|
72740
|
+
if (queryLower.startsWith("select:")) {
|
|
72741
|
+
const names = query.slice(7).split(",").map((n) => n.trim());
|
|
72742
|
+
return names.map((n) => deferredToolSchemas.get(n)).filter((s) => s !== void 0);
|
|
72743
|
+
}
|
|
72744
|
+
const requiredTerms = queryTerms.filter((t) => t.startsWith("+")).map((t) => t.slice(1));
|
|
72745
|
+
const searchTerms = queryTerms.filter((t) => !t.startsWith("+"));
|
|
72746
|
+
const results = [];
|
|
72747
|
+
for (const schema of deferredToolSchemas.values()) {
|
|
72748
|
+
const nameLower = schema.name.toLowerCase();
|
|
72749
|
+
const descLower = schema.description.toLowerCase();
|
|
72750
|
+
if (requiredTerms.length > 0 && !requiredTerms.every((rt) => nameLower.includes(rt))) {
|
|
72751
|
+
continue;
|
|
72752
|
+
}
|
|
72753
|
+
let score = 0;
|
|
72754
|
+
const allTerms = searchTerms.length > 0 ? searchTerms : requiredTerms;
|
|
72755
|
+
for (const term of allTerms) {
|
|
72756
|
+
if (nameLower === term) score += 10;
|
|
72757
|
+
else if (nameLower.includes(term)) score += 5;
|
|
72758
|
+
if (descLower.includes(term)) score += 3;
|
|
72759
|
+
}
|
|
72760
|
+
if (score > 0) {
|
|
72761
|
+
results.push({ schema, score });
|
|
72762
|
+
}
|
|
72763
|
+
}
|
|
72764
|
+
results.sort((a, b) => b.score - a.score);
|
|
72765
|
+
return results.slice(0, maxResults).map((r) => r.schema);
|
|
71707
72766
|
}
|
|
71708
72767
|
function searchTools(query, maxResults = 5) {
|
|
71709
72768
|
const results = [];
|
|
@@ -71741,7 +72800,7 @@ function matchScore(name, hint, queryTerms) {
|
|
|
71741
72800
|
}
|
|
71742
72801
|
return score;
|
|
71743
72802
|
}
|
|
71744
|
-
var registeredTools, deferredTools, disabledTools, mcpTools;
|
|
72803
|
+
var registeredTools, deferredTools, disabledTools, mcpTools, deferredToolSchemas;
|
|
71745
72804
|
var init_registry2 = __esm({
|
|
71746
72805
|
"src/tools/registry.ts"() {
|
|
71747
72806
|
"use strict";
|
|
@@ -71750,6 +72809,7 @@ var init_registry2 = __esm({
|
|
|
71750
72809
|
deferredTools = /* @__PURE__ */ new Map();
|
|
71751
72810
|
disabledTools = /* @__PURE__ */ new Set();
|
|
71752
72811
|
mcpTools = /* @__PURE__ */ new Map();
|
|
72812
|
+
deferredToolSchemas = /* @__PURE__ */ new Map();
|
|
71753
72813
|
}
|
|
71754
72814
|
});
|
|
71755
72815
|
|
|
@@ -71797,6 +72857,24 @@ function simpleTool(opts) {
|
|
|
71797
72857
|
mapToolResultToToolResultBlockParam: opts.mapResult
|
|
71798
72858
|
};
|
|
71799
72859
|
}
|
|
72860
|
+
function toNotebookSource(text) {
|
|
72861
|
+
const lines = text.split("\n");
|
|
72862
|
+
return lines.map(
|
|
72863
|
+
(l, i) => i < lines.length - 1 ? l + "\n" : l
|
|
72864
|
+
);
|
|
72865
|
+
}
|
|
72866
|
+
function createCell(cellType, source) {
|
|
72867
|
+
const base = {
|
|
72868
|
+
cell_type: cellType,
|
|
72869
|
+
metadata: {},
|
|
72870
|
+
source: toNotebookSource(source)
|
|
72871
|
+
};
|
|
72872
|
+
if (cellType === "code") {
|
|
72873
|
+
base.execution_count = null;
|
|
72874
|
+
base.outputs = [];
|
|
72875
|
+
}
|
|
72876
|
+
return base;
|
|
72877
|
+
}
|
|
71800
72878
|
var toolSearchTool, cronCreateTool, cronDeleteTool, cronListTool, enterWorktreeTool, exitWorktreeTool, notebookEditTool, configTool, sendMessageTool;
|
|
71801
72879
|
var init_misc = __esm({
|
|
71802
72880
|
"src/tools/builtin/misc.ts"() {
|
|
@@ -71806,30 +72884,68 @@ var init_misc = __esm({
|
|
|
71806
72884
|
init_constants();
|
|
71807
72885
|
toolSearchTool = simpleTool({
|
|
71808
72886
|
name: TOOL_SEARCH_TOOL,
|
|
71809
|
-
hint: "find available tools by keyword",
|
|
72887
|
+
hint: "find available tools by keyword \u2014 fetches full schemas for deferred tools",
|
|
71810
72888
|
inputSchema: external_exports.strictObject({
|
|
71811
|
-
query: external_exports.string().describe(
|
|
71812
|
-
|
|
72889
|
+
query: external_exports.string().describe(
|
|
72890
|
+
'Query to find deferred tools. Use "select:Read,Edit,Grep" for exact names, or keywords to search. Use "+slack send" to require "slack" in name.'
|
|
72891
|
+
),
|
|
72892
|
+
max_results: external_exports.number().default(5).describe("Maximum number of results to return (default: 5)")
|
|
71813
72893
|
}),
|
|
71814
72894
|
readOnly: true,
|
|
71815
72895
|
concurrent: true,
|
|
71816
72896
|
defer: false,
|
|
71817
|
-
prompt:
|
|
72897
|
+
prompt: `Fetches full schema definitions for deferred tools so they can be called.
|
|
72898
|
+
|
|
72899
|
+
Deferred tools appear by name in the "Deferred Tools" section of the system prompt. Until fetched, only the name is known \u2014 there is no parameter schema, so the tool cannot be invoked. This tool takes a query, matches it against the deferred tool list, and returns the matched tools' complete JSONSchema definitions inside a <functions> block. Once a tool's schema appears in that result, it is callable exactly like any tool defined at the top of the prompt.
|
|
72900
|
+
|
|
72901
|
+
Result format: each matched tool appears as one <function>{"description": "...", "name": "...", "parameters": {...}}</function> line inside the <functions> block \u2014 the same encoding as the tool list at the top of this prompt.
|
|
72902
|
+
|
|
72903
|
+
Query forms:
|
|
72904
|
+
- "select:Read,Edit,Grep" \u2014 fetch these exact tools by name
|
|
72905
|
+
- "notebook jupyter" \u2014 keyword search, up to max_results best matches
|
|
72906
|
+
- "+slack send" \u2014 require "slack" in the name, rank by remaining terms`,
|
|
71818
72907
|
async call(input) {
|
|
71819
|
-
const
|
|
71820
|
-
const
|
|
72908
|
+
const matchedSchemas = searchDeferredToolSchemas(input.query, input.max_results);
|
|
72909
|
+
const registryResults = searchTools(input.query, input.max_results);
|
|
72910
|
+
const allDeferred = getAllDeferredToolSchemas();
|
|
71821
72911
|
return {
|
|
71822
72912
|
data: {
|
|
71823
|
-
|
|
71824
|
-
|
|
72913
|
+
matchedSchemas,
|
|
72914
|
+
registryResults,
|
|
72915
|
+
totalDeferredCount: allDeferred.length
|
|
71825
72916
|
}
|
|
71826
72917
|
};
|
|
71827
72918
|
},
|
|
71828
72919
|
mapResult(result, id) {
|
|
71829
|
-
const
|
|
71830
|
-
|
|
71831
|
-
)
|
|
71832
|
-
|
|
72920
|
+
const sections = [];
|
|
72921
|
+
const schemas = result.matchedSchemas;
|
|
72922
|
+
if (schemas && schemas.length > 0) {
|
|
72923
|
+
const functionDefs = schemas.map(
|
|
72924
|
+
(s) => `<function>{"description": ${JSON.stringify(s.description)}, "name": ${JSON.stringify(s.name)}, "parameters": ${JSON.stringify(s.inputSchema)}}</function>`
|
|
72925
|
+
).join("\n");
|
|
72926
|
+
sections.push(`<functions>
|
|
72927
|
+
${functionDefs}
|
|
72928
|
+
</functions>`);
|
|
72929
|
+
}
|
|
72930
|
+
const registryResults = result.registryResults;
|
|
72931
|
+
if (registryResults && registryResults.length > 0) {
|
|
72932
|
+
const extraHits = registryResults.filter(
|
|
72933
|
+
(r) => !schemas?.some((s) => s.name === r.name)
|
|
72934
|
+
);
|
|
72935
|
+
if (extraHits.length > 0) {
|
|
72936
|
+
const lines = extraHits.map(
|
|
72937
|
+
(r) => `${r.name}${r.deferred ? " (deferred)" : ""}: ${r.hint}`
|
|
72938
|
+
);
|
|
72939
|
+
sections.push(lines.join("\n"));
|
|
72940
|
+
}
|
|
72941
|
+
}
|
|
72942
|
+
if (sections.length === 0) {
|
|
72943
|
+
return { type: "tool_result", tool_use_id: id, content: "No tools found matching the query." };
|
|
72944
|
+
}
|
|
72945
|
+
const footer = `
|
|
72946
|
+
|
|
72947
|
+
${result.totalDeferredCount} deferred tool(s) available. Use ToolSearch to fetch schemas for any listed tool.`;
|
|
72948
|
+
return { type: "tool_result", tool_use_id: id, content: sections.join("\n\n") + footer };
|
|
71833
72949
|
}
|
|
71834
72950
|
});
|
|
71835
72951
|
cronCreateTool = simpleTool({
|
|
@@ -71917,34 +73033,134 @@ var init_misc = __esm({
|
|
|
71917
73033
|
});
|
|
71918
73034
|
notebookEditTool = simpleTool({
|
|
71919
73035
|
name: NOTEBOOK_EDIT_TOOL,
|
|
71920
|
-
hint: "edit Jupyter notebook cells",
|
|
73036
|
+
hint: "edit Jupyter notebook cells \u2014 insert, replace, delete, move, change type",
|
|
71921
73037
|
inputSchema: external_exports.strictObject({
|
|
71922
73038
|
notebook_path: external_exports.string().describe("Path to the .ipynb file"),
|
|
71923
|
-
|
|
71924
|
-
|
|
73039
|
+
command: external_exports.enum(["insert_cell", "replace_cell", "delete_cell", "move_cell", "change_cell_type"]).describe("Operation to perform"),
|
|
73040
|
+
cell_index: external_exports.number().optional().describe("Cell index to operate on (0-based). For insert_cell, position to insert at (omit to append)."),
|
|
73041
|
+
cell_type: external_exports.enum(["code", "markdown", "raw"]).optional().describe("Cell type \u2014 required for insert_cell and change_cell_type"),
|
|
73042
|
+
new_source: external_exports.string().optional().describe("New cell content \u2014 required for insert_cell and replace_cell"),
|
|
73043
|
+
target_index: external_exports.number().optional().describe("Destination index for move_cell")
|
|
71925
73044
|
}),
|
|
71926
73045
|
readOnly: false,
|
|
71927
73046
|
concurrent: false,
|
|
71928
|
-
defer:
|
|
71929
|
-
prompt:
|
|
73047
|
+
defer: false,
|
|
73048
|
+
prompt: `Edit Jupyter notebook (.ipynb) cells. Supports 5 commands:
|
|
73049
|
+
|
|
73050
|
+
- insert_cell: Insert a new cell at cell_index (or end if omitted). Requires cell_type and new_source.
|
|
73051
|
+
- replace_cell: Replace the source of the cell at cell_index with new_source. Requires cell_index and new_source.
|
|
73052
|
+
- delete_cell: Delete the cell at cell_index. Requires cell_index.
|
|
73053
|
+
- move_cell: Move cell from cell_index to target_index. Requires cell_index and target_index.
|
|
73054
|
+
- change_cell_type: Change the type of cell at cell_index to cell_type. Requires cell_index and cell_type.
|
|
73055
|
+
|
|
73056
|
+
All metadata, outputs, and kernel info are preserved. Cell indices are 0-based.`,
|
|
71930
73057
|
async call(input) {
|
|
71931
|
-
const { readFileSync:
|
|
73058
|
+
const { readFileSync: readFileSync15, writeFileSync: writeFileSync10 } = await import("fs");
|
|
73059
|
+
const { resolve: resolve8 } = await import("path");
|
|
73060
|
+
const notebookPath = resolve8(input.notebook_path);
|
|
71932
73061
|
try {
|
|
71933
|
-
const
|
|
71934
|
-
|
|
71935
|
-
|
|
71936
|
-
|
|
71937
|
-
|
|
71938
|
-
|
|
71939
|
-
|
|
73062
|
+
const raw = readFileSync15(notebookPath, "utf-8");
|
|
73063
|
+
const notebook = JSON.parse(raw);
|
|
73064
|
+
if (!notebook.cells || !Array.isArray(notebook.cells)) {
|
|
73065
|
+
return { data: { success: false, error: "Invalid notebook: no cells array found" } };
|
|
73066
|
+
}
|
|
73067
|
+
const cells = notebook.cells;
|
|
73068
|
+
const totalCells = cells.length;
|
|
73069
|
+
switch (input.command) {
|
|
73070
|
+
case "insert_cell": {
|
|
73071
|
+
if (!input.cell_type) return { data: { success: false, error: "insert_cell requires cell_type" } };
|
|
73072
|
+
const source = input.new_source ?? "";
|
|
73073
|
+
const newCell = createCell(input.cell_type, source);
|
|
73074
|
+
const idx = input.cell_index ?? totalCells;
|
|
73075
|
+
if (idx < 0 || idx > totalCells) {
|
|
73076
|
+
return { data: { success: false, error: `cell_index ${idx} out of range (0-${totalCells})` } };
|
|
73077
|
+
}
|
|
73078
|
+
cells.splice(idx, 0, newCell);
|
|
73079
|
+
notebook.cells = cells;
|
|
73080
|
+
writeFileSync10(notebookPath, JSON.stringify(notebook, null, 1), "utf-8");
|
|
73081
|
+
return { data: { success: true, message: `Inserted ${input.cell_type} cell at index ${idx} (notebook now has ${cells.length} cells)` } };
|
|
73082
|
+
}
|
|
73083
|
+
case "replace_cell": {
|
|
73084
|
+
if (input.cell_index == null) return { data: { success: false, error: "replace_cell requires cell_index" } };
|
|
73085
|
+
if (input.new_source == null) return { data: { success: false, error: "replace_cell requires new_source" } };
|
|
73086
|
+
if (input.cell_index < 0 || input.cell_index >= totalCells) {
|
|
73087
|
+
return { data: { success: false, error: `cell_index ${input.cell_index} out of range (0-${totalCells - 1})` } };
|
|
73088
|
+
}
|
|
73089
|
+
const cell = cells[input.cell_index];
|
|
73090
|
+
cell.source = toNotebookSource(input.new_source);
|
|
73091
|
+
if (cell.cell_type === "code") {
|
|
73092
|
+
cell.outputs = [];
|
|
73093
|
+
cell.execution_count = null;
|
|
73094
|
+
}
|
|
73095
|
+
writeFileSync10(notebookPath, JSON.stringify(notebook, null, 1), "utf-8");
|
|
73096
|
+
return { data: { success: true, message: `Replaced source of cell ${input.cell_index} (${cell.cell_type})` } };
|
|
73097
|
+
}
|
|
73098
|
+
case "delete_cell": {
|
|
73099
|
+
if (input.cell_index == null) return { data: { success: false, error: "delete_cell requires cell_index" } };
|
|
73100
|
+
if (input.cell_index < 0 || input.cell_index >= totalCells) {
|
|
73101
|
+
return { data: { success: false, error: `cell_index ${input.cell_index} out of range (0-${totalCells - 1})` } };
|
|
73102
|
+
}
|
|
73103
|
+
const deletedType = cells[input.cell_index].cell_type;
|
|
73104
|
+
cells.splice(input.cell_index, 1);
|
|
73105
|
+
notebook.cells = cells;
|
|
73106
|
+
writeFileSync10(notebookPath, JSON.stringify(notebook, null, 1), "utf-8");
|
|
73107
|
+
return { data: { success: true, message: `Deleted ${deletedType} cell at index ${input.cell_index} (notebook now has ${cells.length} cells)` } };
|
|
73108
|
+
}
|
|
73109
|
+
case "move_cell": {
|
|
73110
|
+
if (input.cell_index == null) return { data: { success: false, error: "move_cell requires cell_index" } };
|
|
73111
|
+
if (input.target_index == null) return { data: { success: false, error: "move_cell requires target_index" } };
|
|
73112
|
+
if (input.cell_index < 0 || input.cell_index >= totalCells) {
|
|
73113
|
+
return { data: { success: false, error: `cell_index ${input.cell_index} out of range (0-${totalCells - 1})` } };
|
|
73114
|
+
}
|
|
73115
|
+
if (input.target_index < 0 || input.target_index >= totalCells) {
|
|
73116
|
+
return { data: { success: false, error: `target_index ${input.target_index} out of range (0-${totalCells - 1})` } };
|
|
73117
|
+
}
|
|
73118
|
+
if (input.cell_index === input.target_index) {
|
|
73119
|
+
return { data: { success: true, message: `Cell ${input.cell_index} is already at target position` } };
|
|
73120
|
+
}
|
|
73121
|
+
const [movedCell] = cells.splice(input.cell_index, 1);
|
|
73122
|
+
cells.splice(input.target_index, 0, movedCell);
|
|
73123
|
+
notebook.cells = cells;
|
|
73124
|
+
writeFileSync10(notebookPath, JSON.stringify(notebook, null, 1), "utf-8");
|
|
73125
|
+
return { data: { success: true, message: `Moved cell from index ${input.cell_index} to index ${input.target_index}` } };
|
|
73126
|
+
}
|
|
73127
|
+
case "change_cell_type": {
|
|
73128
|
+
if (input.cell_index == null) return { data: { success: false, error: "change_cell_type requires cell_index" } };
|
|
73129
|
+
if (!input.cell_type) return { data: { success: false, error: "change_cell_type requires cell_type" } };
|
|
73130
|
+
if (input.cell_index < 0 || input.cell_index >= totalCells) {
|
|
73131
|
+
return { data: { success: false, error: `cell_index ${input.cell_index} out of range (0-${totalCells - 1})` } };
|
|
73132
|
+
}
|
|
73133
|
+
const cell = cells[input.cell_index];
|
|
73134
|
+
const oldType = cell.cell_type;
|
|
73135
|
+
if (oldType === input.cell_type) {
|
|
73136
|
+
return { data: { success: true, message: `Cell ${input.cell_index} is already type ${input.cell_type}` } };
|
|
73137
|
+
}
|
|
73138
|
+
cell.cell_type = input.cell_type;
|
|
73139
|
+
if (input.cell_type === "code") {
|
|
73140
|
+
if (!("execution_count" in cell)) cell.execution_count = null;
|
|
73141
|
+
if (!("outputs" in cell)) cell.outputs = [];
|
|
73142
|
+
}
|
|
73143
|
+
if (oldType === "code" && input.cell_type !== "code") {
|
|
73144
|
+
delete cell.execution_count;
|
|
73145
|
+
delete cell.outputs;
|
|
73146
|
+
}
|
|
73147
|
+
writeFileSync10(notebookPath, JSON.stringify(notebook, null, 1), "utf-8");
|
|
73148
|
+
return { data: { success: true, message: `Changed cell ${input.cell_index} from ${oldType} to ${input.cell_type}` } };
|
|
73149
|
+
}
|
|
73150
|
+
default:
|
|
73151
|
+
return { data: { success: false, error: `Unknown command: ${input.command}` } };
|
|
71940
73152
|
}
|
|
71941
|
-
return { data: { success: false, error: "Cell index out of range" } };
|
|
71942
73153
|
} catch (e) {
|
|
71943
73154
|
return { data: { success: false, error: String(e) } };
|
|
71944
73155
|
}
|
|
71945
73156
|
},
|
|
71946
73157
|
mapResult(result, id) {
|
|
71947
|
-
return {
|
|
73158
|
+
return {
|
|
73159
|
+
type: "tool_result",
|
|
73160
|
+
tool_use_id: id,
|
|
73161
|
+
content: result.success ? result.message : `Error: ${result.error}`,
|
|
73162
|
+
...result.success ? {} : { is_error: true }
|
|
73163
|
+
};
|
|
71948
73164
|
}
|
|
71949
73165
|
});
|
|
71950
73166
|
configTool = simpleTool({
|
|
@@ -78242,9 +79458,9 @@ var init_protocol = __esm({
|
|
|
78242
79458
|
});
|
|
78243
79459
|
this.setRequestHandler(ListTasksRequestSchema, async (request, extra) => {
|
|
78244
79460
|
try {
|
|
78245
|
-
const { tasks, nextCursor } = await this._taskStore.listTasks(request.params?.cursor, extra.sessionId);
|
|
79461
|
+
const { tasks: tasks2, nextCursor } = await this._taskStore.listTasks(request.params?.cursor, extra.sessionId);
|
|
78246
79462
|
return {
|
|
78247
|
-
tasks,
|
|
79463
|
+
tasks: tasks2,
|
|
78248
79464
|
nextCursor,
|
|
78249
79465
|
_meta: {}
|
|
78250
79466
|
};
|
|
@@ -88935,6 +90151,13 @@ async function connectMcpServers(configs, batchSize = DEFAULT_BATCH_SIZE) {
|
|
|
88935
90151
|
}
|
|
88936
90152
|
return results;
|
|
88937
90153
|
}
|
|
90154
|
+
function getServerClient(name) {
|
|
90155
|
+
const server = connectedServers.get(name);
|
|
90156
|
+
return server?.client ?? null;
|
|
90157
|
+
}
|
|
90158
|
+
function getConnectedServerNames() {
|
|
90159
|
+
return [...connectedServers.keys()];
|
|
90160
|
+
}
|
|
88938
90161
|
function wrapMcpTool(serverName, mcpTool, client) {
|
|
88939
90162
|
const toolName = `mcp__${serverName}__${mcpTool.name}`;
|
|
88940
90163
|
return {
|
|
@@ -89020,6 +90243,239 @@ var init_client4 = __esm({
|
|
|
89020
90243
|
}
|
|
89021
90244
|
});
|
|
89022
90245
|
|
|
90246
|
+
// src/tools/builtin/mcp-resources.ts
|
|
90247
|
+
var ListMcpResourcesInputSchema, ListMcpResourcesOutputSchema, listMcpResourcesTool, LIST_MCP_RESOURCES_PROMPT, ReadMcpResourceInputSchema, ReadMcpResourceOutputSchema, readMcpResourceTool, READ_MCP_RESOURCE_PROMPT;
|
|
90248
|
+
var init_mcp_resources = __esm({
|
|
90249
|
+
"src/tools/builtin/mcp-resources.ts"() {
|
|
90250
|
+
"use strict";
|
|
90251
|
+
init_zod();
|
|
90252
|
+
init_constants();
|
|
90253
|
+
init_client4();
|
|
90254
|
+
ListMcpResourcesInputSchema = external_exports.strictObject({});
|
|
90255
|
+
ListMcpResourcesOutputSchema = external_exports.object({
|
|
90256
|
+
resources: external_exports.array(external_exports.object({
|
|
90257
|
+
server: external_exports.string(),
|
|
90258
|
+
uri: external_exports.string(),
|
|
90259
|
+
name: external_exports.string(),
|
|
90260
|
+
description: external_exports.string().optional(),
|
|
90261
|
+
mimeType: external_exports.string().optional()
|
|
90262
|
+
})),
|
|
90263
|
+
totalCount: external_exports.number()
|
|
90264
|
+
});
|
|
90265
|
+
listMcpResourcesTool = {
|
|
90266
|
+
name: LIST_MCP_RESOURCES_TOOL,
|
|
90267
|
+
searchHint: "list MCP server resources",
|
|
90268
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
90269
|
+
shouldDefer: true,
|
|
90270
|
+
async description() {
|
|
90271
|
+
return "List all resources available from connected MCP servers.";
|
|
90272
|
+
},
|
|
90273
|
+
async prompt() {
|
|
90274
|
+
return LIST_MCP_RESOURCES_PROMPT;
|
|
90275
|
+
},
|
|
90276
|
+
get inputSchema() {
|
|
90277
|
+
return ListMcpResourcesInputSchema;
|
|
90278
|
+
},
|
|
90279
|
+
get outputSchema() {
|
|
90280
|
+
return ListMcpResourcesOutputSchema;
|
|
90281
|
+
},
|
|
90282
|
+
userFacingName() {
|
|
90283
|
+
return "List MCP Resources";
|
|
90284
|
+
},
|
|
90285
|
+
isEnabled() {
|
|
90286
|
+
return true;
|
|
90287
|
+
},
|
|
90288
|
+
isConcurrencySafe() {
|
|
90289
|
+
return true;
|
|
90290
|
+
},
|
|
90291
|
+
isReadOnly() {
|
|
90292
|
+
return true;
|
|
90293
|
+
},
|
|
90294
|
+
toAutoClassifierInput() {
|
|
90295
|
+
return "list mcp resources";
|
|
90296
|
+
},
|
|
90297
|
+
async validateInput() {
|
|
90298
|
+
return { result: true };
|
|
90299
|
+
},
|
|
90300
|
+
async checkPermissions() {
|
|
90301
|
+
return { behavior: "allow" };
|
|
90302
|
+
},
|
|
90303
|
+
async call(_input, _context) {
|
|
90304
|
+
const serverNames = getConnectedServerNames();
|
|
90305
|
+
const resources = [];
|
|
90306
|
+
for (const serverName of serverNames) {
|
|
90307
|
+
const client = getServerClient(serverName);
|
|
90308
|
+
if (!client) continue;
|
|
90309
|
+
try {
|
|
90310
|
+
const result = await client.listResources();
|
|
90311
|
+
if (result.resources && Array.isArray(result.resources)) {
|
|
90312
|
+
for (const res of result.resources) {
|
|
90313
|
+
resources.push({
|
|
90314
|
+
server: serverName,
|
|
90315
|
+
uri: res.uri,
|
|
90316
|
+
name: res.name,
|
|
90317
|
+
description: res.description,
|
|
90318
|
+
mimeType: res.mimeType
|
|
90319
|
+
});
|
|
90320
|
+
}
|
|
90321
|
+
}
|
|
90322
|
+
} catch {
|
|
90323
|
+
}
|
|
90324
|
+
}
|
|
90325
|
+
return {
|
|
90326
|
+
data: {
|
|
90327
|
+
resources,
|
|
90328
|
+
totalCount: resources.length
|
|
90329
|
+
}
|
|
90330
|
+
};
|
|
90331
|
+
},
|
|
90332
|
+
mapToolResultToToolResultBlockParam(result, toolUseId) {
|
|
90333
|
+
if (result.resources.length === 0) {
|
|
90334
|
+
return {
|
|
90335
|
+
type: "tool_result",
|
|
90336
|
+
tool_use_id: toolUseId,
|
|
90337
|
+
content: "No resources found from any connected MCP server."
|
|
90338
|
+
};
|
|
90339
|
+
}
|
|
90340
|
+
const lines = result.resources.map((r) => {
|
|
90341
|
+
let line = `[${r.server}] ${r.uri} \u2014 ${r.name}`;
|
|
90342
|
+
if (r.description) line += ` (${r.description})`;
|
|
90343
|
+
if (r.mimeType) line += ` [${r.mimeType}]`;
|
|
90344
|
+
return line;
|
|
90345
|
+
});
|
|
90346
|
+
return {
|
|
90347
|
+
type: "tool_result",
|
|
90348
|
+
tool_use_id: toolUseId,
|
|
90349
|
+
content: `Found ${result.totalCount} resource(s):
|
|
90350
|
+
|
|
90351
|
+
${lines.join("\n")}`
|
|
90352
|
+
};
|
|
90353
|
+
}
|
|
90354
|
+
};
|
|
90355
|
+
LIST_MCP_RESOURCES_PROMPT = `List all resources available from connected MCP servers.
|
|
90356
|
+
- Returns resources with server name, URI, name, description, and MIME type
|
|
90357
|
+
- No input required \u2014 queries all connected servers
|
|
90358
|
+
- Use ReadMcpResourceTool to read a specific resource by server name and URI`;
|
|
90359
|
+
ReadMcpResourceInputSchema = external_exports.strictObject({
|
|
90360
|
+
server_name: external_exports.string().describe("The name of the MCP server that owns the resource"),
|
|
90361
|
+
uri: external_exports.string().describe("The URI of the resource to read")
|
|
90362
|
+
});
|
|
90363
|
+
ReadMcpResourceOutputSchema = external_exports.object({
|
|
90364
|
+
contents: external_exports.array(external_exports.object({
|
|
90365
|
+
uri: external_exports.string(),
|
|
90366
|
+
mimeType: external_exports.string().optional(),
|
|
90367
|
+
text: external_exports.string().optional(),
|
|
90368
|
+
blob: external_exports.string().optional()
|
|
90369
|
+
}))
|
|
90370
|
+
});
|
|
90371
|
+
readMcpResourceTool = {
|
|
90372
|
+
name: READ_MCP_RESOURCE_TOOL,
|
|
90373
|
+
searchHint: "read MCP server resource by URI",
|
|
90374
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
90375
|
+
shouldDefer: true,
|
|
90376
|
+
async description(input) {
|
|
90377
|
+
return input?.uri ? `Read MCP resource: ${input.uri}` : "Read a resource from a connected MCP server.";
|
|
90378
|
+
},
|
|
90379
|
+
async prompt() {
|
|
90380
|
+
return READ_MCP_RESOURCE_PROMPT;
|
|
90381
|
+
},
|
|
90382
|
+
get inputSchema() {
|
|
90383
|
+
return ReadMcpResourceInputSchema;
|
|
90384
|
+
},
|
|
90385
|
+
get outputSchema() {
|
|
90386
|
+
return ReadMcpResourceOutputSchema;
|
|
90387
|
+
},
|
|
90388
|
+
userFacingName() {
|
|
90389
|
+
return "Read MCP Resource";
|
|
90390
|
+
},
|
|
90391
|
+
isEnabled() {
|
|
90392
|
+
return true;
|
|
90393
|
+
},
|
|
90394
|
+
isConcurrencySafe() {
|
|
90395
|
+
return true;
|
|
90396
|
+
},
|
|
90397
|
+
isReadOnly() {
|
|
90398
|
+
return true;
|
|
90399
|
+
},
|
|
90400
|
+
toAutoClassifierInput(input) {
|
|
90401
|
+
return `${input.server_name} ${input.uri}`;
|
|
90402
|
+
},
|
|
90403
|
+
async validateInput(input) {
|
|
90404
|
+
if (!input.server_name?.trim()) {
|
|
90405
|
+
return { result: false, message: "server_name is required", errorCode: 1 };
|
|
90406
|
+
}
|
|
90407
|
+
if (!input.uri?.trim()) {
|
|
90408
|
+
return { result: false, message: "uri is required", errorCode: 2 };
|
|
90409
|
+
}
|
|
90410
|
+
return { result: true };
|
|
90411
|
+
},
|
|
90412
|
+
async checkPermissions() {
|
|
90413
|
+
return { behavior: "allow" };
|
|
90414
|
+
},
|
|
90415
|
+
async call(input, _context) {
|
|
90416
|
+
const client = getServerClient(input.server_name);
|
|
90417
|
+
if (!client) {
|
|
90418
|
+
return {
|
|
90419
|
+
data: {
|
|
90420
|
+
contents: [{
|
|
90421
|
+
uri: input.uri,
|
|
90422
|
+
text: `Error: MCP server "${input.server_name}" is not connected. Use ListMcpResourcesTool to see available servers.`
|
|
90423
|
+
}]
|
|
90424
|
+
}
|
|
90425
|
+
};
|
|
90426
|
+
}
|
|
90427
|
+
try {
|
|
90428
|
+
const result = await client.readResource({ uri: input.uri });
|
|
90429
|
+
const contents = (result.contents ?? []).map((c) => ({
|
|
90430
|
+
uri: c.uri ?? input.uri,
|
|
90431
|
+
mimeType: c.mimeType,
|
|
90432
|
+
text: c.text,
|
|
90433
|
+
blob: c.blob
|
|
90434
|
+
}));
|
|
90435
|
+
return { data: { contents } };
|
|
90436
|
+
} catch (error2) {
|
|
90437
|
+
return {
|
|
90438
|
+
data: {
|
|
90439
|
+
contents: [{
|
|
90440
|
+
uri: input.uri,
|
|
90441
|
+
text: `Error reading resource: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
90442
|
+
}]
|
|
90443
|
+
}
|
|
90444
|
+
};
|
|
90445
|
+
}
|
|
90446
|
+
},
|
|
90447
|
+
mapToolResultToToolResultBlockParam(result, toolUseId) {
|
|
90448
|
+
if (result.contents.length === 0) {
|
|
90449
|
+
return {
|
|
90450
|
+
type: "tool_result",
|
|
90451
|
+
tool_use_id: toolUseId,
|
|
90452
|
+
content: "Resource returned no content."
|
|
90453
|
+
};
|
|
90454
|
+
}
|
|
90455
|
+
const parts = [];
|
|
90456
|
+
for (const c of result.contents) {
|
|
90457
|
+
if (c.text) {
|
|
90458
|
+
parts.push(c.text);
|
|
90459
|
+
} else if (c.blob) {
|
|
90460
|
+
parts.push(`[base64 blob, ${c.blob.length} chars]${c.mimeType ? ` (${c.mimeType})` : ""}`);
|
|
90461
|
+
} else {
|
|
90462
|
+
parts.push(`[empty content for ${c.uri}]`);
|
|
90463
|
+
}
|
|
90464
|
+
}
|
|
90465
|
+
return {
|
|
90466
|
+
type: "tool_result",
|
|
90467
|
+
tool_use_id: toolUseId,
|
|
90468
|
+
content: parts.join("\n\n")
|
|
90469
|
+
};
|
|
90470
|
+
}
|
|
90471
|
+
};
|
|
90472
|
+
READ_MCP_RESOURCE_PROMPT = `Read a resource from a connected MCP server.
|
|
90473
|
+
- Requires server_name (the MCP server name) and uri (the resource URI)
|
|
90474
|
+
- Use ListMcpResourcesTool first to discover available resources
|
|
90475
|
+
- Returns text content or base64-encoded binary data`;
|
|
90476
|
+
}
|
|
90477
|
+
});
|
|
90478
|
+
|
|
89023
90479
|
// src/mcp/handlers.ts
|
|
89024
90480
|
function mcpToolsToHandlers() {
|
|
89025
90481
|
const mcpTools2 = getMcpTools();
|
|
@@ -89108,51 +90564,61 @@ var init_init = __esm({
|
|
|
89108
90564
|
});
|
|
89109
90565
|
|
|
89110
90566
|
// src/core/team.ts
|
|
89111
|
-
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, existsSync as existsSync14, mkdirSync as mkdirSync7 } from "fs";
|
|
89112
|
-
import { join as join8 } from "path";
|
|
89113
90567
|
function createTeam(name, description) {
|
|
89114
|
-
const
|
|
90568
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
90569
|
+
dbRun(
|
|
90570
|
+
`INSERT OR IGNORE INTO teams (name, description, task_list_id, created_at) VALUES (?, ?, ?, ?)`,
|
|
90571
|
+
[name, description ?? null, name, now]
|
|
90572
|
+
);
|
|
90573
|
+
return {
|
|
89115
90574
|
name,
|
|
89116
90575
|
description,
|
|
89117
|
-
createdAt:
|
|
90576
|
+
createdAt: now,
|
|
89118
90577
|
members: [],
|
|
89119
90578
|
taskListId: name
|
|
89120
90579
|
};
|
|
89121
|
-
const teamsDir = getTeamsDir();
|
|
89122
|
-
writeFileSync8(join8(teamsDir, `${name}.json`), JSON.stringify(team, null, 2), "utf-8");
|
|
89123
|
-
const taskDir = join8(getTasksDir(), name);
|
|
89124
|
-
if (!existsSync14(taskDir)) mkdirSync7(taskDir, { recursive: true });
|
|
89125
|
-
return team;
|
|
89126
90580
|
}
|
|
89127
90581
|
function getTeam(name) {
|
|
89128
|
-
const
|
|
89129
|
-
if (!
|
|
89130
|
-
|
|
89131
|
-
|
|
89132
|
-
|
|
89133
|
-
|
|
89134
|
-
|
|
90582
|
+
const row = dbGet(`SELECT * FROM teams WHERE name = ?`, [name]);
|
|
90583
|
+
if (!row) return null;
|
|
90584
|
+
const members = dbAll(
|
|
90585
|
+
`SELECT * FROM team_members WHERE team_name = ?`,
|
|
90586
|
+
[name]
|
|
90587
|
+
);
|
|
90588
|
+
return {
|
|
90589
|
+
name: row.name,
|
|
90590
|
+
description: row.description ?? void 0,
|
|
90591
|
+
createdAt: row.created_at ?? "",
|
|
90592
|
+
taskListId: row.task_list_id ?? row.name,
|
|
90593
|
+
members: members.map((m) => ({
|
|
90594
|
+
name: m.agent_name,
|
|
90595
|
+
agentId: m.agent_name,
|
|
90596
|
+
role: m.role ?? void 0,
|
|
90597
|
+
status: m.status ?? "idle",
|
|
90598
|
+
currentTask: m.current_task ?? void 0
|
|
90599
|
+
}))
|
|
90600
|
+
};
|
|
89135
90601
|
}
|
|
89136
90602
|
function addTeamMember(teamName, member) {
|
|
89137
|
-
|
|
89138
|
-
|
|
89139
|
-
|
|
89140
|
-
|
|
89141
|
-
|
|
90603
|
+
dbRun(
|
|
90604
|
+
`DELETE FROM team_members WHERE team_name = ? AND agent_name = ?`,
|
|
90605
|
+
[teamName, member.name]
|
|
90606
|
+
);
|
|
90607
|
+
dbRun(
|
|
90608
|
+
`INSERT INTO team_members (team_name, agent_name, role, status, current_task) VALUES (?, ?, ?, ?, ?)`,
|
|
90609
|
+
[teamName, member.name, member.role ?? null, member.status, member.currentTask ?? null]
|
|
90610
|
+
);
|
|
89142
90611
|
}
|
|
89143
90612
|
function updateMemberStatus(teamName, memberName, status) {
|
|
89144
|
-
|
|
89145
|
-
|
|
89146
|
-
|
|
89147
|
-
|
|
89148
|
-
member.status = status;
|
|
89149
|
-
writeFileSync8(join8(getTeamsDir(), `${teamName}.json`), JSON.stringify(team, null, 2), "utf-8");
|
|
89150
|
-
}
|
|
90613
|
+
dbRun(
|
|
90614
|
+
`UPDATE team_members SET status = ? WHERE team_name = ? AND agent_name = ?`,
|
|
90615
|
+
[status, teamName, memberName]
|
|
90616
|
+
);
|
|
89151
90617
|
}
|
|
89152
90618
|
var init_team = __esm({
|
|
89153
90619
|
"src/core/team.ts"() {
|
|
89154
90620
|
"use strict";
|
|
89155
|
-
|
|
90621
|
+
init_db();
|
|
89156
90622
|
}
|
|
89157
90623
|
});
|
|
89158
90624
|
|
|
@@ -90156,6 +91622,7 @@ __export(app_exports, {
|
|
|
90156
91622
|
launchInkApp: () => launchInkApp,
|
|
90157
91623
|
runHeadless: () => runHeadless
|
|
90158
91624
|
});
|
|
91625
|
+
import { execSync as execSync4 } from "child_process";
|
|
90159
91626
|
function useSpinner(active) {
|
|
90160
91627
|
const [i, setI] = (0, import_react22.useState)(0);
|
|
90161
91628
|
(0, import_react22.useEffect)(() => {
|
|
@@ -90178,6 +91645,8 @@ function createToolHandlers(mcpHandlers) {
|
|
|
90178
91645
|
taskGetTool,
|
|
90179
91646
|
taskListTool,
|
|
90180
91647
|
taskUpdateTool,
|
|
91648
|
+
taskOutputTool,
|
|
91649
|
+
taskStopTool,
|
|
90181
91650
|
askUserQuestionTool,
|
|
90182
91651
|
webSearchTool,
|
|
90183
91652
|
webFetchTool,
|
|
@@ -90192,49 +91661,75 @@ function createToolHandlers(mcpHandlers) {
|
|
|
90192
91661
|
exitWorktreeTool,
|
|
90193
91662
|
notebookEditTool,
|
|
90194
91663
|
configTool,
|
|
90195
|
-
sendMessageTool
|
|
91664
|
+
sendMessageTool,
|
|
91665
|
+
listMcpResourcesTool,
|
|
91666
|
+
readMcpResourceTool,
|
|
91667
|
+
skillTool
|
|
90196
91668
|
];
|
|
90197
|
-
const permCtx = createDefaultPermissionContext();
|
|
91669
|
+
const permCtx = createDefaultPermissionContext(getSettings());
|
|
90198
91670
|
const appState = { toolPermissionContext: permCtx, verbose: false };
|
|
90199
|
-
const
|
|
90200
|
-
|
|
90201
|
-
|
|
90202
|
-
|
|
90203
|
-
|
|
90204
|
-
|
|
90205
|
-
|
|
90206
|
-
|
|
90207
|
-
|
|
90208
|
-
|
|
90209
|
-
|
|
90210
|
-
|
|
90211
|
-
|
|
90212
|
-
|
|
90213
|
-
options: { mainLoopModel: "sonnet", thinkingConfig: { type: "disabled" }, isNonInteractiveSession: false, tools: [], agentDefinitions: { activeAgents: [] } }
|
|
90214
|
-
};
|
|
90215
|
-
const result = await tool.call(input, toolCtx);
|
|
90216
|
-
const block2 = tool.mapToolResultToToolResultBlockParam(result.data, ctx.toolUseId ?? "");
|
|
90217
|
-
const dur = performance.now() - t0;
|
|
90218
|
-
try {
|
|
90219
|
-
dbRun("INSERT INTO audit_log (tool_name, input_summary, result_summary, duration_ms, was_allowed) VALUES (?, ?, ?, ?, 1)", [tool.name, summary, block2.content.slice(0, 200), dur]);
|
|
90220
|
-
} catch {
|
|
90221
|
-
}
|
|
90222
|
-
return block2.is_error ? { data: block2.content, error: block2.content, isError: true } : { data: block2.content };
|
|
90223
|
-
} catch (err) {
|
|
90224
|
-
const dur = performance.now() - t0;
|
|
90225
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
91671
|
+
const immediate = [];
|
|
91672
|
+
const all = [];
|
|
91673
|
+
const deferredInfo = [];
|
|
91674
|
+
const deferredSchemas = /* @__PURE__ */ new Map();
|
|
91675
|
+
for (const tool of tools) {
|
|
91676
|
+
const handler = {
|
|
91677
|
+
name: tool.name,
|
|
91678
|
+
description: TOOL_DESCRIPTIONS[tool.name] ?? `Tool: ${tool.name}`,
|
|
91679
|
+
inputSchema: TOOL_JSON_SCHEMAS[tool.name] ?? { type: "object", properties: {} },
|
|
91680
|
+
isReadOnly: tool.isReadOnly(),
|
|
91681
|
+
isConcurrencySafe: tool.isConcurrencySafe(),
|
|
91682
|
+
call: async (input, ctx) => {
|
|
91683
|
+
const summary = toolSummary(tool.name, input);
|
|
91684
|
+
const t0 = performance.now();
|
|
90226
91685
|
try {
|
|
90227
|
-
|
|
90228
|
-
|
|
91686
|
+
const toolCtx = {
|
|
91687
|
+
abortController: new AbortController(),
|
|
91688
|
+
getAppState: () => appState,
|
|
91689
|
+
setAppState: (fn) => Object.assign(appState, fn(appState)),
|
|
91690
|
+
options: { mainLoopModel: "sonnet", thinkingConfig: { type: "disabled" }, isNonInteractiveSession: false, tools: [], agentDefinitions: { activeAgents: [] } }
|
|
91691
|
+
};
|
|
91692
|
+
const result = await tool.call(input, toolCtx);
|
|
91693
|
+
const block2 = tool.mapToolResultToToolResultBlockParam(result.data, ctx.toolUseId ?? "");
|
|
91694
|
+
const dur = performance.now() - t0;
|
|
91695
|
+
try {
|
|
91696
|
+
dbRun("INSERT INTO audit_log (tool_name, input_summary, result_summary, duration_ms, was_allowed) VALUES (?, ?, ?, ?, 1)", [tool.name, summary, block2.content.slice(0, 200), dur]);
|
|
91697
|
+
} catch {
|
|
91698
|
+
}
|
|
91699
|
+
return block2.is_error ? { data: block2.content, error: block2.content, isError: true } : { data: block2.content };
|
|
91700
|
+
} catch (err) {
|
|
91701
|
+
const dur = performance.now() - t0;
|
|
91702
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
91703
|
+
try {
|
|
91704
|
+
dbRun("INSERT INTO audit_log (tool_name, input_summary, result_summary, duration_ms, was_allowed) VALUES (?, ?, ?, ?, 1)", [tool.name, summary, errMsg.slice(0, 200), dur]);
|
|
91705
|
+
} catch {
|
|
91706
|
+
}
|
|
91707
|
+
return { error: errMsg, isError: true };
|
|
90229
91708
|
}
|
|
90230
|
-
return { error: errMsg, isError: true };
|
|
90231
91709
|
}
|
|
91710
|
+
};
|
|
91711
|
+
all.push(handler);
|
|
91712
|
+
if (tool.shouldDefer) {
|
|
91713
|
+
deferredInfo.push({
|
|
91714
|
+
name: tool.name,
|
|
91715
|
+
description: TOOL_DESCRIPTIONS[tool.name] ?? tool.searchHint
|
|
91716
|
+
});
|
|
91717
|
+
deferredSchemas.set(tool.name, {
|
|
91718
|
+
name: tool.name,
|
|
91719
|
+
description: TOOL_DESCRIPTIONS[tool.name] ?? tool.searchHint,
|
|
91720
|
+
inputSchema: TOOL_JSON_SCHEMAS[tool.name] ?? { type: "object", properties: {} }
|
|
91721
|
+
});
|
|
91722
|
+
} else {
|
|
91723
|
+
immediate.push(handler);
|
|
90232
91724
|
}
|
|
90233
|
-
}
|
|
91725
|
+
}
|
|
90234
91726
|
if (mcpHandlers && mcpHandlers.length > 0) {
|
|
90235
|
-
|
|
91727
|
+
for (const h of mcpHandlers) {
|
|
91728
|
+
immediate.push(h);
|
|
91729
|
+
all.push(h);
|
|
91730
|
+
}
|
|
90236
91731
|
}
|
|
90237
|
-
return
|
|
91732
|
+
return { immediate, all, deferredInfo, deferredSchemas };
|
|
90238
91733
|
}
|
|
90239
91734
|
function shortPath(p) {
|
|
90240
91735
|
if (!p) return "";
|
|
@@ -90246,8 +91741,12 @@ function shortPath(p) {
|
|
|
90246
91741
|
}
|
|
90247
91742
|
function toolSummary(name, input) {
|
|
90248
91743
|
switch (name) {
|
|
90249
|
-
case "Bash":
|
|
90250
|
-
|
|
91744
|
+
case "Bash": {
|
|
91745
|
+
let cmd = String(input.command ?? "");
|
|
91746
|
+
const cwd2 = process.cwd();
|
|
91747
|
+
if (cwd2 && cmd.includes(cwd2)) cmd = cmd.replaceAll(cwd2, ".");
|
|
91748
|
+
return cmd.slice(0, 60);
|
|
91749
|
+
}
|
|
90251
91750
|
case "Read":
|
|
90252
91751
|
return shortPath(String(input.file_path ?? ""));
|
|
90253
91752
|
case "Edit":
|
|
@@ -90293,11 +91792,21 @@ function toolSummary(name, input) {
|
|
|
90293
91792
|
case "ExitWorktree":
|
|
90294
91793
|
return String(input.action ?? "");
|
|
90295
91794
|
case "NotebookEdit":
|
|
90296
|
-
return shortPath(String(input.notebook_path ?? ""));
|
|
91795
|
+
return `${input.command ?? ""} ${shortPath(String(input.notebook_path ?? ""))}`.trim();
|
|
90297
91796
|
case "Config":
|
|
90298
91797
|
return String(input.setting ?? "");
|
|
90299
91798
|
case "SendMessage":
|
|
90300
91799
|
return `to:${input.to ?? ""}`;
|
|
91800
|
+
case "TaskOutput":
|
|
91801
|
+
return String(input.task_id ?? "");
|
|
91802
|
+
case "TaskStop":
|
|
91803
|
+
return String(input.task_id ?? "");
|
|
91804
|
+
case "ListMcpResourcesTool":
|
|
91805
|
+
return "";
|
|
91806
|
+
case "ReadMcpResourceTool":
|
|
91807
|
+
return `${input.server_name ?? ""}:${input.uri ?? ""}`.slice(0, 60);
|
|
91808
|
+
case "Skill":
|
|
91809
|
+
return String(input.skill ?? "").slice(0, 50);
|
|
90301
91810
|
default:
|
|
90302
91811
|
return "";
|
|
90303
91812
|
}
|
|
@@ -90306,20 +91815,97 @@ function SpinnerDot() {
|
|
|
90306
91815
|
const f = useSpinner(true);
|
|
90307
91816
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "cyan", children: f });
|
|
90308
91817
|
}
|
|
91818
|
+
function BackgroundTaskItem({ task }) {
|
|
91819
|
+
const spinner = useSpinner(task.status === "running");
|
|
91820
|
+
const icon = task.status === "running" ? spinner : task.status === "completed" ? "\u2713" : "\u2717";
|
|
91821
|
+
const color = task.status === "running" ? "yellow" : task.status === "completed" ? "green" : "red";
|
|
91822
|
+
const now = Date.now();
|
|
91823
|
+
const durationMs = task.endTime ? task.endTime - task.startTime : now - task.startTime;
|
|
91824
|
+
const durSec = Math.round(durationMs / 1e3);
|
|
91825
|
+
const durStr = durSec < 60 ? `${durSec}s` : `${Math.floor(durSec / 60)}m ${durSec % 60}s`;
|
|
91826
|
+
const desc = task.description.length > 40 ? task.description.slice(0, 37) + "..." : task.description;
|
|
91827
|
+
let detail = `${task.status === "running" ? "running" : task.status}`;
|
|
91828
|
+
detail += ` \xB7 ${durStr}`;
|
|
91829
|
+
if (task.exitCode !== void 0 && task.exitCode !== null && task.status !== "running") {
|
|
91830
|
+
detail += ` \xB7 exit ${task.exitCode}`;
|
|
91831
|
+
}
|
|
91832
|
+
if (task.progress?.tokenCount) {
|
|
91833
|
+
detail += ` \xB7 ${fmtTok(task.progress.tokenCount)} tokens`;
|
|
91834
|
+
}
|
|
91835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
91836
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color, children: [
|
|
91837
|
+
icon,
|
|
91838
|
+
" "
|
|
91839
|
+
] }),
|
|
91840
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, children: task.id }),
|
|
91841
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
|
|
91842
|
+
": ",
|
|
91843
|
+
desc,
|
|
91844
|
+
" "
|
|
91845
|
+
] }),
|
|
91846
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
|
|
91847
|
+
"(",
|
|
91848
|
+
detail,
|
|
91849
|
+
")"
|
|
91850
|
+
] })
|
|
91851
|
+
] });
|
|
91852
|
+
}
|
|
91853
|
+
function BackgroundTaskList({ tasks: tasks2 }) {
|
|
91854
|
+
if (tasks2.length === 0) return null;
|
|
91855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", children: tasks2.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BackgroundTaskItem, { task: t }, t.id)) });
|
|
91856
|
+
}
|
|
91857
|
+
function useCustomStatusLine(config2, context) {
|
|
91858
|
+
const [output, setOutput] = (0, import_react22.useState)(null);
|
|
91859
|
+
const lastRunRef = (0, import_react22.useRef)(0);
|
|
91860
|
+
(0, import_react22.useEffect)(() => {
|
|
91861
|
+
if (!config2 || config2.type !== "command") {
|
|
91862
|
+
setOutput(null);
|
|
91863
|
+
return;
|
|
91864
|
+
}
|
|
91865
|
+
const runCommand = () => {
|
|
91866
|
+
try {
|
|
91867
|
+
const stdinData = JSON.stringify({
|
|
91868
|
+
model: context.model,
|
|
91869
|
+
cost: context.cost,
|
|
91870
|
+
tokens: context.tokens,
|
|
91871
|
+
cwd: process.cwd(),
|
|
91872
|
+
version: VERSION
|
|
91873
|
+
});
|
|
91874
|
+
const result = execSync4(config2.command, {
|
|
91875
|
+
timeout: 3e3,
|
|
91876
|
+
input: stdinData,
|
|
91877
|
+
encoding: "utf-8",
|
|
91878
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
91879
|
+
});
|
|
91880
|
+
const trimmed = result.trim();
|
|
91881
|
+
if (trimmed) {
|
|
91882
|
+
setOutput(config2.padding ? trimmed.padEnd(config2.padding) : trimmed);
|
|
91883
|
+
}
|
|
91884
|
+
} catch {
|
|
91885
|
+
setOutput(null);
|
|
91886
|
+
}
|
|
91887
|
+
lastRunRef.current = Date.now();
|
|
91888
|
+
};
|
|
91889
|
+
runCommand();
|
|
91890
|
+
const interval = setInterval(runCommand, 2e3);
|
|
91891
|
+
return () => clearInterval(interval);
|
|
91892
|
+
}, [config2?.command, config2?.padding, context.model, context.cost, context.tokens]);
|
|
91893
|
+
return output;
|
|
91894
|
+
}
|
|
90309
91895
|
function ToolItem({ tool }) {
|
|
90310
91896
|
const f = useSpinner(tool.status === "running");
|
|
90311
|
-
const icon = tool.status === "running" ? f :
|
|
90312
|
-
const color = tool.status === "running" ? "
|
|
90313
|
-
const toolArgs = tool.summary ? `
|
|
91897
|
+
const icon = tool.status === "running" ? f : "\u25CF";
|
|
91898
|
+
const color = tool.status === "running" ? "cyan" : tool.status === "error" ? "red" : "cyan";
|
|
91899
|
+
const toolArgs = tool.summary ? ` ${tool.summary.slice(0, 50)}` : "";
|
|
90314
91900
|
const dur = tool.durationMs != null ? ` (${(tool.durationMs / 1e3).toFixed(1)}s)` : "";
|
|
90315
91901
|
const resultLine = tool.result && tool.status === "done" ? formatToolResult(tool.name, tool.result)[0] ?? "" : "";
|
|
90316
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
91902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", marginTop: 0, children: [
|
|
90317
91903
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
90318
91904
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color, children: [
|
|
90319
91905
|
icon,
|
|
90320
91906
|
" "
|
|
90321
91907
|
] }),
|
|
90322
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, children: tool.name }),
|
|
91908
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, color, children: tool.name }),
|
|
90323
91909
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
|
|
90324
91910
|
toolArgs,
|
|
90325
91911
|
dur
|
|
@@ -90331,7 +91917,7 @@ function ToolItem({ tool }) {
|
|
|
90331
91917
|
CONN,
|
|
90332
91918
|
" "
|
|
90333
91919
|
] }),
|
|
90334
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: resultLine.slice(0, 90) })
|
|
91920
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: resultLine.slice(0, 90) })
|
|
90335
91921
|
] }),
|
|
90336
91922
|
tool.error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
90337
91923
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
|
|
@@ -90416,19 +92002,24 @@ function MessageView({ msg }) {
|
|
|
90416
92002
|
] }) })
|
|
90417
92003
|
] });
|
|
90418
92004
|
}
|
|
90419
|
-
function StatusBar({ model, mode, cost, tokens, agentName, teamName, classification }) {
|
|
92005
|
+
function StatusBar({ model, mode, cost, tokens, agentName, teamName, classification, bgTaskCount, customStatusLine }) {
|
|
92006
|
+
if (customStatusLine) {
|
|
92007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: customStatusLine }) });
|
|
92008
|
+
}
|
|
90420
92009
|
const teamLabel = agentName && teamName ? ` \xB7 ${agentName}@${teamName}` : "";
|
|
90421
92010
|
const intentLabel = classification && classification.intent !== "general" ? ` \xB7 [${classification.intent}]` : "";
|
|
92011
|
+
const bgLabel = bgTaskCount && bgTaskCount > 0 ? ` \xB7 ${bgTaskCount} background task${bgTaskCount > 1 ? "s" : ""}` : "";
|
|
90422
92012
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
|
|
90423
92013
|
model,
|
|
90424
|
-
"
|
|
92014
|
+
" \\u00B7 ",
|
|
90425
92015
|
mode,
|
|
90426
|
-
"
|
|
92016
|
+
" \\u00B7 $",
|
|
90427
92017
|
cost.toFixed(4),
|
|
90428
|
-
"
|
|
92018
|
+
" \\u00B7 ",
|
|
90429
92019
|
fmtTok(tokens),
|
|
90430
92020
|
teamLabel,
|
|
90431
|
-
intentLabel
|
|
92021
|
+
intentLabel,
|
|
92022
|
+
bgLabel
|
|
90432
92023
|
] }) });
|
|
90433
92024
|
}
|
|
90434
92025
|
function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedSession, mcpToolHandlers, agentId, agentName, teamName }) {
|
|
@@ -90453,7 +92044,21 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90453
92044
|
const _rows = stdout?.rows ?? 24;
|
|
90454
92045
|
const [slashSelected, setSlashSelected] = (0, import_react22.useState)(0);
|
|
90455
92046
|
const [lastClassification, setLastClassification] = (0, import_react22.useState)(null);
|
|
92047
|
+
const [bgTasks, setBgTasks] = (0, import_react22.useState)([]);
|
|
90456
92048
|
const appSettings = getSettings();
|
|
92049
|
+
const statusLineConfig = appSettings.statusLine;
|
|
92050
|
+
const customStatusLine = useCustomStatusLine(statusLineConfig, { model, cost, tokens });
|
|
92051
|
+
(0, import_react22.useEffect)(() => {
|
|
92052
|
+
const poll = () => {
|
|
92053
|
+
const running = getRunningTasks();
|
|
92054
|
+
const recent = getRecentlyCompletedTasks(5e3);
|
|
92055
|
+
const all = [...running, ...recent];
|
|
92056
|
+
setBgTasks(all);
|
|
92057
|
+
};
|
|
92058
|
+
poll();
|
|
92059
|
+
const interval = setInterval(poll, 1e3);
|
|
92060
|
+
return () => clearInterval(interval);
|
|
92061
|
+
}, []);
|
|
90457
92062
|
const thinkingConfig = (() => {
|
|
90458
92063
|
if (appSettings.thinking?.enabled) {
|
|
90459
92064
|
return appSettings.thinking.budgetTokens ? { type: "enabled", budget_tokens: appSettings.thinking.budgetTokens } : { type: "enabled" };
|
|
@@ -90570,6 +92175,42 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90570
92175
|
]);
|
|
90571
92176
|
return;
|
|
90572
92177
|
}
|
|
92178
|
+
if (r.action === "compact") {
|
|
92179
|
+
if (history.length === 0) {
|
|
92180
|
+
setMsgs((p) => [...p, { id: `s${Date.now()}`, role: "system", content: "Nothing to compact \u2014 conversation is empty.", timestamp: Date.now() }]);
|
|
92181
|
+
return;
|
|
92182
|
+
}
|
|
92183
|
+
setMsgs((p) => [...p, { id: `s${Date.now()}`, role: "system", content: "Compacting conversation...", timestamp: Date.now() }]);
|
|
92184
|
+
try {
|
|
92185
|
+
const client = getApiClient();
|
|
92186
|
+
const customInstructions = r.data;
|
|
92187
|
+
const summaryPrompt = customInstructions ? `Summarize the conversation so far in 2-3 concise sentences, focusing on: ${customInstructions}. Include key decisions, files changed, and current state.` : "Summarize the conversation so far in 2-3 concise sentences. Include key decisions, files changed, and current state of the work.";
|
|
92188
|
+
const summaryResponse = await client.createMessage({
|
|
92189
|
+
model,
|
|
92190
|
+
messages: [
|
|
92191
|
+
...history,
|
|
92192
|
+
{ role: "user", content: summaryPrompt }
|
|
92193
|
+
],
|
|
92194
|
+
maxTokens: 1024
|
|
92195
|
+
});
|
|
92196
|
+
const summaryText = summaryResponse.content.filter((b) => b.type === "text").map((b) => b.text).join("\n").trim() || "Conversation compacted.";
|
|
92197
|
+
const summarySystemMsg = {
|
|
92198
|
+
id: `compact${Date.now()}`,
|
|
92199
|
+
role: "system",
|
|
92200
|
+
content: `[Compacted conversation summary]
|
|
92201
|
+
${summaryText}`,
|
|
92202
|
+
timestamp: Date.now()
|
|
92203
|
+
};
|
|
92204
|
+
setMsgs([summarySystemMsg]);
|
|
92205
|
+
setHistory([
|
|
92206
|
+
{ role: "user", content: "Here is a summary of our conversation so far:\n" + summaryText },
|
|
92207
|
+
{ role: "assistant", content: "Understood. I have the context from our previous conversation. How can I help you continue?" }
|
|
92208
|
+
]);
|
|
92209
|
+
} catch (e) {
|
|
92210
|
+
setMsgs((p) => [...p, { id: `e${Date.now()}`, role: "system", content: `Failed to compact: ${e instanceof Error ? e.message : String(e)}`, timestamp: Date.now() }]);
|
|
92211
|
+
}
|
|
92212
|
+
return;
|
|
92213
|
+
}
|
|
90573
92214
|
if (r.output) setMsgs((p) => [...p, { id: `s${Date.now()}`, role: "system", content: r.output, timestamp: Date.now() }]);
|
|
90574
92215
|
if (r.action === "exit") exit();
|
|
90575
92216
|
if (r.action === "clear") {
|
|
@@ -90599,48 +92240,22 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90599
92240
|
}
|
|
90600
92241
|
const t0 = performance.now();
|
|
90601
92242
|
try {
|
|
90602
|
-
const
|
|
90603
|
-
const permCtx = createDefaultPermissionContext();
|
|
92243
|
+
const toolSplit = createToolHandlers(mcpToolHandlers);
|
|
92244
|
+
const permCtx = createDefaultPermissionContext(getSettings());
|
|
90604
92245
|
const toolStartTimes = /* @__PURE__ */ new Map();
|
|
92246
|
+
setDeferredToolSchemas([...toolSplit.deferredSchemas.values()]);
|
|
90605
92247
|
const classification = classifyPrompt(text);
|
|
90606
92248
|
setLastClassification(classification);
|
|
90607
|
-
const
|
|
90608
|
-
|
|
90609
|
-
"Read",
|
|
90610
|
-
"Edit",
|
|
90611
|
-
"Write",
|
|
90612
|
-
"Glob",
|
|
90613
|
-
"Grep",
|
|
90614
|
-
"Agent",
|
|
90615
|
-
"TaskCreate",
|
|
90616
|
-
"TaskGet",
|
|
90617
|
-
"TaskList",
|
|
90618
|
-
"TaskUpdate",
|
|
90619
|
-
"AskUserQuestion",
|
|
90620
|
-
"WebSearch",
|
|
90621
|
-
"WebFetch",
|
|
90622
|
-
"LSP",
|
|
90623
|
-
"EnterPlanMode",
|
|
90624
|
-
"ExitPlanMode",
|
|
90625
|
-
"ToolSearch",
|
|
90626
|
-
"CronCreate",
|
|
90627
|
-
"CronDelete",
|
|
90628
|
-
"CronList",
|
|
90629
|
-
"EnterWorktree",
|
|
90630
|
-
"ExitWorktree",
|
|
90631
|
-
"NotebookEdit",
|
|
90632
|
-
"Config",
|
|
90633
|
-
"SendMessage"
|
|
90634
|
-
]);
|
|
90635
|
-
const toolHandlers = filterToolsByClassification(allToolHandlers, classification, builtinToolNames);
|
|
92249
|
+
const allBuiltinToolNames = new Set(toolSplit.all.map((h) => h.name));
|
|
92250
|
+
const toolHandlers = filterToolsByClassification(toolSplit.all, classification, allBuiltinToolNames);
|
|
90636
92251
|
try {
|
|
90637
92252
|
dbRun(
|
|
90638
92253
|
"INSERT INTO audit_log (tool_name, input_summary, result_summary, duration_ms, was_allowed) VALUES (?, ?, ?, ?, 1)",
|
|
90639
|
-
["__classifier", text.slice(0, 200), `${classification.intent}: ${classification.reason} (${toolHandlers.length}/${
|
|
92254
|
+
["__classifier", text.slice(0, 200), `${classification.intent}: ${classification.reason} (${toolHandlers.length}/${toolSplit.all.length} tools, ${toolSplit.deferredInfo.length} deferred)`, 0]
|
|
90640
92255
|
);
|
|
90641
92256
|
} catch {
|
|
90642
92257
|
}
|
|
90643
|
-
const
|
|
92258
|
+
const immediateBuiltinTools = [
|
|
90644
92259
|
bashTool,
|
|
90645
92260
|
readTool,
|
|
90646
92261
|
editTool,
|
|
@@ -90648,28 +92263,11 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90648
92263
|
globTool,
|
|
90649
92264
|
grepTool,
|
|
90650
92265
|
agentTool,
|
|
90651
|
-
taskCreateTool,
|
|
90652
|
-
taskGetTool,
|
|
90653
|
-
taskListTool,
|
|
90654
|
-
taskUpdateTool,
|
|
90655
|
-
askUserQuestionTool,
|
|
90656
|
-
webSearchTool,
|
|
90657
|
-
webFetchTool,
|
|
90658
|
-
lspTool,
|
|
90659
|
-
enterPlanModeTool,
|
|
90660
|
-
exitPlanModeTool,
|
|
90661
92266
|
toolSearchTool,
|
|
90662
|
-
|
|
90663
|
-
|
|
90664
|
-
cronListTool,
|
|
90665
|
-
enterWorktreeTool,
|
|
90666
|
-
exitWorktreeTool,
|
|
90667
|
-
notebookEditTool,
|
|
90668
|
-
configTool,
|
|
90669
|
-
sendMessageTool
|
|
90670
|
-
];
|
|
92267
|
+
skillTool
|
|
92268
|
+
].filter((t) => !t.shouldDefer);
|
|
90671
92269
|
const toolPrompts = await Promise.all(
|
|
90672
|
-
|
|
92270
|
+
immediateBuiltinTools.map(async (t) => ({ name: t.name, prompt: await t.prompt() }))
|
|
90673
92271
|
);
|
|
90674
92272
|
const turnAbort = new AbortController();
|
|
90675
92273
|
abortRef.current = turnAbort;
|
|
@@ -90682,7 +92280,8 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90682
92280
|
projectDir: process.cwd(),
|
|
90683
92281
|
model,
|
|
90684
92282
|
permissionMode: mode,
|
|
90685
|
-
tools: toolPrompts
|
|
92283
|
+
tools: toolPrompts,
|
|
92284
|
+
deferredTools: toolSplit.deferredInfo
|
|
90686
92285
|
}),
|
|
90687
92286
|
tools: toolHandlers,
|
|
90688
92287
|
model,
|
|
@@ -90698,7 +92297,7 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90698
92297
|
}
|
|
90699
92298
|
} catch {
|
|
90700
92299
|
}
|
|
90701
|
-
if (dangerouslySkipPermissions) {
|
|
92300
|
+
if (dangerouslySkipPermissions || permCtx.mode === "bypassPermissions") {
|
|
90702
92301
|
return { behavior: "allow" };
|
|
90703
92302
|
}
|
|
90704
92303
|
const ruleResult = checkToolPermission(toolName, toolInput, permCtx);
|
|
@@ -90896,11 +92495,12 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90896
92495
|
else if (!key.ctrl && !key.meta && ch) setInput((p) => p + ch);
|
|
90897
92496
|
});
|
|
90898
92497
|
const cols = stdout?.columns ?? 80;
|
|
90899
|
-
const
|
|
92498
|
+
const pad = 2;
|
|
92499
|
+
const sep = "\u2500".repeat(Math.min(cols - pad, 120));
|
|
90900
92500
|
const hasRunningTools = activeTools.some((t) => t.status === "running");
|
|
90901
92501
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
90902
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Static, { items: msgs, children: (msg) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageView, { msg }) }, msg.id) }),
|
|
90903
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
92502
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Static, { items: msgs, children: (msg) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageView, { msg }) }, msg.id) }),
|
|
92503
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [
|
|
90904
92504
|
busy && activeTools.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", children: activeTools.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolItem, { tool: t }, t.id)) }),
|
|
90905
92505
|
busy && thinkingText && !streaming && activeTools.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
90906
92506
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
@@ -90914,10 +92514,7 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90914
92514
|
line.slice(0, 120)
|
|
90915
92515
|
] }) }, i))
|
|
90916
92516
|
] }),
|
|
90917
|
-
busy && streaming && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
90918
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "green", children: "\u25CF " }),
|
|
90919
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: streaming.split("\n").filter((l) => l.trim()).slice(-3).join("\n").slice(-200) })
|
|
90920
|
-
] }),
|
|
92517
|
+
busy && streaming && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: streaming.split("\n").filter((l) => l.trim()).slice(-3).join("\n").slice(-200) }) }),
|
|
90921
92518
|
busy && !streaming && !thinkingText && activeTools.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
90922
92519
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SpinnerDot, {}),
|
|
90923
92520
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: " Thinking..." })
|
|
@@ -90947,6 +92544,7 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90947
92544
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "]lways" })
|
|
90948
92545
|
] })
|
|
90949
92546
|
] }),
|
|
92547
|
+
bgTasks.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BackgroundTaskList, { tasks: bgTasks }),
|
|
90950
92548
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
90951
92549
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: sep }),
|
|
90952
92550
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
@@ -90978,7 +92576,7 @@ function App2({ model, mode, dangerouslySkipPermissions, initialPrompt, resumedS
|
|
|
90978
92576
|
] })
|
|
90979
92577
|
] }, cmd.name)) }),
|
|
90980
92578
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: sep }),
|
|
90981
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBar, { model, mode, cost, tokens, agentName: agentName ?? agentId, teamName, classification: lastClassification })
|
|
92579
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBar, { model, mode, cost, tokens, agentName: agentName ?? agentId, teamName, classification: lastClassification, bgTaskCount: bgTasks.filter((t) => t.status === "running").length, customStatusLine })
|
|
90982
92580
|
] })
|
|
90983
92581
|
] })
|
|
90984
92582
|
] });
|
|
@@ -91101,6 +92699,7 @@ var init_app = __esm({
|
|
|
91101
92699
|
init_agent_loop();
|
|
91102
92700
|
init_permissions();
|
|
91103
92701
|
init_db();
|
|
92702
|
+
init_background_tasks();
|
|
91104
92703
|
init_session();
|
|
91105
92704
|
init_system_prompt();
|
|
91106
92705
|
init_bash();
|
|
@@ -91111,17 +92710,21 @@ var init_app = __esm({
|
|
|
91111
92710
|
init_grep();
|
|
91112
92711
|
init_agent();
|
|
91113
92712
|
init_tasks();
|
|
92713
|
+
init_task_output();
|
|
91114
92714
|
init_ask_user();
|
|
91115
92715
|
init_web_search();
|
|
91116
92716
|
init_web_fetch();
|
|
91117
92717
|
init_lsp();
|
|
91118
92718
|
init_plan_mode();
|
|
91119
92719
|
init_misc();
|
|
92720
|
+
init_mcp_resources();
|
|
91120
92721
|
init_registry();
|
|
91121
92722
|
init_init();
|
|
91122
92723
|
init_client4();
|
|
91123
92724
|
init_team();
|
|
91124
92725
|
init_classifier();
|
|
92726
|
+
init_skill();
|
|
92727
|
+
init_registry2();
|
|
91125
92728
|
import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
91126
92729
|
CONN = "\u23BF";
|
|
91127
92730
|
PROMPT = "\u276F";
|
|
@@ -91357,10 +92960,13 @@ var init_app = __esm({
|
|
|
91357
92960
|
type: "object",
|
|
91358
92961
|
properties: {
|
|
91359
92962
|
notebook_path: { type: "string", description: "Path to the .ipynb file" },
|
|
91360
|
-
|
|
91361
|
-
|
|
92963
|
+
command: { type: "string", enum: ["insert_cell", "replace_cell", "delete_cell", "move_cell", "change_cell_type"], description: "Operation to perform on the notebook" },
|
|
92964
|
+
cell_index: { type: "number", description: "Cell index to operate on (0-based). For insert_cell, position to insert at (omit to append)." },
|
|
92965
|
+
cell_type: { type: "string", enum: ["code", "markdown", "raw"], description: "Cell type \u2014 required for insert_cell and change_cell_type" },
|
|
92966
|
+
new_source: { type: "string", description: "New cell content \u2014 required for insert_cell and replace_cell" },
|
|
92967
|
+
target_index: { type: "number", description: "Destination index for move_cell" }
|
|
91362
92968
|
},
|
|
91363
|
-
required: ["notebook_path", "
|
|
92969
|
+
required: ["notebook_path", "command"]
|
|
91364
92970
|
},
|
|
91365
92971
|
Config: {
|
|
91366
92972
|
type: "object",
|
|
@@ -91377,6 +92983,40 @@ var init_app = __esm({
|
|
|
91377
92983
|
message: { type: "string", description: "Message content" }
|
|
91378
92984
|
},
|
|
91379
92985
|
required: ["to", "message"]
|
|
92986
|
+
},
|
|
92987
|
+
TaskOutput: {
|
|
92988
|
+
type: "object",
|
|
92989
|
+
properties: {
|
|
92990
|
+
task_id: { type: "string", description: "The ID of the background task to check (e.g. 'bg-1', 'agent-2')" }
|
|
92991
|
+
},
|
|
92992
|
+
required: ["task_id"]
|
|
92993
|
+
},
|
|
92994
|
+
TaskStop: {
|
|
92995
|
+
type: "object",
|
|
92996
|
+
properties: {
|
|
92997
|
+
task_id: { type: "string", description: "The ID of the background task to stop (e.g. 'bg-1', 'agent-2')" }
|
|
92998
|
+
},
|
|
92999
|
+
required: ["task_id"]
|
|
93000
|
+
},
|
|
93001
|
+
ListMcpResourcesTool: {
|
|
93002
|
+
type: "object",
|
|
93003
|
+
properties: {}
|
|
93004
|
+
},
|
|
93005
|
+
ReadMcpResourceTool: {
|
|
93006
|
+
type: "object",
|
|
93007
|
+
properties: {
|
|
93008
|
+
server_name: { type: "string", description: "The name of the MCP server that owns the resource" },
|
|
93009
|
+
uri: { type: "string", description: "The URI of the resource to read" }
|
|
93010
|
+
},
|
|
93011
|
+
required: ["server_name", "uri"]
|
|
93012
|
+
},
|
|
93013
|
+
Skill: {
|
|
93014
|
+
type: "object",
|
|
93015
|
+
properties: {
|
|
93016
|
+
skill: { type: "string", description: "The skill name to invoke (e.g. 'commit', 'review-pr')" },
|
|
93017
|
+
args: { type: "string", description: "Optional arguments to pass to the skill prompt" }
|
|
93018
|
+
},
|
|
93019
|
+
required: ["skill"]
|
|
91380
93020
|
}
|
|
91381
93021
|
};
|
|
91382
93022
|
TOOL_DESCRIPTIONS = {
|
|
@@ -91403,9 +93043,14 @@ var init_app = __esm({
|
|
|
91403
93043
|
CronList: "List all active scheduled cron jobs.",
|
|
91404
93044
|
EnterWorktree: "Create an isolated git worktree and switch into it.",
|
|
91405
93045
|
ExitWorktree: "Exit a worktree session, keeping or removing the worktree.",
|
|
91406
|
-
NotebookEdit: "Edit
|
|
93046
|
+
NotebookEdit: "Edit Jupyter notebook cells \u2014 insert, replace, delete, move cells, or change cell type. Preserves all metadata and outputs.",
|
|
91407
93047
|
Config: "Get or set a configuration setting.",
|
|
91408
|
-
SendMessage: "Send a direct message to another agent or to the user."
|
|
93048
|
+
SendMessage: "Send a direct message to another agent or to the user.",
|
|
93049
|
+
TaskOutput: "Check the status and output of a background task (bash or agent).",
|
|
93050
|
+
TaskStop: "Stop a running background task by its ID.",
|
|
93051
|
+
ListMcpResourcesTool: "List all resources available from connected MCP servers.",
|
|
93052
|
+
ReadMcpResourceTool: "Read a resource from a connected MCP server by server name and URI.",
|
|
93053
|
+
Skill: "Execute a skill within the main conversation. Skills are user-defined prompts in .coders/skills/ or .claude/skills/ directories."
|
|
91409
93054
|
};
|
|
91410
93055
|
}
|
|
91411
93056
|
});
|
|
@@ -92224,16 +93869,16 @@ __export(marketplace_exports, {
|
|
|
92224
93869
|
removeMarketplace: () => removeMarketplace,
|
|
92225
93870
|
uninstallPlugin: () => uninstallPlugin
|
|
92226
93871
|
});
|
|
92227
|
-
import { readFileSync as
|
|
92228
|
-
import { join as
|
|
92229
|
-
import { execSync as
|
|
93872
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync17, mkdirSync as mkdirSync8, cpSync, rmSync } from "fs";
|
|
93873
|
+
import { join as join11, resolve as resolve7 } from "path";
|
|
93874
|
+
import { execSync as execSync5 } from "child_process";
|
|
92230
93875
|
import { tmpdir } from "os";
|
|
92231
93876
|
import { randomBytes } from "crypto";
|
|
92232
93877
|
function getMarketplaces() {
|
|
92233
93878
|
const path = getMarketplacesConfigPath();
|
|
92234
|
-
if (!
|
|
93879
|
+
if (!existsSync17(path)) return [];
|
|
92235
93880
|
try {
|
|
92236
|
-
return JSON.parse(
|
|
93881
|
+
return JSON.parse(readFileSync14(path, "utf-8"));
|
|
92237
93882
|
} catch {
|
|
92238
93883
|
return [];
|
|
92239
93884
|
}
|
|
@@ -92253,8 +93898,8 @@ function removeMarketplace(name) {
|
|
|
92253
93898
|
}
|
|
92254
93899
|
function saveMarketplaces(marketplaces) {
|
|
92255
93900
|
const path = getMarketplacesConfigPath();
|
|
92256
|
-
const dir =
|
|
92257
|
-
if (!
|
|
93901
|
+
const dir = join11(path, "..");
|
|
93902
|
+
if (!existsSync17(dir)) mkdirSync8(dir, { recursive: true });
|
|
92258
93903
|
writeFileSync9(path, JSON.stringify(marketplaces, null, 2) + "\n", "utf-8");
|
|
92259
93904
|
}
|
|
92260
93905
|
async function installFromMarketplace(pluginName, marketplaceName) {
|
|
@@ -92278,7 +93923,7 @@ async function installPluginFromMarketplace(name, marketplace) {
|
|
|
92278
93923
|
return installFromGit(gitUrl, pluginsDir);
|
|
92279
93924
|
}
|
|
92280
93925
|
case "directory": {
|
|
92281
|
-
const sourcePath =
|
|
93926
|
+
const sourcePath = join11(marketplace.source, name);
|
|
92282
93927
|
return installFromDirectory(sourcePath, pluginsDir);
|
|
92283
93928
|
}
|
|
92284
93929
|
case "url":
|
|
@@ -92297,10 +93942,10 @@ function installFromSource(source, pluginsDir) {
|
|
|
92297
93942
|
}
|
|
92298
93943
|
function installFromGit(url2, pluginsDir) {
|
|
92299
93944
|
const dir = pluginsDir ?? getPluginsDir();
|
|
92300
|
-
const tempDir =
|
|
93945
|
+
const tempDir = join11(tmpdir(), `coders-plugin-${randomBytes(8).toString("hex")}`);
|
|
92301
93946
|
try {
|
|
92302
93947
|
try {
|
|
92303
|
-
|
|
93948
|
+
execSync5(`git clone --depth 1 ${escapeShellArg(url2)} ${escapeShellArg(tempDir)}`, {
|
|
92304
93949
|
encoding: "utf-8",
|
|
92305
93950
|
stdio: "pipe",
|
|
92306
93951
|
timeout: 6e4
|
|
@@ -92311,21 +93956,21 @@ function installFromGit(url2, pluginsDir) {
|
|
|
92311
93956
|
error: `Failed to clone "${url2}": ${err instanceof Error ? err.message : String(err)}`
|
|
92312
93957
|
};
|
|
92313
93958
|
}
|
|
92314
|
-
const manifestPath =
|
|
92315
|
-
if (!
|
|
93959
|
+
const manifestPath = join11(tempDir, "manifest.json");
|
|
93960
|
+
if (!existsSync17(manifestPath)) {
|
|
92316
93961
|
return { success: false, error: `No manifest.json found in cloned repository "${url2}"` };
|
|
92317
93962
|
}
|
|
92318
93963
|
const validated = validateManifest(manifestPath);
|
|
92319
93964
|
if (!validated.success) return validated;
|
|
92320
93965
|
const pluginName = validated.pluginName;
|
|
92321
|
-
const targetDir =
|
|
92322
|
-
if (
|
|
93966
|
+
const targetDir = join11(dir, pluginName);
|
|
93967
|
+
if (existsSync17(targetDir)) {
|
|
92323
93968
|
return { success: false, error: `Plugin "${pluginName}" is already installed` };
|
|
92324
93969
|
}
|
|
92325
93970
|
mkdirSync8(targetDir, { recursive: true });
|
|
92326
93971
|
cpSync(tempDir, targetDir, {
|
|
92327
93972
|
recursive: true,
|
|
92328
|
-
filter: (src) => !src.includes(
|
|
93973
|
+
filter: (src) => !src.includes(join11(tempDir, ".git"))
|
|
92329
93974
|
});
|
|
92330
93975
|
return {
|
|
92331
93976
|
success: true,
|
|
@@ -92343,18 +93988,18 @@ function installFromGit(url2, pluginsDir) {
|
|
|
92343
93988
|
function installFromDirectory(sourcePath, pluginsDir) {
|
|
92344
93989
|
const dir = pluginsDir ?? getPluginsDir();
|
|
92345
93990
|
const resolvedSource = resolve7(sourcePath);
|
|
92346
|
-
if (!
|
|
93991
|
+
if (!existsSync17(resolvedSource)) {
|
|
92347
93992
|
return { success: false, error: `Source directory does not exist: "${resolvedSource}"` };
|
|
92348
93993
|
}
|
|
92349
|
-
const manifestPath =
|
|
92350
|
-
if (!
|
|
93994
|
+
const manifestPath = join11(resolvedSource, "manifest.json");
|
|
93995
|
+
if (!existsSync17(manifestPath)) {
|
|
92351
93996
|
return { success: false, error: `No manifest.json found in "${resolvedSource}"` };
|
|
92352
93997
|
}
|
|
92353
93998
|
const validated = validateManifest(manifestPath);
|
|
92354
93999
|
if (!validated.success) return validated;
|
|
92355
94000
|
const pluginName = validated.pluginName;
|
|
92356
|
-
const targetDir =
|
|
92357
|
-
if (
|
|
94001
|
+
const targetDir = join11(dir, pluginName);
|
|
94002
|
+
if (existsSync17(targetDir)) {
|
|
92358
94003
|
return { success: false, error: `Plugin "${pluginName}" is already installed` };
|
|
92359
94004
|
}
|
|
92360
94005
|
mkdirSync8(targetDir, { recursive: true });
|
|
@@ -92368,8 +94013,8 @@ function installFromDirectory(sourcePath, pluginsDir) {
|
|
|
92368
94013
|
}
|
|
92369
94014
|
function uninstallPlugin(name, pluginsDir) {
|
|
92370
94015
|
const dir = pluginsDir ?? getPluginsDir();
|
|
92371
|
-
const targetDir =
|
|
92372
|
-
if (!
|
|
94016
|
+
const targetDir = join11(dir, name);
|
|
94017
|
+
if (!existsSync17(targetDir)) return false;
|
|
92373
94018
|
rmSync(targetDir, { recursive: true, force: true });
|
|
92374
94019
|
return true;
|
|
92375
94020
|
}
|
|
@@ -92378,7 +94023,7 @@ function isGitUrl(source) {
|
|
|
92378
94023
|
}
|
|
92379
94024
|
function validateManifest(manifestPath) {
|
|
92380
94025
|
try {
|
|
92381
|
-
const raw = JSON.parse(
|
|
94026
|
+
const raw = JSON.parse(readFileSync14(manifestPath, "utf-8"));
|
|
92382
94027
|
const result = PluginManifestSchema.safeParse(raw);
|
|
92383
94028
|
if (!result.success) {
|
|
92384
94029
|
const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
@@ -92412,8 +94057,8 @@ var main_exports = {};
|
|
|
92412
94057
|
__export(main_exports, {
|
|
92413
94058
|
main: () => main
|
|
92414
94059
|
});
|
|
92415
|
-
import { execSync as
|
|
92416
|
-
import { existsSync as
|
|
94060
|
+
import { execSync as execSync6 } from "child_process";
|
|
94061
|
+
import { existsSync as existsSync18 } from "fs";
|
|
92417
94062
|
function helpConfig() {
|
|
92418
94063
|
return {
|
|
92419
94064
|
sortSubcommands: true,
|
|
@@ -92847,15 +94492,15 @@ ${installed.length} plugin(s) installed`);
|
|
|
92847
94492
|
}
|
|
92848
94493
|
});
|
|
92849
94494
|
plugin.command("install <plugin>").alias("i").description("Install a plugin from a marketplace or local path").option("-s, --scope <scope>", "Installation scope", "user").option("-m, --marketplace <name>", "Marketplace to install from").action(async (source, options2) => {
|
|
92850
|
-
const { resolve: resolve8, join:
|
|
94495
|
+
const { resolve: resolve8, join: join12 } = await import("path");
|
|
92851
94496
|
const { existsSync: pathExists } = await import("fs");
|
|
92852
94497
|
const resolvedPath = resolve8(source);
|
|
92853
|
-
const isLocalDir = pathExists(resolvedPath) && pathExists(
|
|
94498
|
+
const isLocalDir = pathExists(resolvedPath) && pathExists(join12(resolvedPath, "manifest.json"));
|
|
92854
94499
|
if (isLocalDir) {
|
|
92855
94500
|
try {
|
|
92856
|
-
const { readFileSync:
|
|
94501
|
+
const { readFileSync: readFileSync15, cpSync: cpSync2, mkdirSync: mkdirSync9 } = await import("fs");
|
|
92857
94502
|
const { PluginManifestSchema: PluginManifestSchema2 } = await Promise.resolve().then(() => (init_manifest(), manifest_exports));
|
|
92858
|
-
const manifestRaw = JSON.parse(
|
|
94503
|
+
const manifestRaw = JSON.parse(readFileSync15(join12(resolvedPath, "manifest.json"), "utf-8"));
|
|
92859
94504
|
const result = PluginManifestSchema2.safeParse(manifestRaw);
|
|
92860
94505
|
if (!result.success) {
|
|
92861
94506
|
console.error("Error: Invalid plugin manifest:");
|
|
@@ -92866,7 +94511,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
92866
94511
|
}
|
|
92867
94512
|
const pluginName = result.data.name;
|
|
92868
94513
|
const pluginsDir = getPluginsDir();
|
|
92869
|
-
const targetDir =
|
|
94514
|
+
const targetDir = join12(pluginsDir, pluginName);
|
|
92870
94515
|
if (pathExists(targetDir)) {
|
|
92871
94516
|
console.error(`Error: Plugin "${pluginName}" is already installed.`);
|
|
92872
94517
|
console.error("Uninstall it first: coders plugin uninstall " + pluginName);
|
|
@@ -92913,13 +94558,13 @@ ${installed.length} plugin(s) installed`);
|
|
|
92913
94558
|
});
|
|
92914
94559
|
plugin.command("validate <path>").description("Validate a plugin manifest").option("--json", "Output validation result as JSON").action(async (manifestPath, options2) => {
|
|
92915
94560
|
try {
|
|
92916
|
-
const { existsSync: pathExists, readFileSync:
|
|
92917
|
-
const { resolve: resolve8, join:
|
|
94561
|
+
const { existsSync: pathExists, readFileSync: readFileSync15 } = await import("fs");
|
|
94562
|
+
const { resolve: resolve8, join: join12 } = await import("path");
|
|
92918
94563
|
const { PluginManifestSchema: PluginManifestSchema2 } = await Promise.resolve().then(() => (init_manifest(), manifest_exports));
|
|
92919
94564
|
const resolvedPath = resolve8(manifestPath);
|
|
92920
94565
|
let filePath;
|
|
92921
|
-
if (pathExists(
|
|
92922
|
-
filePath =
|
|
94566
|
+
if (pathExists(join12(resolvedPath, "manifest.json"))) {
|
|
94567
|
+
filePath = join12(resolvedPath, "manifest.json");
|
|
92923
94568
|
} else if (pathExists(resolvedPath)) {
|
|
92924
94569
|
filePath = resolvedPath;
|
|
92925
94570
|
} else {
|
|
@@ -92929,7 +94574,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
92929
94574
|
}
|
|
92930
94575
|
let raw;
|
|
92931
94576
|
try {
|
|
92932
|
-
raw = JSON.parse(
|
|
94577
|
+
raw = JSON.parse(readFileSync15(filePath, "utf-8"));
|
|
92933
94578
|
} catch {
|
|
92934
94579
|
console.error(`Error: Could not parse JSON from ${filePath}`);
|
|
92935
94580
|
process.exit(1);
|
|
@@ -93026,8 +94671,8 @@ ${installed.length} plugin(s) installed`);
|
|
|
93026
94671
|
try {
|
|
93027
94672
|
const userSettingsPath = getUserSettingsPath();
|
|
93028
94673
|
const projectSettingsPath = getProjectSettingsPath(process.cwd());
|
|
93029
|
-
const userExists =
|
|
93030
|
-
const projectExists =
|
|
94674
|
+
const userExists = existsSync18(userSettingsPath);
|
|
94675
|
+
const projectExists = existsSync18(projectSettingsPath);
|
|
93031
94676
|
const parts = [];
|
|
93032
94677
|
if (userExists) parts.push("user");
|
|
93033
94678
|
if (projectExists) parts.push("project");
|
|
@@ -93058,7 +94703,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
93058
94703
|
issues++;
|
|
93059
94704
|
}
|
|
93060
94705
|
try {
|
|
93061
|
-
const gitVersion =
|
|
94706
|
+
const gitVersion = execSync6("git --version", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
93062
94707
|
console.log(` ${ok} Git: ${gitVersion.replace("git version ", "")}`);
|
|
93063
94708
|
} catch {
|
|
93064
94709
|
console.log(` ${fail} Git: not found in PATH`);
|
|
@@ -93066,7 +94711,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
93066
94711
|
}
|
|
93067
94712
|
try {
|
|
93068
94713
|
const pluginsDir = getPluginsDir();
|
|
93069
|
-
const dirExists =
|
|
94714
|
+
const dirExists = existsSync18(pluginsDir);
|
|
93070
94715
|
if (dirExists) {
|
|
93071
94716
|
const discovered = discoverPlugins();
|
|
93072
94717
|
if (discovered.length > 0) {
|
|
@@ -93085,7 +94730,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
93085
94730
|
issues++;
|
|
93086
94731
|
}
|
|
93087
94732
|
try {
|
|
93088
|
-
const rgVersion =
|
|
94733
|
+
const rgVersion = execSync6("rg --version", { encoding: "utf-8", timeout: 5e3 }).split("\n")[0].trim();
|
|
93089
94734
|
console.log(` ${ok} Ripgrep: ${rgVersion.replace("ripgrep ", "")}`);
|
|
93090
94735
|
} catch {
|
|
93091
94736
|
console.log(` ${fail} Ripgrep: not found in PATH (needed for Grep tool)`);
|
|
@@ -93104,7 +94749,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
93104
94749
|
console.log("Checking for updates...\n");
|
|
93105
94750
|
let latestVersion;
|
|
93106
94751
|
try {
|
|
93107
|
-
latestVersion =
|
|
94752
|
+
latestVersion = execSync6(`npm view ${PACKAGE_NAME} version`, {
|
|
93108
94753
|
encoding: "utf-8",
|
|
93109
94754
|
timeout: 15e3,
|
|
93110
94755
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -93148,7 +94793,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
93148
94793
|
}
|
|
93149
94794
|
let installCmd;
|
|
93150
94795
|
try {
|
|
93151
|
-
|
|
94796
|
+
execSync6("bun --version", { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] });
|
|
93152
94797
|
installCmd = `bun install -g ${PACKAGE_NAME}@latest`;
|
|
93153
94798
|
} catch {
|
|
93154
94799
|
installCmd = `npm install -g ${PACKAGE_NAME}@latest`;
|
|
@@ -93156,7 +94801,7 @@ ${installed.length} plugin(s) installed`);
|
|
|
93156
94801
|
console.log(`Running: ${installCmd}
|
|
93157
94802
|
`);
|
|
93158
94803
|
try {
|
|
93159
|
-
|
|
94804
|
+
execSync6(installCmd, { encoding: "utf-8", timeout: 12e4, stdio: "inherit" });
|
|
93160
94805
|
console.log(`
|
|
93161
94806
|
Successfully updated to v${latestVersion}.`);
|
|
93162
94807
|
} catch (err) {
|
|
@@ -93424,7 +95069,7 @@ var VERSION, BUILD_TIME, PACKAGE_NAME, ISSUES_URL, startupTimestamps, originalCw
|
|
|
93424
95069
|
var init_index = __esm({
|
|
93425
95070
|
"src/cli/index.ts"() {
|
|
93426
95071
|
VERSION = "0.1.2";
|
|
93427
|
-
BUILD_TIME = "2026-03-
|
|
95072
|
+
BUILD_TIME = "2026-03-21T05:56:28.429Z";
|
|
93428
95073
|
PACKAGE_NAME = "@hasna/coders";
|
|
93429
95074
|
ISSUES_URL = "https://github.com/hasnaxyz/open-coders/issues";
|
|
93430
95075
|
startupTimestamps = {};
|