@wrongstack/tools 0.281.3 → 0.282.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/audit.js +34 -13
- package/dist/audit.js.map +1 -1
- package/dist/bash.js +41 -23
- package/dist/bash.js.map +1 -1
- package/dist/builtin.js +613 -72
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.js +61 -2
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/codebase-index/worker.js +61 -2
- package/dist/codebase-index/worker.js.map +1 -1
- package/dist/exec.js +34 -13
- package/dist/exec.js.map +1 -1
- package/dist/format.js +34 -13
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +242 -192
- package/dist/index.js +12613 -12074
- package/dist/index.js.map +1 -1
- package/dist/install.js +34 -13
- package/dist/install.js.map +1 -1
- package/dist/lint.js +34 -13
- package/dist/lint.js.map +1 -1
- package/dist/pack.js +612 -72
- package/dist/pack.js.map +1 -1
- package/dist/process-registry.d.ts +16 -3
- package/dist/process-registry.js +34 -13
- package/dist/process-registry.js.map +1 -1
- package/dist/test.js +34 -13
- package/dist/test.js.map +1 -1
- package/dist/typecheck.js +34 -13
- package/dist/typecheck.js.map +1 -1
- package/dist/write.js +65 -46
- package/dist/write.js.map +1 -1
- package/package.json +2 -2
package/dist/pack.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn, execFileSync } from 'node:child_process';
|
|
2
2
|
import * as Core from '@wrongstack/core';
|
|
3
|
-
import { buildChildEnv, getDesignKitLoader, isDesignStack, loadActiveKit, applyTokenOverrides, setActiveKit, recordKitChoice, recordOverrides, setDesignOverrides, materializeTokens, runDesignVerify, ToolValidationError, detectNewlineStyle, normalizeToLf, toStyle, atomicWrite, unifiedDiff, ToolError, FetchError, isPrivateIPv4, isPrivateIPv6, assessCommitSafety, compileGlob, expectDefined, recordPackageAction, detectPackageEcosystem, deepMerge, mutatePlan, clearPlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, mutateTasks, formatTaskList, formatPlan, FsError, toErrorMessage as toErrorMessage$2, computeTaskItemProgress, loadPlan, savePlan, loadTasks, saveTasks, wstackGlobalRoot, resolveWstackPaths, truncate } from '@wrongstack/core';
|
|
3
|
+
import { buildChildEnv, getDesignKitLoader, isDesignStack, loadActiveKit, applyTokenOverrides, setActiveKit, recordKitChoice, recordOverrides, setDesignOverrides, materializeTokens, runDesignVerify, ToolValidationError, detectNewlineStyle, normalizeToLf, toStyle, atomicWrite, unifiedDiff, ToolError, FetchError, isPrivateIPv4, isPrivateIPv6, assessCommitSafety, compileGlob, expectDefined, recordPackageAction, detectPackageEcosystem, deepMerge, addLinkToTask, addNoteToTask, updateCheckOnTask, addCheckToTask, addDependency, updateTaskAssignment, assignTask, removeTask, moveTask, updateTask, getTask, transferTaskToBoard, copyTaskToBoard, addTask, removeColumn, updateColumn, addColumn, searchKanban, exportBoardAsMarkdown, generateBoardFromDescription, createBoard, parseLinesIntoTasks, getBoard, removeBoard, duplicateBoard, updateBoard, listBoards, mutatePlan, clearPlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, mutateTasks, formatTaskList, formatPlan, FsError, toErrorMessage as toErrorMessage$2, computeTaskItemProgress, loadPlan, savePlan, loadTasks, saveTasks, wstackGlobalRoot, resolveWstackPaths, truncate } from '@wrongstack/core';
|
|
4
4
|
import * as fs from 'node:fs';
|
|
5
5
|
import { statSync, mkdirSync, createWriteStream } from 'node:fs';
|
|
6
6
|
import * as fs2 from 'node:fs/promises';
|
|
@@ -345,14 +345,34 @@ function redactCommand(cmd) {
|
|
|
345
345
|
return result;
|
|
346
346
|
}
|
|
347
347
|
var DEFAULT_GRACE_MS = 2e3;
|
|
348
|
-
|
|
348
|
+
var WIN32_TASKKILL_TIMEOUT_MS = 5e3;
|
|
349
|
+
function killWin32Tree(pid, opts = {}) {
|
|
349
350
|
try {
|
|
350
351
|
const child = spawn("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
351
352
|
stdio: "ignore",
|
|
352
353
|
windowsHide: true
|
|
353
354
|
});
|
|
354
|
-
|
|
355
|
-
|
|
355
|
+
let settled = false;
|
|
356
|
+
let timeout;
|
|
357
|
+
const settle = () => {
|
|
358
|
+
if (settled) return;
|
|
359
|
+
settled = true;
|
|
360
|
+
if (timeout) clearTimeout(timeout);
|
|
361
|
+
try {
|
|
362
|
+
opts.onSettled?.();
|
|
363
|
+
} catch {
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
child.on("error", settle);
|
|
367
|
+
child.on("close", settle);
|
|
368
|
+
timeout = setTimeout(() => {
|
|
369
|
+
try {
|
|
370
|
+
child.kill();
|
|
371
|
+
} catch {
|
|
372
|
+
}
|
|
373
|
+
settle();
|
|
374
|
+
}, Math.max(1, opts.timeoutMs ?? WIN32_TASKKILL_TIMEOUT_MS));
|
|
375
|
+
timeout.unref?.();
|
|
356
376
|
child.unref();
|
|
357
377
|
return true;
|
|
358
378
|
} catch {
|
|
@@ -582,17 +602,18 @@ var ProcessRegistryImpl = class {
|
|
|
582
602
|
const isWin4 = os2.platform() === "win32";
|
|
583
603
|
if (isWin4) {
|
|
584
604
|
const liveRealChild = p.child.exitCode === null && typeof p.child.pid === "number";
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
} catch {
|
|
591
|
-
}
|
|
605
|
+
const directFallback = () => {
|
|
606
|
+
if (p.child.exitCode === null) {
|
|
607
|
+
try {
|
|
608
|
+
p.child.kill("SIGKILL");
|
|
609
|
+
} catch {
|
|
592
610
|
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
if (liveRealChild && killWin32Tree(pid, {
|
|
614
|
+
timeoutMs: Math.max(graceMs, WIN32_TASKKILL_TIMEOUT_MS),
|
|
615
|
+
onSettled: directFallback
|
|
616
|
+
})) ; else {
|
|
596
617
|
try {
|
|
597
618
|
p.child.kill(force ? "SIGKILL" : "SIGTERM");
|
|
598
619
|
} catch {
|
|
@@ -2088,17 +2109,14 @@ var bashTool = {
|
|
|
2088
2109
|
const spool = createOutputSpool({ tool: "bash", thresholdBytes: MAX_OUTPUT });
|
|
2089
2110
|
function killWithTimeout(child2, timeoutMs2) {
|
|
2090
2111
|
if (isWin4) {
|
|
2091
|
-
if (typeof child2.pid === "number" && child2.exitCode === null
|
|
2092
|
-
const
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
}
|
|
2112
|
+
if (typeof child2.pid === "number" && child2.exitCode === null) {
|
|
2113
|
+
const attempted = registry.kill(child2.pid, { force: true, graceMs: timeoutMs2 });
|
|
2114
|
+
if (!attempted) {
|
|
2115
|
+
try {
|
|
2116
|
+
child2.kill();
|
|
2117
|
+
} catch {
|
|
2098
2118
|
}
|
|
2099
|
-
}
|
|
2100
|
-
timers.push(fallback);
|
|
2101
|
-
fallback.unref?.();
|
|
2119
|
+
}
|
|
2102
2120
|
} else {
|
|
2103
2121
|
try {
|
|
2104
2122
|
child2.kill();
|
|
@@ -3475,10 +3493,69 @@ function detectLang(file) {
|
|
|
3475
3493
|
async function parseSymbols2(opts) {
|
|
3476
3494
|
const { file, content, lang } = opts;
|
|
3477
3495
|
try {
|
|
3478
|
-
|
|
3496
|
+
const parsed = await syncGoParse(file, content, lang);
|
|
3497
|
+
if (parsed.symbols.length > 0) {
|
|
3498
|
+
return parsed;
|
|
3499
|
+
}
|
|
3500
|
+
return fallbackParse(file, content, lang);
|
|
3479
3501
|
} catch {
|
|
3480
|
-
return
|
|
3502
|
+
return fallbackParse(file, content, lang);
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
function fallbackParse(filePath, content, lang) {
|
|
3506
|
+
if (!/^\s*package\s+[A-Za-z_]\w*/m.test(content) || hasUnbalancedDelimiters(content)) {
|
|
3507
|
+
return { file: filePath, lang, symbols: [], mtimeMs: Date.now() };
|
|
3508
|
+
}
|
|
3509
|
+
const symbols = [];
|
|
3510
|
+
const packageName = content.match(/^\s*package\s+([A-Za-z_]\w*)/m)?.[1] ?? "";
|
|
3511
|
+
const lines = content.split(/\r?\n/);
|
|
3512
|
+
for (const [idx, line] of lines.entries()) {
|
|
3513
|
+
const trimmed = line.trimStart();
|
|
3514
|
+
const col = line.length - trimmed.length + 1;
|
|
3515
|
+
const fn = /^func\s+(?:\([^)]*\)\s*)?([A-Za-z_]\w*)\s*\(/.exec(trimmed);
|
|
3516
|
+
if (fn?.[1]) {
|
|
3517
|
+
addFallbackSymbol(symbols, { filePath, lang, kind: trimmed.startsWith("func (") ? "method" : "function", name: fn[1], line: idx + 1, col, signature: trimmed, scope: packageName ? `${packageName}.${fn[1]}` : fn[1] });
|
|
3518
|
+
continue;
|
|
3519
|
+
}
|
|
3520
|
+
const typeDecl = /^type\s+([A-Za-z_]\w*)\b/.exec(trimmed);
|
|
3521
|
+
if (typeDecl?.[1]) {
|
|
3522
|
+
addFallbackSymbol(symbols, { filePath, lang, kind: "type", name: typeDecl[1], line: idx + 1, col, signature: trimmed, scope: packageName });
|
|
3523
|
+
continue;
|
|
3524
|
+
}
|
|
3525
|
+
const valueDecl = /^(const|var)\s+([A-Za-z_]\w*)\b/.exec(trimmed);
|
|
3526
|
+
if (valueDecl?.[1] && valueDecl[2]) {
|
|
3527
|
+
addFallbackSymbol(symbols, { filePath, lang, kind: valueDecl[1], name: valueDecl[2], line: idx + 1, col, signature: trimmed, scope: packageName });
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
return { file: filePath, lang, symbols, mtimeMs: Date.now() };
|
|
3531
|
+
}
|
|
3532
|
+
function addFallbackSymbol(symbols, opts) {
|
|
3533
|
+
symbols.push({
|
|
3534
|
+
id: 0,
|
|
3535
|
+
lang: opts.lang,
|
|
3536
|
+
kind: opts.kind,
|
|
3537
|
+
name: opts.name,
|
|
3538
|
+
file: opts.filePath,
|
|
3539
|
+
line: opts.line,
|
|
3540
|
+
col: opts.col,
|
|
3541
|
+
signature: opts.signature,
|
|
3542
|
+
docComment: "",
|
|
3543
|
+
scope: opts.scope,
|
|
3544
|
+
text: `${opts.name} ${opts.signature}`.trim()
|
|
3545
|
+
});
|
|
3546
|
+
}
|
|
3547
|
+
function hasUnbalancedDelimiters(content) {
|
|
3548
|
+
const pairs = { "(": ")", "[": "]", "{": "}" };
|
|
3549
|
+
const closers = new Set(Object.values(pairs));
|
|
3550
|
+
const stack = [];
|
|
3551
|
+
for (const ch of content) {
|
|
3552
|
+
if (pairs[ch]) {
|
|
3553
|
+
stack.push(pairs[ch]);
|
|
3554
|
+
} else if (closers.has(ch) && stack.pop() !== ch) {
|
|
3555
|
+
return true;
|
|
3556
|
+
}
|
|
3481
3557
|
}
|
|
3558
|
+
return stack.length > 0;
|
|
3482
3559
|
}
|
|
3483
3560
|
var GO_PARSE_SCRIPT = `
|
|
3484
3561
|
package main
|
|
@@ -9206,6 +9283,449 @@ function toYaml(data, indent = 0) {
|
|
|
9206
9283
|
}
|
|
9207
9284
|
return String(data) + "\n";
|
|
9208
9285
|
}
|
|
9286
|
+
var kanbanTool = {
|
|
9287
|
+
name: "kanban",
|
|
9288
|
+
category: "Project",
|
|
9289
|
+
description: "Manage project-scoped multi-kanban boards stored under .wrongstack/kanbans. Supports board/task/column CRUD, search, assignment metadata, provider/model/fallback routing hints, success checks, notes, links, and run status updates.",
|
|
9290
|
+
usageHint: "Use this for durable project kanban state. Assign tasks with provider/model/fallback hints before spawning agents; after a subagent starts or finishes, call mark_assignment to record subagentId/runTaskId/status/result.",
|
|
9291
|
+
permission: "confirm",
|
|
9292
|
+
mutating: true,
|
|
9293
|
+
capabilities: ["fs.write"],
|
|
9294
|
+
icon: "task",
|
|
9295
|
+
timeoutMs: 5e3,
|
|
9296
|
+
inputSchema: {
|
|
9297
|
+
type: "object",
|
|
9298
|
+
properties: {
|
|
9299
|
+
action: {
|
|
9300
|
+
type: "string",
|
|
9301
|
+
enum: [
|
|
9302
|
+
"list_boards",
|
|
9303
|
+
"get_board",
|
|
9304
|
+
"create_board",
|
|
9305
|
+
"duplicate_board",
|
|
9306
|
+
"update_board",
|
|
9307
|
+
"delete_board",
|
|
9308
|
+
"generate_board",
|
|
9309
|
+
"export_markdown",
|
|
9310
|
+
"search_tasks",
|
|
9311
|
+
"add_column",
|
|
9312
|
+
"update_column",
|
|
9313
|
+
"delete_column",
|
|
9314
|
+
"add_task",
|
|
9315
|
+
"copy_task",
|
|
9316
|
+
"transfer_task",
|
|
9317
|
+
"get_task",
|
|
9318
|
+
"update_task",
|
|
9319
|
+
"move_task",
|
|
9320
|
+
"delete_task",
|
|
9321
|
+
"assign_task",
|
|
9322
|
+
"mark_assignment",
|
|
9323
|
+
"add_dependency",
|
|
9324
|
+
"add_check",
|
|
9325
|
+
"update_check",
|
|
9326
|
+
"add_note",
|
|
9327
|
+
"add_link"
|
|
9328
|
+
]
|
|
9329
|
+
},
|
|
9330
|
+
boardId: { type: "string" },
|
|
9331
|
+
taskId: { type: "string" },
|
|
9332
|
+
columnId: { type: "string" },
|
|
9333
|
+
targetBoardId: { type: "string" },
|
|
9334
|
+
targetColumnId: { type: "string" },
|
|
9335
|
+
title: { type: "string" },
|
|
9336
|
+
description: { type: "string" },
|
|
9337
|
+
tags: { type: "array", items: { type: "string" } },
|
|
9338
|
+
labels: { type: "array", items: { type: "string" } },
|
|
9339
|
+
priority: { type: "string", enum: ["critical", "high", "medium", "low"] },
|
|
9340
|
+
status: {
|
|
9341
|
+
type: "string",
|
|
9342
|
+
enum: [
|
|
9343
|
+
"pending",
|
|
9344
|
+
"ready",
|
|
9345
|
+
"in_progress",
|
|
9346
|
+
"blocked",
|
|
9347
|
+
"review",
|
|
9348
|
+
"completed",
|
|
9349
|
+
"failed",
|
|
9350
|
+
"archived"
|
|
9351
|
+
]
|
|
9352
|
+
},
|
|
9353
|
+
order: { type: "number" },
|
|
9354
|
+
query: { type: "string" },
|
|
9355
|
+
agentId: { type: "string" },
|
|
9356
|
+
name: { type: "string" },
|
|
9357
|
+
role: { type: "string" },
|
|
9358
|
+
provider: { type: "string" },
|
|
9359
|
+
model: { type: "string" },
|
|
9360
|
+
fallbackProfile: { type: "string" },
|
|
9361
|
+
fallbackModels: { type: "array", items: { type: "string" } },
|
|
9362
|
+
tools: { type: "array", items: { type: "string" } },
|
|
9363
|
+
allowedCapabilities: { type: "array", items: { type: "string" } },
|
|
9364
|
+
subagentId: { type: "string" },
|
|
9365
|
+
runTaskId: { type: "string" },
|
|
9366
|
+
lastResult: { type: "string" },
|
|
9367
|
+
error: { type: "string" },
|
|
9368
|
+
assignmentStatus: {
|
|
9369
|
+
type: "string",
|
|
9370
|
+
enum: ["assigned", "queued", "running", "completed", "failed", "cancelled"]
|
|
9371
|
+
},
|
|
9372
|
+
dependencyTaskId: { type: "string" },
|
|
9373
|
+
checkId: { type: "string" },
|
|
9374
|
+
checkDescription: { type: "string" },
|
|
9375
|
+
checkStatus: { type: "string", enum: ["pending", "passed", "failed", "skipped"] },
|
|
9376
|
+
note: { type: "string" },
|
|
9377
|
+
author: { type: "string" },
|
|
9378
|
+
url: { type: "string" },
|
|
9379
|
+
linkTitle: { type: "string" },
|
|
9380
|
+
linkType: {
|
|
9381
|
+
type: "string",
|
|
9382
|
+
enum: ["issue", "pr", "doc", "commit", "design", "file", "url", "other"]
|
|
9383
|
+
},
|
|
9384
|
+
context: { type: "string" },
|
|
9385
|
+
columns: { type: "array", items: { type: "string" } },
|
|
9386
|
+
generatedBy: { type: "string" },
|
|
9387
|
+
includeTasks: { type: "boolean" },
|
|
9388
|
+
includeCompletedTasks: { type: "boolean" },
|
|
9389
|
+
preserveAssignment: { type: "boolean" },
|
|
9390
|
+
preserveDependencies: { type: "boolean" },
|
|
9391
|
+
moveTasksToColumnId: { type: "string" }
|
|
9392
|
+
},
|
|
9393
|
+
required: ["action"]
|
|
9394
|
+
},
|
|
9395
|
+
async execute(input, ctx) {
|
|
9396
|
+
const projectRoot = ctx.projectRoot;
|
|
9397
|
+
if (!projectRoot) return fail("No project root is available.");
|
|
9398
|
+
switch (input.action) {
|
|
9399
|
+
case "list_boards": {
|
|
9400
|
+
const boards = await listBoards(projectRoot);
|
|
9401
|
+
return { ok: true, message: `${boards.length} board(s).`, boards };
|
|
9402
|
+
}
|
|
9403
|
+
case "get_board": {
|
|
9404
|
+
const board = await requireBoard(projectRoot, input.boardId);
|
|
9405
|
+
return board ? okBoard(board) : fail("Board not found.");
|
|
9406
|
+
}
|
|
9407
|
+
case "create_board": {
|
|
9408
|
+
if (!input.title) return fail("create_board requires title.");
|
|
9409
|
+
const board = await createBoard(projectRoot, {
|
|
9410
|
+
title: input.title,
|
|
9411
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
9412
|
+
...input.tags !== void 0 ? { tags: input.tags } : {},
|
|
9413
|
+
...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {}
|
|
9414
|
+
});
|
|
9415
|
+
return { ok: true, message: `Board created: ${board.title}`, board };
|
|
9416
|
+
}
|
|
9417
|
+
case "update_board": {
|
|
9418
|
+
if (!input.boardId) return fail("update_board requires boardId.");
|
|
9419
|
+
const board = await updateBoard(projectRoot, input.boardId, {
|
|
9420
|
+
...input.title !== void 0 ? { title: input.title } : {},
|
|
9421
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
9422
|
+
...input.tags !== void 0 ? { tags: input.tags } : {}
|
|
9423
|
+
});
|
|
9424
|
+
return board ? okBoard(board, "Board updated.") : fail("Board not found.");
|
|
9425
|
+
}
|
|
9426
|
+
case "duplicate_board": {
|
|
9427
|
+
if (!input.boardId) return fail("duplicate_board requires boardId.");
|
|
9428
|
+
const board = await duplicateBoard(projectRoot, input.boardId, {
|
|
9429
|
+
...input.title !== void 0 ? { title: input.title } : {},
|
|
9430
|
+
...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {},
|
|
9431
|
+
...input.includeTasks !== void 0 ? { includeTasks: input.includeTasks } : {},
|
|
9432
|
+
...input.includeCompletedTasks !== void 0 ? { includeCompletedTasks: input.includeCompletedTasks } : {},
|
|
9433
|
+
...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {}
|
|
9434
|
+
});
|
|
9435
|
+
return board ? okBoard(board, "Board duplicated.") : fail("Board not found.");
|
|
9436
|
+
}
|
|
9437
|
+
case "delete_board": {
|
|
9438
|
+
if (!input.boardId) return fail("delete_board requires boardId.");
|
|
9439
|
+
const removed = await removeBoard(projectRoot, input.boardId);
|
|
9440
|
+
return { ok: removed, message: removed ? "Board deleted." : "Board not found." };
|
|
9441
|
+
}
|
|
9442
|
+
case "generate_board": {
|
|
9443
|
+
if (!input.description) return fail("generate_board requires description.");
|
|
9444
|
+
const boardInput = generateBoardFromDescription({
|
|
9445
|
+
description: input.description,
|
|
9446
|
+
...input.title !== void 0 ? { title: input.title } : {},
|
|
9447
|
+
...input.context !== void 0 ? { context: input.context } : {},
|
|
9448
|
+
...input.columns !== void 0 ? { columns: input.columns } : {}
|
|
9449
|
+
});
|
|
9450
|
+
const board = await createBoard(projectRoot, boardInput);
|
|
9451
|
+
for (const taskInput2 of parseLinesIntoTasks(
|
|
9452
|
+
input.description,
|
|
9453
|
+
board.columns[0]?.id ?? "backlog"
|
|
9454
|
+
)) {
|
|
9455
|
+
await addTask(projectRoot, board.id, taskInput2);
|
|
9456
|
+
}
|
|
9457
|
+
return okBoard(await getBoard(projectRoot, board.id) ?? board, "Board generated.");
|
|
9458
|
+
}
|
|
9459
|
+
case "export_markdown": {
|
|
9460
|
+
const board = await requireBoard(projectRoot, input.boardId);
|
|
9461
|
+
if (!board) return fail("Board not found.");
|
|
9462
|
+
return {
|
|
9463
|
+
ok: true,
|
|
9464
|
+
message: "Board exported.",
|
|
9465
|
+
board,
|
|
9466
|
+
markdown: exportBoardAsMarkdown(board)
|
|
9467
|
+
};
|
|
9468
|
+
}
|
|
9469
|
+
case "search_tasks": {
|
|
9470
|
+
const tasks = await searchKanban(projectRoot, {
|
|
9471
|
+
query: input.query,
|
|
9472
|
+
boardId: input.boardId,
|
|
9473
|
+
assignedAgent: input.agentId,
|
|
9474
|
+
status: input.status,
|
|
9475
|
+
priority: input.priority,
|
|
9476
|
+
label: input.labels?.[0]
|
|
9477
|
+
});
|
|
9478
|
+
return { ok: true, message: `${tasks.length} task(s) matched.`, tasks };
|
|
9479
|
+
}
|
|
9480
|
+
case "add_column": {
|
|
9481
|
+
if (!input.boardId || !input.title) return fail("add_column requires boardId and title.");
|
|
9482
|
+
const result = await addColumn(projectRoot, input.boardId, {
|
|
9483
|
+
title: input.title,
|
|
9484
|
+
...input.description !== void 0 ? { description: input.description } : {}
|
|
9485
|
+
});
|
|
9486
|
+
return result ? okBoard(result.board, "Column added.") : fail("Board not found.");
|
|
9487
|
+
}
|
|
9488
|
+
case "update_column": {
|
|
9489
|
+
if (!input.boardId || !input.columnId)
|
|
9490
|
+
return fail("update_column requires boardId and columnId.");
|
|
9491
|
+
const board = await updateColumn(projectRoot, input.boardId, input.columnId, {
|
|
9492
|
+
...input.title !== void 0 ? { title: input.title } : {},
|
|
9493
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
9494
|
+
...input.order !== void 0 ? { order: input.order } : {}
|
|
9495
|
+
});
|
|
9496
|
+
return board ? okBoard(board, "Column updated.") : fail("Column not found.");
|
|
9497
|
+
}
|
|
9498
|
+
case "delete_column": {
|
|
9499
|
+
if (!input.boardId || !input.columnId)
|
|
9500
|
+
return fail("delete_column requires boardId and columnId.");
|
|
9501
|
+
const board = await removeColumn(projectRoot, input.boardId, input.columnId, {
|
|
9502
|
+
moveTasksToColumnId: input.moveTasksToColumnId
|
|
9503
|
+
});
|
|
9504
|
+
return board ? okBoard(board, "Column deleted.") : fail("Column not found.");
|
|
9505
|
+
}
|
|
9506
|
+
case "add_task": {
|
|
9507
|
+
if (!input.boardId || !input.title) return fail("add_task requires boardId and title.");
|
|
9508
|
+
const result = await addTask(projectRoot, input.boardId, taskInput(input));
|
|
9509
|
+
return result ? okTask(result.board, result.task, "Task added.") : fail("Board not found.");
|
|
9510
|
+
}
|
|
9511
|
+
case "copy_task": {
|
|
9512
|
+
if (!input.boardId || !input.taskId || !input.targetBoardId) {
|
|
9513
|
+
return fail("copy_task requires boardId, taskId, and targetBoardId.");
|
|
9514
|
+
}
|
|
9515
|
+
const result = await copyTaskToBoard(
|
|
9516
|
+
projectRoot,
|
|
9517
|
+
input.boardId,
|
|
9518
|
+
input.taskId,
|
|
9519
|
+
input.targetBoardId,
|
|
9520
|
+
{
|
|
9521
|
+
...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
|
|
9522
|
+
...input.order !== void 0 ? { targetOrder: input.order } : {},
|
|
9523
|
+
...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
|
|
9524
|
+
...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
|
|
9525
|
+
}
|
|
9526
|
+
);
|
|
9527
|
+
return result ? okTask(result.targetBoard, result.task, "Task copied to target board.") : fail("Board or task not found.");
|
|
9528
|
+
}
|
|
9529
|
+
case "transfer_task": {
|
|
9530
|
+
if (!input.boardId || !input.taskId || !input.targetBoardId) {
|
|
9531
|
+
return fail("transfer_task requires boardId, taskId, and targetBoardId.");
|
|
9532
|
+
}
|
|
9533
|
+
const result = await transferTaskToBoard(
|
|
9534
|
+
projectRoot,
|
|
9535
|
+
input.boardId,
|
|
9536
|
+
input.taskId,
|
|
9537
|
+
input.targetBoardId,
|
|
9538
|
+
{
|
|
9539
|
+
...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
|
|
9540
|
+
...input.order !== void 0 ? { targetOrder: input.order } : {},
|
|
9541
|
+
...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
|
|
9542
|
+
...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
|
|
9543
|
+
}
|
|
9544
|
+
);
|
|
9545
|
+
return result ? okTask(result.targetBoard, result.task, "Task transferred to target board.") : fail("Board or task not found.");
|
|
9546
|
+
}
|
|
9547
|
+
case "get_task": {
|
|
9548
|
+
if (!input.boardId || !input.taskId) return fail("get_task requires boardId and taskId.");
|
|
9549
|
+
const task = await getTask(projectRoot, input.boardId, input.taskId);
|
|
9550
|
+
return task ? { ok: true, message: "Task loaded.", task } : fail("Task not found.");
|
|
9551
|
+
}
|
|
9552
|
+
case "update_task": {
|
|
9553
|
+
if (!input.boardId || !input.taskId)
|
|
9554
|
+
return fail("update_task requires boardId and taskId.");
|
|
9555
|
+
const board = await updateTask(projectRoot, input.boardId, input.taskId, taskPatch(input));
|
|
9556
|
+
return board ? okBoard(board, "Task updated.") : fail("Task not found.");
|
|
9557
|
+
}
|
|
9558
|
+
case "move_task": {
|
|
9559
|
+
if (!input.boardId || !input.taskId || !input.targetColumnId) {
|
|
9560
|
+
return fail("move_task requires boardId, taskId, and targetColumnId.");
|
|
9561
|
+
}
|
|
9562
|
+
const board = await moveTask(
|
|
9563
|
+
projectRoot,
|
|
9564
|
+
input.boardId,
|
|
9565
|
+
input.taskId,
|
|
9566
|
+
input.targetColumnId,
|
|
9567
|
+
input.order
|
|
9568
|
+
);
|
|
9569
|
+
return board ? okBoard(board, "Task moved.") : fail("Move failed.");
|
|
9570
|
+
}
|
|
9571
|
+
case "delete_task": {
|
|
9572
|
+
if (!input.boardId || !input.taskId)
|
|
9573
|
+
return fail("delete_task requires boardId and taskId.");
|
|
9574
|
+
const board = await removeTask(projectRoot, input.boardId, input.taskId);
|
|
9575
|
+
return board ? okBoard(board, "Task deleted.") : fail("Task not found.");
|
|
9576
|
+
}
|
|
9577
|
+
case "assign_task": {
|
|
9578
|
+
if (!input.boardId || !input.taskId)
|
|
9579
|
+
return fail("assign_task requires boardId and taskId.");
|
|
9580
|
+
const board = await assignTask(
|
|
9581
|
+
projectRoot,
|
|
9582
|
+
input.boardId,
|
|
9583
|
+
input.taskId,
|
|
9584
|
+
assignmentInput(input)
|
|
9585
|
+
);
|
|
9586
|
+
return board ? okBoard(board, "Task assigned.") : fail("Task not found.");
|
|
9587
|
+
}
|
|
9588
|
+
case "mark_assignment": {
|
|
9589
|
+
if (!input.boardId || !input.taskId)
|
|
9590
|
+
return fail("mark_assignment requires boardId and taskId.");
|
|
9591
|
+
const assignmentStatus = input.assignmentStatus ?? (input.status === "completed" ? "completed" : input.error ? "failed" : void 0);
|
|
9592
|
+
const board = await updateTaskAssignment(projectRoot, input.boardId, input.taskId, {
|
|
9593
|
+
...assignmentStatus !== void 0 ? { status: assignmentStatus } : {},
|
|
9594
|
+
...input.subagentId !== void 0 ? { subagentId: input.subagentId } : {},
|
|
9595
|
+
...input.runTaskId !== void 0 ? { runTaskId: input.runTaskId } : {},
|
|
9596
|
+
...input.lastResult !== void 0 ? { lastResult: input.lastResult } : {},
|
|
9597
|
+
...input.error !== void 0 ? { error: input.error } : {},
|
|
9598
|
+
...input.agentId !== void 0 ? { agentId: input.agentId } : {}
|
|
9599
|
+
});
|
|
9600
|
+
return board ? okBoard(board, "Assignment updated.") : fail("Task not found.");
|
|
9601
|
+
}
|
|
9602
|
+
case "add_dependency": {
|
|
9603
|
+
if (!input.boardId || !input.taskId || !input.dependencyTaskId) {
|
|
9604
|
+
return fail("add_dependency requires boardId, taskId, and dependencyTaskId.");
|
|
9605
|
+
}
|
|
9606
|
+
const board = await addDependency(
|
|
9607
|
+
projectRoot,
|
|
9608
|
+
input.boardId,
|
|
9609
|
+
input.taskId,
|
|
9610
|
+
input.dependencyTaskId
|
|
9611
|
+
);
|
|
9612
|
+
return board ? okBoard(board, "Dependency added.") : fail("Task not found.");
|
|
9613
|
+
}
|
|
9614
|
+
case "add_check": {
|
|
9615
|
+
if (!input.boardId || !input.taskId || !input.checkDescription) {
|
|
9616
|
+
return fail("add_check requires boardId, taskId, and checkDescription.");
|
|
9617
|
+
}
|
|
9618
|
+
const board = await addCheckToTask(projectRoot, input.boardId, input.taskId, {
|
|
9619
|
+
description: input.checkDescription,
|
|
9620
|
+
type: "manual",
|
|
9621
|
+
status: input.checkStatus
|
|
9622
|
+
});
|
|
9623
|
+
return board ? okBoard(board, "Check added.") : fail("Task not found.");
|
|
9624
|
+
}
|
|
9625
|
+
case "update_check": {
|
|
9626
|
+
if (!input.boardId || !input.taskId || !input.checkId) {
|
|
9627
|
+
return fail("update_check requires boardId, taskId, and checkId.");
|
|
9628
|
+
}
|
|
9629
|
+
const board = await updateCheckOnTask(
|
|
9630
|
+
projectRoot,
|
|
9631
|
+
input.boardId,
|
|
9632
|
+
input.taskId,
|
|
9633
|
+
input.checkId,
|
|
9634
|
+
{
|
|
9635
|
+
...input.checkDescription !== void 0 ? { description: input.checkDescription } : {},
|
|
9636
|
+
...input.checkStatus !== void 0 ? { status: input.checkStatus } : {}
|
|
9637
|
+
}
|
|
9638
|
+
);
|
|
9639
|
+
return board ? okBoard(board, "Check updated.") : fail("Check not found.");
|
|
9640
|
+
}
|
|
9641
|
+
case "add_note": {
|
|
9642
|
+
if (!input.boardId || !input.taskId || !input.note)
|
|
9643
|
+
return fail("add_note requires boardId, taskId, and note.");
|
|
9644
|
+
const board = await addNoteToTask(projectRoot, input.boardId, input.taskId, {
|
|
9645
|
+
author: input.author ?? "agent",
|
|
9646
|
+
content: input.note
|
|
9647
|
+
});
|
|
9648
|
+
return board ? okBoard(board, "Note added.") : fail("Task not found.");
|
|
9649
|
+
}
|
|
9650
|
+
case "add_link": {
|
|
9651
|
+
if (!input.boardId || !input.taskId || !input.url)
|
|
9652
|
+
return fail("add_link requires boardId, taskId, and url.");
|
|
9653
|
+
const board = await addLinkToTask(projectRoot, input.boardId, input.taskId, {
|
|
9654
|
+
url: input.url,
|
|
9655
|
+
type: input.linkType ?? "url",
|
|
9656
|
+
...input.linkTitle !== void 0 ? { title: input.linkTitle } : {}
|
|
9657
|
+
});
|
|
9658
|
+
return board ? okBoard(board, "Link added.") : fail("Task not found.");
|
|
9659
|
+
}
|
|
9660
|
+
default:
|
|
9661
|
+
return fail(`Unknown kanban action: ${input.action}`);
|
|
9662
|
+
}
|
|
9663
|
+
}
|
|
9664
|
+
};
|
|
9665
|
+
function fail(message) {
|
|
9666
|
+
return { ok: false, message };
|
|
9667
|
+
}
|
|
9668
|
+
function okBoard(board, message = "Board loaded.") {
|
|
9669
|
+
return { ok: true, message, board };
|
|
9670
|
+
}
|
|
9671
|
+
function okTask(board, task, message) {
|
|
9672
|
+
return { ok: true, message, board, task };
|
|
9673
|
+
}
|
|
9674
|
+
async function requireBoard(projectRoot, boardId) {
|
|
9675
|
+
return boardId ? getBoard(projectRoot, boardId) : null;
|
|
9676
|
+
}
|
|
9677
|
+
function taskInput(input) {
|
|
9678
|
+
return {
|
|
9679
|
+
title: input.title ?? "",
|
|
9680
|
+
columnId: input.columnId,
|
|
9681
|
+
description: input.description,
|
|
9682
|
+
priority: input.priority,
|
|
9683
|
+
status: input.status,
|
|
9684
|
+
labels: input.labels,
|
|
9685
|
+
assignedAgent: input.agentId,
|
|
9686
|
+
...input.agentId || input.provider || input.model ? { assignment: assignmentForTaskCreate(input) } : {}
|
|
9687
|
+
};
|
|
9688
|
+
}
|
|
9689
|
+
function taskPatch(input) {
|
|
9690
|
+
return {
|
|
9691
|
+
title: input.title,
|
|
9692
|
+
description: input.description,
|
|
9693
|
+
columnId: input.columnId,
|
|
9694
|
+
order: input.order,
|
|
9695
|
+
priority: input.priority,
|
|
9696
|
+
status: input.status,
|
|
9697
|
+
labels: input.labels,
|
|
9698
|
+
assignedAgent: input.agentId
|
|
9699
|
+
};
|
|
9700
|
+
}
|
|
9701
|
+
function assignmentInput(input) {
|
|
9702
|
+
return {
|
|
9703
|
+
agentId: input.agentId,
|
|
9704
|
+
name: input.name,
|
|
9705
|
+
role: input.role,
|
|
9706
|
+
provider: input.provider,
|
|
9707
|
+
model: input.model,
|
|
9708
|
+
fallbackProfile: input.fallbackProfile,
|
|
9709
|
+
fallbackModels: input.fallbackModels,
|
|
9710
|
+
tools: input.tools,
|
|
9711
|
+
allowedCapabilities: input.allowedCapabilities,
|
|
9712
|
+
assignee: input.assignee
|
|
9713
|
+
};
|
|
9714
|
+
}
|
|
9715
|
+
function assignmentForTaskCreate(input) {
|
|
9716
|
+
return {
|
|
9717
|
+
status: input.assignmentStatus ?? "assigned",
|
|
9718
|
+
...input.agentId !== void 0 ? { agentId: input.agentId } : {},
|
|
9719
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
9720
|
+
...input.role !== void 0 ? { role: input.role } : {},
|
|
9721
|
+
...input.provider !== void 0 ? { provider: input.provider } : {},
|
|
9722
|
+
...input.model !== void 0 ? { model: input.model } : {},
|
|
9723
|
+
...input.fallbackProfile !== void 0 ? { fallbackProfile: input.fallbackProfile } : {},
|
|
9724
|
+
...input.fallbackModels !== void 0 ? { fallbackModels: input.fallbackModels } : {},
|
|
9725
|
+
...input.tools !== void 0 ? { tools: input.tools } : {},
|
|
9726
|
+
...input.allowedCapabilities !== void 0 ? { allowedCapabilities: input.allowedCapabilities } : {}
|
|
9727
|
+
};
|
|
9728
|
+
}
|
|
9209
9729
|
|
|
9210
9730
|
// src/lint.ts
|
|
9211
9731
|
var lintTool = {
|
|
@@ -12229,56 +12749,75 @@ var writeTool = {
|
|
|
12229
12749
|
required: ["path", "content"]
|
|
12230
12750
|
},
|
|
12231
12751
|
async execute(input, ctx) {
|
|
12232
|
-
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
message: "write: content is required",
|
|
12241
|
-
field: "content"
|
|
12242
|
-
});
|
|
12243
|
-
}
|
|
12244
|
-
const absPath = await safeResolveReal(input.path, ctx);
|
|
12245
|
-
let existed = false;
|
|
12246
|
-
let prev = "";
|
|
12247
|
-
try {
|
|
12248
|
-
const stat12 = await fs2.stat(absPath);
|
|
12249
|
-
existed = stat12.isFile();
|
|
12250
|
-
if (existed) {
|
|
12251
|
-
if (!ctx.hasRead(absPath)) {
|
|
12252
|
-
prev = await fs2.readFile(absPath, "utf8");
|
|
12253
|
-
ctx.recordRead(absPath, stat12.mtimeMs, "write");
|
|
12254
|
-
} else {
|
|
12255
|
-
prev = await fs2.readFile(absPath, "utf8");
|
|
12256
|
-
}
|
|
12257
|
-
}
|
|
12258
|
-
} catch (err) {
|
|
12259
|
-
if (err.code !== "ENOENT") {
|
|
12260
|
-
throw err;
|
|
12752
|
+
return writeFile7(input, ctx);
|
|
12753
|
+
},
|
|
12754
|
+
async *executeStream(input, ctx) {
|
|
12755
|
+
const prepared = await prepareWrite(input, ctx);
|
|
12756
|
+
if (!prepared.existed) {
|
|
12757
|
+
for (const line of input.content.split("\n")) {
|
|
12758
|
+
yield { type: "partial_output", text: `${line}
|
|
12759
|
+
`, data: { livePreview: true } };
|
|
12261
12760
|
}
|
|
12262
12761
|
}
|
|
12263
|
-
await
|
|
12264
|
-
const diff = existed ? unifiedDiff(prev, input.content, { fromFile: input.path, toFile: input.path }) : `+++ ${input.path}
|
|
12265
|
-
+ (new file, ${input.content.split("\n").length} lines)`;
|
|
12266
|
-
const stat11 = await fs2.stat(absPath);
|
|
12267
|
-
ctx.recordRead(absPath, stat11.mtimeMs, "write");
|
|
12268
|
-
ctx.session.recordFileChange({
|
|
12269
|
-
path: absPath,
|
|
12270
|
-
action: existed ? "modified" : "created",
|
|
12271
|
-
before: existed ? prev : null,
|
|
12272
|
-
after: input.content
|
|
12273
|
-
});
|
|
12274
|
-
return {
|
|
12275
|
-
path: absPath,
|
|
12276
|
-
bytes_written: Buffer.byteLength(input.content, "utf8"),
|
|
12277
|
-
created: !existed,
|
|
12278
|
-
diff
|
|
12279
|
-
};
|
|
12762
|
+
yield { type: "final", output: await finishWrite(input, ctx, prepared) };
|
|
12280
12763
|
}
|
|
12281
12764
|
};
|
|
12765
|
+
async function writeFile7(input, ctx) {
|
|
12766
|
+
return finishWrite(input, ctx, await prepareWrite(input, ctx));
|
|
12767
|
+
}
|
|
12768
|
+
async function prepareWrite(input, ctx) {
|
|
12769
|
+
if (!input?.path) {
|
|
12770
|
+
throw new ToolValidationError({
|
|
12771
|
+
message: "write: path is required",
|
|
12772
|
+
field: "path"
|
|
12773
|
+
});
|
|
12774
|
+
}
|
|
12775
|
+
if (input.content === void 0) {
|
|
12776
|
+
throw new ToolValidationError({
|
|
12777
|
+
message: "write: content is required",
|
|
12778
|
+
field: "content"
|
|
12779
|
+
});
|
|
12780
|
+
}
|
|
12781
|
+
const absPath = await safeResolveReal(input.path, ctx);
|
|
12782
|
+
let existed = false;
|
|
12783
|
+
let prev = "";
|
|
12784
|
+
try {
|
|
12785
|
+
const stat11 = await fs2.stat(absPath);
|
|
12786
|
+
existed = stat11.isFile();
|
|
12787
|
+
if (existed) {
|
|
12788
|
+
if (!ctx.hasRead(absPath)) {
|
|
12789
|
+
prev = await fs2.readFile(absPath, "utf8");
|
|
12790
|
+
ctx.recordRead(absPath, stat11.mtimeMs, "write");
|
|
12791
|
+
} else {
|
|
12792
|
+
prev = await fs2.readFile(absPath, "utf8");
|
|
12793
|
+
}
|
|
12794
|
+
}
|
|
12795
|
+
} catch (err) {
|
|
12796
|
+
if (err.code !== "ENOENT") {
|
|
12797
|
+
throw err;
|
|
12798
|
+
}
|
|
12799
|
+
}
|
|
12800
|
+
return { absPath, existed, prev };
|
|
12801
|
+
}
|
|
12802
|
+
async function finishWrite(input, ctx, prepared) {
|
|
12803
|
+
await atomicWrite(prepared.absPath, input.content);
|
|
12804
|
+
const diff = prepared.existed ? unifiedDiff(prepared.prev, input.content, { fromFile: input.path, toFile: input.path }) : `+++ ${input.path}
|
|
12805
|
+
+ (new file, ${input.content.split("\n").length} lines)`;
|
|
12806
|
+
const stat11 = await fs2.stat(prepared.absPath);
|
|
12807
|
+
ctx.recordRead(prepared.absPath, stat11.mtimeMs, "write");
|
|
12808
|
+
ctx.session.recordFileChange({
|
|
12809
|
+
path: prepared.absPath,
|
|
12810
|
+
action: prepared.existed ? "modified" : "created",
|
|
12811
|
+
before: prepared.existed ? prepared.prev : null,
|
|
12812
|
+
after: input.content
|
|
12813
|
+
});
|
|
12814
|
+
return {
|
|
12815
|
+
path: prepared.absPath,
|
|
12816
|
+
bytes_written: Buffer.byteLength(input.content, "utf8"),
|
|
12817
|
+
created: !prepared.existed,
|
|
12818
|
+
diff
|
|
12819
|
+
};
|
|
12820
|
+
}
|
|
12282
12821
|
|
|
12283
12822
|
// src/builtin.ts
|
|
12284
12823
|
var builtinTools = [
|
|
@@ -12294,6 +12833,7 @@ var builtinTools = [
|
|
|
12294
12833
|
searchTool,
|
|
12295
12834
|
todoTool,
|
|
12296
12835
|
planTool,
|
|
12836
|
+
kanbanTool,
|
|
12297
12837
|
taskTool,
|
|
12298
12838
|
gitTool,
|
|
12299
12839
|
patchTool,
|