@ouro.bot/cli 0.1.0-alpha.36 → 0.1.0-alpha.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -185
- package/changelog.json +18 -0
- package/dist/heart/daemon/daemon-cli.js +359 -32
- package/dist/heart/daemon/specialist-prompt.js +2 -1
- package/dist/heart/daemon/specialist-tools.js +48 -2
- package/dist/heart/kicks.js +1 -1
- package/dist/mind/friends/channel.js +8 -0
- package/dist/mind/friends/store-file.js +19 -0
- package/dist/mind/prompt.js +122 -2
- package/dist/repertoire/tools-base.js +193 -271
- package/dist/repertoire/tools.js +8 -26
- package/dist/senses/bluebubbles.js +178 -0
- package/dist/senses/cli.js +28 -10
- package/dist/senses/inner-dialog.js +28 -26
- package/dist/senses/teams.js +179 -0
- package/package.json +2 -1
- package/subagents/README.md +40 -53
|
@@ -33,37 +33,31 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.finalAnswerTool = exports.baseToolHandlers = exports.tools = exports.baseToolDefinitions = void 0;
|
|
36
|
+
exports.finalAnswerTool = exports.baseToolHandlers = exports.tools = exports.baseToolDefinitions = exports.editFileReadTracker = void 0;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const fg = __importStar(require("fast-glob"));
|
|
38
39
|
const child_process_1 = require("child_process");
|
|
39
40
|
const path = __importStar(require("path"));
|
|
40
41
|
const skills_1 = require("./skills");
|
|
41
42
|
const config_1 = require("../heart/config");
|
|
42
43
|
const runtime_1 = require("../nerves/runtime");
|
|
43
44
|
const identity_1 = require("../heart/identity");
|
|
44
|
-
const tasks_1 = require("./tasks");
|
|
45
45
|
const tools_1 = require("./coding/tools");
|
|
46
46
|
const memory_1 = require("../mind/memory");
|
|
47
47
|
const pending_1 = require("../mind/pending");
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
status: normalizeOptionalText(args.status) ?? undefined,
|
|
62
|
-
validator: normalizeOptionalText(args.validator),
|
|
63
|
-
requester: normalizeOptionalText(args.requester),
|
|
64
|
-
cadence: normalizeOptionalText(args.cadence),
|
|
65
|
-
scheduledAt: normalizeOptionalText(args.scheduledAt),
|
|
66
|
-
};
|
|
48
|
+
// Tracks which file paths have been read via read_file in this session.
|
|
49
|
+
// edit_file requires a file to be read first (must-read-first guard).
|
|
50
|
+
exports.editFileReadTracker = new Set();
|
|
51
|
+
function buildContextDiff(lines, changeStart, changeEnd, contextSize = 3) {
|
|
52
|
+
const start = Math.max(0, changeStart - contextSize);
|
|
53
|
+
const end = Math.min(lines.length, changeEnd + contextSize);
|
|
54
|
+
const result = [];
|
|
55
|
+
for (let i = start; i < end; i++) {
|
|
56
|
+
const lineNum = i + 1;
|
|
57
|
+
const prefix = (i >= changeStart && i < changeEnd) ? ">" : " ";
|
|
58
|
+
result.push(`${prefix} ${lineNum} | ${lines[i]}`);
|
|
59
|
+
}
|
|
60
|
+
return result.join("\n");
|
|
67
61
|
}
|
|
68
62
|
exports.baseToolDefinitions = [
|
|
69
63
|
{
|
|
@@ -74,12 +68,27 @@ exports.baseToolDefinitions = [
|
|
|
74
68
|
description: "read file contents",
|
|
75
69
|
parameters: {
|
|
76
70
|
type: "object",
|
|
77
|
-
properties: {
|
|
71
|
+
properties: {
|
|
72
|
+
path: { type: "string" },
|
|
73
|
+
offset: { type: "number", description: "1-based line number to start reading from" },
|
|
74
|
+
limit: { type: "number", description: "maximum number of lines to return" },
|
|
75
|
+
},
|
|
78
76
|
required: ["path"],
|
|
79
77
|
},
|
|
80
78
|
},
|
|
81
79
|
},
|
|
82
|
-
handler: (a) =>
|
|
80
|
+
handler: (a) => {
|
|
81
|
+
const content = fs.readFileSync(a.path, "utf-8");
|
|
82
|
+
exports.editFileReadTracker.add(a.path);
|
|
83
|
+
const offset = a.offset ? parseInt(a.offset, 10) : undefined;
|
|
84
|
+
const limit = a.limit ? parseInt(a.limit, 10) : undefined;
|
|
85
|
+
if (offset === undefined && limit === undefined)
|
|
86
|
+
return content;
|
|
87
|
+
const lines = content.split("\n");
|
|
88
|
+
const start = offset ? offset - 1 : 0;
|
|
89
|
+
const end = limit !== undefined ? start + limit : lines.length;
|
|
90
|
+
return lines.slice(start, end).join("\n");
|
|
91
|
+
},
|
|
83
92
|
},
|
|
84
93
|
{
|
|
85
94
|
tool: {
|
|
@@ -104,97 +113,203 @@ exports.baseToolDefinitions = [
|
|
|
104
113
|
tool: {
|
|
105
114
|
type: "function",
|
|
106
115
|
function: {
|
|
107
|
-
name: "
|
|
108
|
-
description: "
|
|
116
|
+
name: "edit_file",
|
|
117
|
+
description: "surgically edit a file by replacing an exact string. the file must have been read via read_file first. old_string must match exactly one location in the file.",
|
|
109
118
|
parameters: {
|
|
110
119
|
type: "object",
|
|
111
|
-
properties: {
|
|
112
|
-
|
|
120
|
+
properties: {
|
|
121
|
+
path: { type: "string" },
|
|
122
|
+
old_string: { type: "string" },
|
|
123
|
+
new_string: { type: "string" },
|
|
124
|
+
},
|
|
125
|
+
required: ["path", "old_string", "new_string"],
|
|
113
126
|
},
|
|
114
127
|
},
|
|
115
128
|
},
|
|
116
|
-
handler: (a) =>
|
|
129
|
+
handler: (a) => {
|
|
130
|
+
if (!exports.editFileReadTracker.has(a.path)) {
|
|
131
|
+
return `error: you must read the file with read_file before editing it. call read_file on ${a.path} first.`;
|
|
132
|
+
}
|
|
133
|
+
let content;
|
|
134
|
+
try {
|
|
135
|
+
content = fs.readFileSync(a.path, "utf-8");
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
return `error: could not read file: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
|
|
139
|
+
}
|
|
140
|
+
// Count occurrences
|
|
141
|
+
const occurrences = [];
|
|
142
|
+
let searchFrom = 0;
|
|
143
|
+
while (true) {
|
|
144
|
+
const idx = content.indexOf(a.old_string, searchFrom);
|
|
145
|
+
if (idx === -1)
|
|
146
|
+
break;
|
|
147
|
+
occurrences.push(idx);
|
|
148
|
+
searchFrom = idx + 1;
|
|
149
|
+
}
|
|
150
|
+
if (occurrences.length === 0) {
|
|
151
|
+
return `error: old_string not found in ${a.path}`;
|
|
152
|
+
}
|
|
153
|
+
if (occurrences.length > 1) {
|
|
154
|
+
return `error: old_string is ambiguous -- found ${occurrences.length} matches in ${a.path}. provide more context to make the match unique.`;
|
|
155
|
+
}
|
|
156
|
+
// Single unique match -- replace
|
|
157
|
+
const idx = occurrences[0];
|
|
158
|
+
const updated = content.slice(0, idx) + a.new_string + content.slice(idx + a.old_string.length);
|
|
159
|
+
fs.writeFileSync(a.path, updated, "utf-8");
|
|
160
|
+
// Build contextual diff
|
|
161
|
+
const lines = updated.split("\n");
|
|
162
|
+
const prefixLines = content.slice(0, idx).split("\n");
|
|
163
|
+
const changeStartLine = prefixLines.length - 1;
|
|
164
|
+
const newStringLines = a.new_string.split("\n");
|
|
165
|
+
const changeEndLine = changeStartLine + newStringLines.length;
|
|
166
|
+
return buildContextDiff(lines, changeStartLine, changeEndLine);
|
|
167
|
+
},
|
|
117
168
|
},
|
|
118
169
|
{
|
|
119
170
|
tool: {
|
|
120
171
|
type: "function",
|
|
121
172
|
function: {
|
|
122
|
-
name: "
|
|
123
|
-
description: "
|
|
173
|
+
name: "glob",
|
|
174
|
+
description: "find files matching a glob pattern. returns matching paths sorted alphabetically, one per line.",
|
|
124
175
|
parameters: {
|
|
125
176
|
type: "object",
|
|
126
|
-
properties: {
|
|
127
|
-
|
|
177
|
+
properties: {
|
|
178
|
+
pattern: { type: "string", description: "glob pattern (e.g. **/*.ts)" },
|
|
179
|
+
cwd: { type: "string", description: "directory to search from (defaults to process.cwd())" },
|
|
180
|
+
},
|
|
181
|
+
required: ["pattern"],
|
|
128
182
|
},
|
|
129
183
|
},
|
|
130
184
|
},
|
|
131
|
-
handler: (a) =>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
.join("\n")
|
|
185
|
+
handler: (a) => {
|
|
186
|
+
const cwd = a.cwd || process.cwd();
|
|
187
|
+
const matches = fg.globSync(a.pattern, { cwd, dot: true });
|
|
188
|
+
return matches.sort().join("\n");
|
|
189
|
+
},
|
|
135
190
|
},
|
|
136
191
|
{
|
|
137
192
|
tool: {
|
|
138
193
|
type: "function",
|
|
139
194
|
function: {
|
|
140
|
-
name: "
|
|
141
|
-
description: "
|
|
195
|
+
name: "grep",
|
|
196
|
+
description: "search file contents for lines matching a regex pattern. searches recursively when given a directory. returns matching lines with file path and line numbers.",
|
|
142
197
|
parameters: {
|
|
143
198
|
type: "object",
|
|
144
199
|
properties: {
|
|
145
|
-
|
|
146
|
-
|
|
200
|
+
pattern: { type: "string", description: "regex pattern to search for" },
|
|
201
|
+
path: { type: "string", description: "file or directory to search" },
|
|
202
|
+
context_lines: { type: "number", description: "number of surrounding context lines (default 0)" },
|
|
203
|
+
include: { type: "string", description: "glob filter to limit searched files (e.g. *.ts)" },
|
|
147
204
|
},
|
|
148
|
-
required: ["
|
|
205
|
+
required: ["pattern", "path"],
|
|
149
206
|
},
|
|
150
207
|
},
|
|
151
208
|
},
|
|
152
209
|
handler: (a) => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
210
|
+
const targetPath = a.path;
|
|
211
|
+
const regex = new RegExp(a.pattern);
|
|
212
|
+
const contextLines = parseInt(a.context_lines || "0", 10);
|
|
213
|
+
const includeGlob = a.include || undefined;
|
|
214
|
+
function searchFile(filePath) {
|
|
215
|
+
let content;
|
|
216
|
+
try {
|
|
217
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return [];
|
|
156
221
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
222
|
+
const lines = content.split("\n");
|
|
223
|
+
const matchIndices = new Set();
|
|
224
|
+
for (let i = 0; i < lines.length; i++) {
|
|
225
|
+
if (regex.test(lines[i])) {
|
|
226
|
+
matchIndices.add(i);
|
|
160
227
|
}
|
|
161
|
-
(0, child_process_1.execSync)(`git add ${p}`, { encoding: "utf-8" });
|
|
162
228
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
229
|
+
if (matchIndices.size === 0)
|
|
230
|
+
return [];
|
|
231
|
+
const outputIndices = new Set();
|
|
232
|
+
for (const idx of matchIndices) {
|
|
233
|
+
const start = Math.max(0, idx - contextLines);
|
|
234
|
+
const end = Math.min(lines.length - 1, idx + contextLines);
|
|
235
|
+
for (let i = start; i <= end; i++) {
|
|
236
|
+
outputIndices.add(i);
|
|
237
|
+
}
|
|
166
238
|
}
|
|
167
|
-
(
|
|
168
|
-
|
|
239
|
+
const sortedIndices = [...outputIndices].sort((a, b) => a - b);
|
|
240
|
+
const results = [];
|
|
241
|
+
for (const idx of sortedIndices) {
|
|
242
|
+
const lineNum = idx + 1;
|
|
243
|
+
if (matchIndices.has(idx)) {
|
|
244
|
+
results.push(`${filePath}:${lineNum}: ${lines[idx]}`);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
results.push(`-${filePath}:${lineNum}: ${lines[idx]}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return results;
|
|
169
251
|
}
|
|
170
|
-
|
|
171
|
-
|
|
252
|
+
function collectFiles(dirPath) {
|
|
253
|
+
const files = [];
|
|
254
|
+
function walk(dir) {
|
|
255
|
+
let entries;
|
|
256
|
+
try {
|
|
257
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
for (const entry of entries) {
|
|
263
|
+
const fullPath = path.join(dir, entry.name);
|
|
264
|
+
if (entry.isDirectory()) {
|
|
265
|
+
walk(fullPath);
|
|
266
|
+
}
|
|
267
|
+
else if (entry.isFile()) {
|
|
268
|
+
files.push(fullPath);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
walk(dirPath);
|
|
273
|
+
return files.sort();
|
|
274
|
+
}
|
|
275
|
+
function matchesGlob(filePath, glob) {
|
|
276
|
+
const escaped = glob
|
|
277
|
+
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
278
|
+
.replace(/\*/g, ".*")
|
|
279
|
+
.replace(/\?/g, ".");
|
|
280
|
+
return new RegExp(`(^|/)${escaped}$`).test(filePath);
|
|
281
|
+
}
|
|
282
|
+
const stat = fs.statSync(targetPath, { throwIfNoEntry: false });
|
|
283
|
+
if (!stat)
|
|
284
|
+
return "";
|
|
285
|
+
if (stat.isFile()) {
|
|
286
|
+
return searchFile(targetPath).join("\n");
|
|
287
|
+
}
|
|
288
|
+
let files = collectFiles(targetPath);
|
|
289
|
+
if (includeGlob) {
|
|
290
|
+
files = files.filter((f) => matchesGlob(f, includeGlob));
|
|
172
291
|
}
|
|
292
|
+
const allResults = [];
|
|
293
|
+
for (const file of files) {
|
|
294
|
+
allResults.push(...searchFile(file));
|
|
295
|
+
}
|
|
296
|
+
return allResults.join("\n");
|
|
173
297
|
},
|
|
174
298
|
},
|
|
175
299
|
{
|
|
176
300
|
tool: {
|
|
177
301
|
type: "function",
|
|
178
302
|
function: {
|
|
179
|
-
name: "
|
|
180
|
-
description: "
|
|
303
|
+
name: "shell",
|
|
304
|
+
description: "run shell command",
|
|
181
305
|
parameters: {
|
|
182
306
|
type: "object",
|
|
183
|
-
properties: {
|
|
184
|
-
command: { type: "string" },
|
|
185
|
-
},
|
|
307
|
+
properties: { command: { type: "string" } },
|
|
186
308
|
required: ["command"],
|
|
187
309
|
},
|
|
188
310
|
},
|
|
189
311
|
},
|
|
190
|
-
handler: (a) => {
|
|
191
|
-
try {
|
|
192
|
-
return (0, child_process_1.execSync)(`gh ${a.command}`, { encoding: "utf-8", timeout: 60000 });
|
|
193
|
-
}
|
|
194
|
-
catch (e) {
|
|
195
|
-
return `error: ${e}`;
|
|
196
|
-
}
|
|
197
|
-
},
|
|
312
|
+
handler: (a) => (0, child_process_1.execSync)(a.command, { encoding: "utf-8", timeout: 30000 }),
|
|
198
313
|
},
|
|
199
314
|
{
|
|
200
315
|
tool: {
|
|
@@ -229,20 +344,6 @@ exports.baseToolDefinitions = [
|
|
|
229
344
|
}
|
|
230
345
|
},
|
|
231
346
|
},
|
|
232
|
-
{
|
|
233
|
-
tool: {
|
|
234
|
-
type: "function",
|
|
235
|
-
function: {
|
|
236
|
-
name: "get_current_time",
|
|
237
|
-
description: "get the current date and time in America/Los_Angeles (Pacific Time)",
|
|
238
|
-
parameters: { type: "object", properties: {} },
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
handler: () => new Date().toLocaleString("en-US", {
|
|
242
|
-
timeZone: "America/Los_Angeles",
|
|
243
|
-
hour12: false,
|
|
244
|
-
}),
|
|
245
|
-
},
|
|
246
347
|
{
|
|
247
348
|
tool: {
|
|
248
349
|
type: "function",
|
|
@@ -398,192 +499,6 @@ exports.baseToolDefinitions = [
|
|
|
398
499
|
return JSON.stringify(friend, null, 2);
|
|
399
500
|
},
|
|
400
501
|
},
|
|
401
|
-
{
|
|
402
|
-
tool: {
|
|
403
|
-
type: "function",
|
|
404
|
-
function: {
|
|
405
|
-
name: "task_board",
|
|
406
|
-
description: "show the task board grouped by status",
|
|
407
|
-
parameters: { type: "object", properties: {} },
|
|
408
|
-
},
|
|
409
|
-
},
|
|
410
|
-
handler: () => {
|
|
411
|
-
const board = (0, tasks_1.getTaskModule)().getBoard();
|
|
412
|
-
return board.full || board.compact || "no tasks found";
|
|
413
|
-
},
|
|
414
|
-
},
|
|
415
|
-
{
|
|
416
|
-
tool: {
|
|
417
|
-
type: "function",
|
|
418
|
-
function: {
|
|
419
|
-
name: "task_create",
|
|
420
|
-
description: "create a new task in the bundle task system. optionally set `scheduledAt` for a one-time reminder or `cadence` for recurring daemon-scheduled work.",
|
|
421
|
-
parameters: {
|
|
422
|
-
type: "object",
|
|
423
|
-
properties: {
|
|
424
|
-
title: { type: "string" },
|
|
425
|
-
type: { type: "string", enum: ["one-shot", "ongoing", "habit"] },
|
|
426
|
-
category: { type: "string" },
|
|
427
|
-
body: { type: "string" },
|
|
428
|
-
status: { type: "string" },
|
|
429
|
-
validator: { type: "string" },
|
|
430
|
-
requester: { type: "string" },
|
|
431
|
-
scheduledAt: { type: "string", description: "ISO timestamp for a one-time scheduled run/reminder" },
|
|
432
|
-
cadence: { type: "string", description: "recurrence like 30m, 1h, 1d, or cron" },
|
|
433
|
-
},
|
|
434
|
-
required: ["title", "type", "category", "body"],
|
|
435
|
-
},
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
handler: (a) => {
|
|
439
|
-
try {
|
|
440
|
-
const created = (0, tasks_1.getTaskModule)().createTask(buildTaskCreateInput(a));
|
|
441
|
-
return `created: ${created}`;
|
|
442
|
-
}
|
|
443
|
-
catch (error) {
|
|
444
|
-
return `error: ${error instanceof Error ? error.message : String(error)}`;
|
|
445
|
-
}
|
|
446
|
-
},
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
tool: {
|
|
450
|
-
type: "function",
|
|
451
|
-
function: {
|
|
452
|
-
name: "schedule_reminder",
|
|
453
|
-
description: "create a scheduled reminder or recurring daemon job. use `scheduledAt` for one-time reminders and `cadence` for recurring reminders. this writes canonical task fields that the daemon reconciles into OS-level jobs.",
|
|
454
|
-
parameters: {
|
|
455
|
-
type: "object",
|
|
456
|
-
properties: {
|
|
457
|
-
title: { type: "string" },
|
|
458
|
-
body: { type: "string" },
|
|
459
|
-
category: { type: "string" },
|
|
460
|
-
scheduledAt: { type: "string", description: "ISO timestamp for a one-time reminder" },
|
|
461
|
-
cadence: { type: "string", description: "recurrence like 30m, 1h, 1d, or cron" },
|
|
462
|
-
},
|
|
463
|
-
required: ["title", "body"],
|
|
464
|
-
},
|
|
465
|
-
},
|
|
466
|
-
},
|
|
467
|
-
handler: (a) => {
|
|
468
|
-
const scheduledAt = normalizeOptionalText(a.scheduledAt);
|
|
469
|
-
const cadence = normalizeOptionalText(a.cadence);
|
|
470
|
-
if (!scheduledAt && !cadence) {
|
|
471
|
-
return "error: provide scheduledAt or cadence";
|
|
472
|
-
}
|
|
473
|
-
try {
|
|
474
|
-
const created = (0, tasks_1.getTaskModule)().createTask({
|
|
475
|
-
title: a.title,
|
|
476
|
-
type: cadence ? "habit" : "one-shot",
|
|
477
|
-
category: normalizeOptionalText(a.category) ?? "reminder",
|
|
478
|
-
body: a.body,
|
|
479
|
-
scheduledAt,
|
|
480
|
-
cadence,
|
|
481
|
-
});
|
|
482
|
-
return `created: ${created}`;
|
|
483
|
-
}
|
|
484
|
-
catch (error) {
|
|
485
|
-
return `error: ${error instanceof Error ? error.message : String(error)}`;
|
|
486
|
-
}
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
tool: {
|
|
491
|
-
type: "function",
|
|
492
|
-
function: {
|
|
493
|
-
name: "task_update_status",
|
|
494
|
-
description: "update a task status using validated transitions",
|
|
495
|
-
parameters: {
|
|
496
|
-
type: "object",
|
|
497
|
-
properties: {
|
|
498
|
-
name: { type: "string" },
|
|
499
|
-
status: { type: "string" },
|
|
500
|
-
},
|
|
501
|
-
required: ["name", "status"],
|
|
502
|
-
},
|
|
503
|
-
},
|
|
504
|
-
},
|
|
505
|
-
handler: (a) => {
|
|
506
|
-
const result = (0, tasks_1.getTaskModule)().updateStatus(a.name, a.status);
|
|
507
|
-
if (!result.ok) {
|
|
508
|
-
return `error: ${result.reason ?? "status update failed"}`;
|
|
509
|
-
}
|
|
510
|
-
const archivedSuffix = result.archived && result.archived.length > 0
|
|
511
|
-
? ` | archived: ${result.archived.join(", ")}`
|
|
512
|
-
: "";
|
|
513
|
-
return `updated: ${a.name} -> ${result.to}${archivedSuffix}`;
|
|
514
|
-
},
|
|
515
|
-
},
|
|
516
|
-
{
|
|
517
|
-
tool: {
|
|
518
|
-
type: "function",
|
|
519
|
-
function: {
|
|
520
|
-
name: "task_board_status",
|
|
521
|
-
description: "show board detail for a specific status",
|
|
522
|
-
parameters: {
|
|
523
|
-
type: "object",
|
|
524
|
-
properties: {
|
|
525
|
-
status: { type: "string" },
|
|
526
|
-
},
|
|
527
|
-
required: ["status"],
|
|
528
|
-
},
|
|
529
|
-
},
|
|
530
|
-
},
|
|
531
|
-
handler: (a) => {
|
|
532
|
-
const lines = (0, tasks_1.getTaskModule)().boardStatus(a.status);
|
|
533
|
-
return lines.length > 0 ? lines.join("\n") : "no tasks in that status";
|
|
534
|
-
},
|
|
535
|
-
},
|
|
536
|
-
{
|
|
537
|
-
tool: {
|
|
538
|
-
type: "function",
|
|
539
|
-
function: {
|
|
540
|
-
name: "task_board_action",
|
|
541
|
-
description: "show tasks or validation issues that require action",
|
|
542
|
-
parameters: {
|
|
543
|
-
type: "object",
|
|
544
|
-
properties: {
|
|
545
|
-
scope: { type: "string" },
|
|
546
|
-
},
|
|
547
|
-
},
|
|
548
|
-
},
|
|
549
|
-
},
|
|
550
|
-
handler: (a) => {
|
|
551
|
-
const lines = (0, tasks_1.getTaskModule)().boardAction();
|
|
552
|
-
if (!a.scope) {
|
|
553
|
-
return lines.length > 0 ? lines.join("\n") : "no action required";
|
|
554
|
-
}
|
|
555
|
-
const filtered = lines.filter((line) => line.includes(a.scope));
|
|
556
|
-
return filtered.length > 0 ? filtered.join("\n") : "no matching action items";
|
|
557
|
-
},
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
tool: {
|
|
561
|
-
type: "function",
|
|
562
|
-
function: {
|
|
563
|
-
name: "task_board_deps",
|
|
564
|
-
description: "show unresolved task dependencies",
|
|
565
|
-
parameters: { type: "object", properties: {} },
|
|
566
|
-
},
|
|
567
|
-
},
|
|
568
|
-
handler: () => {
|
|
569
|
-
const lines = (0, tasks_1.getTaskModule)().boardDeps();
|
|
570
|
-
return lines.length > 0 ? lines.join("\n") : "no unresolved dependencies";
|
|
571
|
-
},
|
|
572
|
-
},
|
|
573
|
-
{
|
|
574
|
-
tool: {
|
|
575
|
-
type: "function",
|
|
576
|
-
function: {
|
|
577
|
-
name: "task_board_sessions",
|
|
578
|
-
description: "show tasks with active coding or sub-agent sessions",
|
|
579
|
-
parameters: { type: "object", properties: {} },
|
|
580
|
-
},
|
|
581
|
-
},
|
|
582
|
-
handler: () => {
|
|
583
|
-
const lines = (0, tasks_1.getTaskModule)().boardSessions();
|
|
584
|
-
return lines.length > 0 ? lines.join("\n") : "no active sessions";
|
|
585
|
-
},
|
|
586
|
-
},
|
|
587
502
|
{
|
|
588
503
|
tool: {
|
|
589
504
|
type: "function",
|
|
@@ -741,12 +656,18 @@ exports.baseToolDefinitions = [
|
|
|
741
656
|
const key = args.key || "session";
|
|
742
657
|
const content = args.content;
|
|
743
658
|
const now = Date.now();
|
|
744
|
-
const
|
|
659
|
+
const agentName = (0, identity_1.getAgentName)();
|
|
660
|
+
// Self-routing: messages to "self" always go to inner dialog pending dir,
|
|
661
|
+
// regardless of the channel or key the agent specified.
|
|
662
|
+
const isSelf = friendId === "self";
|
|
663
|
+
const pendingDir = isSelf
|
|
664
|
+
? (0, pending_1.getPendingDir)(agentName, "self", "inner", "dialog")
|
|
665
|
+
: (0, pending_1.getPendingDir)(agentName, friendId, channel, key);
|
|
745
666
|
fs.mkdirSync(pendingDir, { recursive: true });
|
|
746
667
|
const fileName = `${now}-${Math.random().toString(36).slice(2, 10)}.json`;
|
|
747
668
|
const filePath = path.join(pendingDir, fileName);
|
|
748
669
|
const envelope = {
|
|
749
|
-
from:
|
|
670
|
+
from: agentName,
|
|
750
671
|
friendId,
|
|
751
672
|
channel,
|
|
752
673
|
key,
|
|
@@ -755,7 +676,8 @@ exports.baseToolDefinitions = [
|
|
|
755
676
|
};
|
|
756
677
|
fs.writeFileSync(filePath, JSON.stringify(envelope, null, 2));
|
|
757
678
|
const preview = content.length > 80 ? content.slice(0, 80) + "…" : content;
|
|
758
|
-
|
|
679
|
+
const target = isSelf ? "inner/dialog" : `${channel}/${key}`;
|
|
680
|
+
return `message queued for delivery to ${friendId} on ${target}. preview: "${preview}". it will be delivered when their session is next active.`;
|
|
759
681
|
},
|
|
760
682
|
},
|
|
761
683
|
...tools_1.codingToolDefinitions,
|
package/dist/repertoire/tools.js
CHANGED
|
@@ -18,14 +18,8 @@ Object.defineProperty(exports, "finalAnswerTool", { enumerable: true, get: funct
|
|
|
18
18
|
var tools_teams_2 = require("./tools-teams");
|
|
19
19
|
Object.defineProperty(exports, "teamsTools", { enumerable: true, get: function () { return tools_teams_2.teamsTools; } });
|
|
20
20
|
// All tool definitions in a single registry
|
|
21
|
-
const allDefinitions = [
|
|
22
|
-
|
|
23
|
-
...tools_bluebubbles_1.bluebubblesToolDefinitions,
|
|
24
|
-
...tools_teams_1.teamsToolDefinitions,
|
|
25
|
-
...ado_semantic_1.adoSemanticToolDefinitions,
|
|
26
|
-
...tools_github_1.githubToolDefinitions,
|
|
27
|
-
];
|
|
28
|
-
const REMOTE_BLOCKED_LOCAL_TOOLS = new Set(["shell", "read_file", "write_file", "git_commit", "gh_cli"]);
|
|
21
|
+
const allDefinitions = [...tools_base_1.baseToolDefinitions, ...tools_bluebubbles_1.bluebubblesToolDefinitions, ...tools_teams_1.teamsToolDefinitions, ...ado_semantic_1.adoSemanticToolDefinitions, ...tools_github_1.githubToolDefinitions];
|
|
22
|
+
const REMOTE_BLOCKED_LOCAL_TOOLS = new Set(["shell", "read_file", "write_file", "edit_file", "glob", "grep"]);
|
|
29
23
|
function isRemoteChannel(capabilities) {
|
|
30
24
|
return capabilities?.channel === "teams" || capabilities?.channel === "bluebubbles";
|
|
31
25
|
}
|
|
@@ -183,28 +177,16 @@ function summarizeArgs(name, args) {
|
|
|
183
177
|
// Base tools
|
|
184
178
|
if (name === "read_file" || name === "write_file")
|
|
185
179
|
return summarizeKeyValues(args, ["path"]);
|
|
186
|
-
if (name === "
|
|
187
|
-
return summarizeKeyValues(args, ["command"]);
|
|
188
|
-
if (name === "list_directory")
|
|
180
|
+
if (name === "edit_file")
|
|
189
181
|
return summarizeKeyValues(args, ["path"]);
|
|
190
|
-
if (name === "
|
|
191
|
-
return summarizeKeyValues(args, ["
|
|
192
|
-
if (name === "
|
|
182
|
+
if (name === "glob")
|
|
183
|
+
return summarizeKeyValues(args, ["pattern", "cwd"]);
|
|
184
|
+
if (name === "grep")
|
|
185
|
+
return summarizeKeyValues(args, ["pattern", "path", "include"]);
|
|
186
|
+
if (name === "shell")
|
|
193
187
|
return summarizeKeyValues(args, ["command"]);
|
|
194
188
|
if (name === "load_skill")
|
|
195
189
|
return summarizeKeyValues(args, ["name"]);
|
|
196
|
-
if (name === "task_create")
|
|
197
|
-
return summarizeKeyValues(args, ["title", "type", "category", "scheduledAt", "cadence"]);
|
|
198
|
-
if (name === "schedule_reminder")
|
|
199
|
-
return summarizeKeyValues(args, ["title", "scheduledAt", "cadence"]);
|
|
200
|
-
if (name === "task_update_status")
|
|
201
|
-
return summarizeKeyValues(args, ["name", "status"]);
|
|
202
|
-
if (name === "task_board_status")
|
|
203
|
-
return summarizeKeyValues(args, ["status"]);
|
|
204
|
-
if (name === "task_board_action")
|
|
205
|
-
return summarizeKeyValues(args, ["scope"]);
|
|
206
|
-
if (name === "task_board" || name === "task_board_deps" || name === "task_board_sessions")
|
|
207
|
-
return "";
|
|
208
190
|
if (name === "coding_spawn")
|
|
209
191
|
return summarizeKeyValues(args, ["runner", "workdir", "taskRef"]);
|
|
210
192
|
if (name === "coding_status")
|