@slock-ai/daemon 0.46.0 → 0.46.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat-bridge.js +5 -5
- package/dist/{chunk-Q4XUZB34.js → chunk-XW57NR6Y.js} +202 -30
- package/dist/cli/index.js +2 -2
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/chat-bridge.js
CHANGED
|
@@ -34,7 +34,7 @@ var searchMessagesDeprecatedSchema = {
|
|
|
34
34
|
};
|
|
35
35
|
var listTasksDeprecatedSchema = {
|
|
36
36
|
channel: z.string().describe("Deprecated channel argument."),
|
|
37
|
-
status: z.enum(["all", "todo", "in_progress", "in_review", "done"]).optional().describe("Deprecated status argument.")
|
|
37
|
+
status: z.enum(["all", "todo", "in_progress", "in_review", "done", "closed"]).optional().describe("Deprecated status argument.")
|
|
38
38
|
};
|
|
39
39
|
var claimTasksDeprecatedSchema = {
|
|
40
40
|
channel: z.string().describe("Deprecated channel argument."),
|
|
@@ -48,7 +48,7 @@ var unclaimTaskDeprecatedSchema = {
|
|
|
48
48
|
var updateTaskStatusDeprecatedSchema = {
|
|
49
49
|
channel: z.string().describe("Deprecated channel argument."),
|
|
50
50
|
task_number: z.number().describe("Deprecated task number."),
|
|
51
|
-
status: z.enum(["todo", "in_progress", "in_review", "done"]).describe("Deprecated status argument.")
|
|
51
|
+
status: z.enum(["todo", "in_progress", "in_review", "done", "closed"]).describe("Deprecated status argument.")
|
|
52
52
|
};
|
|
53
53
|
var DEPRECATED_MCP_TOOL_DEFINITIONS = [
|
|
54
54
|
{
|
|
@@ -1087,7 +1087,7 @@ ${formatted}${footer}`
|
|
|
1087
1087
|
"List all tasks in a channel. Returns each task's number, title, status, assignee, and message ID. Use this to see what work exists before claiming. Tasks marked as legacy are from an older system and cannot be claimed or modified.",
|
|
1088
1088
|
{
|
|
1089
1089
|
channel: z2.string().describe("The channel whose task board to view \u2014 e.g. '#engineering', '#proj-slock'"),
|
|
1090
|
-
status: z2.enum(["all", "todo", "in_progress", "in_review", "done"]).default("all").describe("Filter by status (default: all)")
|
|
1090
|
+
status: z2.enum(["all", "todo", "in_progress", "in_review", "done", "closed"]).default("all").describe("Filter by status (default: all)")
|
|
1091
1091
|
},
|
|
1092
1092
|
async ({ channel, status }) => {
|
|
1093
1093
|
try {
|
|
@@ -1311,11 +1311,11 @@ ${lines.join("\n")}${threadHint}`
|
|
|
1311
1311
|
);
|
|
1312
1312
|
server.tool(
|
|
1313
1313
|
"update_task_status",
|
|
1314
|
-
"Update a task's progress status. You must be the task's assignee to update it. Use in_review when your work is ready for human validation. Only set done for trivial tasks or after explicit approval. Valid transitions: todo\
|
|
1314
|
+
"Update a task's progress status. You must be the task's assignee to update it. Use in_review when your work is ready for human validation. Only set done for trivial tasks or after explicit approval. Use closed to mark a task as won't-do (cancelled / abandoned / out-of-scope) \u2014 distinct from done. Valid transitions: todo\u2192{in_progress,closed}, in_progress\u2192{in_review,done,closed}, in_review\u2192{done,in_progress,closed}, done\u2192{todo,in_progress,in_review,closed}, closed\u2192todo (reopen).",
|
|
1315
1315
|
{
|
|
1316
1316
|
channel: z2.string().describe("The channel \u2014 e.g. '#engineering'"),
|
|
1317
1317
|
task_number: z2.number().describe("The task number to update (e.g. 3)"),
|
|
1318
|
-
status: z2.enum(["todo", "in_progress", "in_review", "done"]).describe("The new status")
|
|
1318
|
+
status: z2.enum(["todo", "in_progress", "in_review", "done", "closed"]).describe("The new status")
|
|
1319
1319
|
},
|
|
1320
1320
|
async ({ channel, task_number, status }) => {
|
|
1321
1321
|
try {
|
|
@@ -2558,8 +2558,8 @@ function runCursorModelsCommand() {
|
|
|
2558
2558
|
}
|
|
2559
2559
|
|
|
2560
2560
|
// src/drivers/gemini.ts
|
|
2561
|
-
import { spawn as spawn5 } from "child_process";
|
|
2562
|
-
import {
|
|
2561
|
+
import { execFileSync as execFileSync2, spawn as spawn5 } from "child_process";
|
|
2562
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
2563
2563
|
import path7 from "path";
|
|
2564
2564
|
function buildGeminiSpawnEnv(ctx, platform = process.platform) {
|
|
2565
2565
|
const { spawnEnv } = prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
|
|
@@ -2568,6 +2568,71 @@ function buildGeminiSpawnEnv(ctx, platform = process.platform) {
|
|
|
2568
2568
|
}
|
|
2569
2569
|
return spawnEnv;
|
|
2570
2570
|
}
|
|
2571
|
+
function normalizeExecOutput2(raw) {
|
|
2572
|
+
return Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw ?? "");
|
|
2573
|
+
}
|
|
2574
|
+
function buildGeminiArgs(config) {
|
|
2575
|
+
const args = [
|
|
2576
|
+
"--output-format",
|
|
2577
|
+
"stream-json",
|
|
2578
|
+
"--yolo",
|
|
2579
|
+
// Gemini CLI headless mode is selected by -p/--prompt. Keep the actual
|
|
2580
|
+
// prompt off argv and feed it through stdin below; this avoids Windows
|
|
2581
|
+
// cmd.exe's 8191-character command-line limit and keeps long wake payloads
|
|
2582
|
+
// below CreateProcess argv pressure too.
|
|
2583
|
+
"-p",
|
|
2584
|
+
""
|
|
2585
|
+
];
|
|
2586
|
+
if (config.model && config.model !== "default") {
|
|
2587
|
+
args.push("--model", config.model);
|
|
2588
|
+
}
|
|
2589
|
+
if (config.sessionId) {
|
|
2590
|
+
args.push("--resume", config.sessionId);
|
|
2591
|
+
}
|
|
2592
|
+
return args;
|
|
2593
|
+
}
|
|
2594
|
+
function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
2595
|
+
const platform = deps.platform ?? process.platform;
|
|
2596
|
+
if (platform !== "win32") {
|
|
2597
|
+
return { command: resolveCommandOnPath("gemini", deps) ?? "gemini", args: commandArgs };
|
|
2598
|
+
}
|
|
2599
|
+
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync2;
|
|
2600
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
2601
|
+
const env = deps.env ?? process.env;
|
|
2602
|
+
const winPath = path7.win32;
|
|
2603
|
+
let geminiEntry = null;
|
|
2604
|
+
try {
|
|
2605
|
+
const globalRoot = normalizeExecOutput2(execFileSyncFn("npm", ["root", "-g"], {
|
|
2606
|
+
encoding: "utf8",
|
|
2607
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2608
|
+
env
|
|
2609
|
+
})).trim();
|
|
2610
|
+
const candidate = winPath.join(globalRoot, "@google", "gemini-cli", "bundle", "gemini.js");
|
|
2611
|
+
if (existsSyncFn(candidate)) geminiEntry = candidate;
|
|
2612
|
+
} catch {
|
|
2613
|
+
}
|
|
2614
|
+
if (!geminiEntry) {
|
|
2615
|
+
try {
|
|
2616
|
+
const cmdPath = normalizeExecOutput2(execFileSyncFn("where.exe", ["gemini"], {
|
|
2617
|
+
encoding: "utf8",
|
|
2618
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2619
|
+
env
|
|
2620
|
+
})).trim().split(/\r?\n/)[0];
|
|
2621
|
+
const candidate = winPath.join(winPath.dirname(cmdPath), "node_modules", "@google", "gemini-cli", "bundle", "gemini.js");
|
|
2622
|
+
if (existsSyncFn(candidate)) geminiEntry = candidate;
|
|
2623
|
+
} catch {
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
if (!geminiEntry) {
|
|
2627
|
+
throw new Error(
|
|
2628
|
+
"Cannot resolve Gemini CLI entry point on Windows. Ensure @google/gemini-cli is installed globally via npm (npm i -g @google/gemini-cli)."
|
|
2629
|
+
);
|
|
2630
|
+
}
|
|
2631
|
+
return {
|
|
2632
|
+
command: process.execPath,
|
|
2633
|
+
args: [geminiEntry, ...commandArgs]
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2571
2636
|
var GeminiDriver = class {
|
|
2572
2637
|
id = "gemini";
|
|
2573
2638
|
lifecycle = {
|
|
@@ -2597,26 +2662,15 @@ var GeminiDriver = class {
|
|
|
2597
2662
|
this.sessionId = ctx.config.sessionId || null;
|
|
2598
2663
|
this.sessionAnnounced = false;
|
|
2599
2664
|
this.writeGeminiSettings(ctx);
|
|
2600
|
-
const args =
|
|
2601
|
-
"--output-format",
|
|
2602
|
-
"stream-json",
|
|
2603
|
-
"--yolo",
|
|
2604
|
-
"-p",
|
|
2605
|
-
ctx.prompt
|
|
2606
|
-
];
|
|
2607
|
-
if (ctx.config.model && ctx.config.model !== "default") {
|
|
2608
|
-
args.push("--model", ctx.config.model);
|
|
2609
|
-
}
|
|
2610
|
-
if (ctx.config.sessionId) {
|
|
2611
|
-
args.push("--resume", ctx.config.sessionId);
|
|
2612
|
-
}
|
|
2665
|
+
const { command, args } = resolveGeminiSpawn(buildGeminiArgs(ctx.config));
|
|
2613
2666
|
const spawnEnv = buildGeminiSpawnEnv(ctx);
|
|
2614
|
-
const proc = spawn5(
|
|
2667
|
+
const proc = spawn5(command, args, {
|
|
2615
2668
|
cwd: ctx.workingDirectory,
|
|
2616
2669
|
stdio: ["pipe", "pipe", "pipe"],
|
|
2617
2670
|
env: spawnEnv,
|
|
2618
|
-
shell:
|
|
2671
|
+
shell: false
|
|
2619
2672
|
});
|
|
2673
|
+
proc.stdin?.end(ctx.prompt);
|
|
2620
2674
|
return { process: proc };
|
|
2621
2675
|
}
|
|
2622
2676
|
parseLine(line) {
|
|
@@ -2718,7 +2772,7 @@ var GeminiDriver = class {
|
|
|
2718
2772
|
// src/drivers/kimi.ts
|
|
2719
2773
|
import { randomUUID } from "crypto";
|
|
2720
2774
|
import { spawn as spawn6 } from "child_process";
|
|
2721
|
-
import { existsSync as
|
|
2775
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
2722
2776
|
import os3 from "os";
|
|
2723
2777
|
import path8 from "path";
|
|
2724
2778
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
@@ -2783,7 +2837,7 @@ var KimiDriver = class {
|
|
|
2783
2837
|
const systemPromptPath = path8.join(ctx.workingDirectory, KIMI_SYSTEM_PROMPT_FILE);
|
|
2784
2838
|
const agentFilePath = path8.join(ctx.workingDirectory, KIMI_AGENT_FILE);
|
|
2785
2839
|
const mcpConfigPath = path8.join(ctx.workingDirectory, KIMI_MCP_FILE);
|
|
2786
|
-
if (!isResume || !
|
|
2840
|
+
if (!isResume || !existsSync6(systemPromptPath)) {
|
|
2787
2841
|
writeFileSync6(systemPromptPath, ctx.prompt, "utf8");
|
|
2788
2842
|
}
|
|
2789
2843
|
writeFileSync6(agentFilePath, [
|
|
@@ -2972,6 +3026,14 @@ var SLOCK_AGENT_NAME = "slock";
|
|
|
2972
3026
|
var NO_MESSAGE_PROMPT = "No new messages are pending. Stop now.";
|
|
2973
3027
|
var FIRST_MESSAGE_TASK_PREFIX = "First message task (system-triggered):";
|
|
2974
3028
|
var MIN_SUPPORTED_OPENCODE_VERSION = "1.14.30";
|
|
3029
|
+
var OPENCODE_PROVIDER_LABELS = {
|
|
3030
|
+
opencode: "OpenCode",
|
|
3031
|
+
"opencode-go": "OpenCode Go",
|
|
3032
|
+
openai: "OpenAI",
|
|
3033
|
+
openrouter: "OpenRouter",
|
|
3034
|
+
deepseek: "DeepSeek",
|
|
3035
|
+
fusecode: "FuseCode"
|
|
3036
|
+
};
|
|
2975
3037
|
function buildChatBridgeCommand(ctx) {
|
|
2976
3038
|
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
2977
3039
|
return [
|
|
@@ -3118,12 +3180,62 @@ function parseOpenCodeModelsOutput(output) {
|
|
|
3118
3180
|
seen.add(line);
|
|
3119
3181
|
models.push({
|
|
3120
3182
|
id: line,
|
|
3121
|
-
label: line,
|
|
3183
|
+
label: formatOpenCodeModelLabel(line),
|
|
3122
3184
|
verified: "launchable"
|
|
3123
3185
|
});
|
|
3124
3186
|
}
|
|
3125
3187
|
return models.length > 0 ? { models } : null;
|
|
3126
3188
|
}
|
|
3189
|
+
function formatOpenCodeModelLabel(modelId) {
|
|
3190
|
+
const separatorIndex = modelId.indexOf("/");
|
|
3191
|
+
if (separatorIndex <= 0 || separatorIndex === modelId.length - 1) return modelId;
|
|
3192
|
+
const providerId = modelId.slice(0, separatorIndex);
|
|
3193
|
+
const modelName = modelId.slice(separatorIndex + 1);
|
|
3194
|
+
const providerLabel = OPENCODE_PROVIDER_LABELS[providerId] || humanizeOpenCodeSegment(providerId);
|
|
3195
|
+
const modelParts = modelName.split("/");
|
|
3196
|
+
const modelLabel = humanizeOpenCodeSegment(modelParts[modelParts.length - 1] || modelName);
|
|
3197
|
+
if (modelParts.length === 1) return `${modelLabel} \xB7 ${providerLabel}`;
|
|
3198
|
+
const upstreamLabel = modelParts.slice(0, -1).map(humanizeOpenCodeSegment).join(" / ");
|
|
3199
|
+
return `${modelLabel} \xB7 ${upstreamLabel} via ${providerLabel}`;
|
|
3200
|
+
}
|
|
3201
|
+
function humanizeOpenCodeSegment(value) {
|
|
3202
|
+
return value.replace(/\[(\d+)m\]/gi, "-$1m").split(/[-_]/).filter(Boolean).map(formatOpenCodeLabelToken).join(" ");
|
|
3203
|
+
}
|
|
3204
|
+
function formatOpenCodeLabelToken(token) {
|
|
3205
|
+
const normalized = token.toLowerCase();
|
|
3206
|
+
const specialCases = {
|
|
3207
|
+
ai: "AI",
|
|
3208
|
+
api: "API",
|
|
3209
|
+
b: "B",
|
|
3210
|
+
chatgpt: "ChatGPT",
|
|
3211
|
+
claude: "Claude",
|
|
3212
|
+
codestral: "Codestral",
|
|
3213
|
+
deepseek: "DeepSeek",
|
|
3214
|
+
flash: "Flash",
|
|
3215
|
+
free: "Free",
|
|
3216
|
+
gemini: "Gemini",
|
|
3217
|
+
glm: "GLM",
|
|
3218
|
+
gpt: "GPT",
|
|
3219
|
+
hy3: "HY3",
|
|
3220
|
+
kimi: "Kimi",
|
|
3221
|
+
m: "M",
|
|
3222
|
+
minimax: "MiniMax",
|
|
3223
|
+
nano: "Nano",
|
|
3224
|
+
nemotron: "Nemotron",
|
|
3225
|
+
omni: "Omni",
|
|
3226
|
+
opus: "Opus",
|
|
3227
|
+
pro: "Pro",
|
|
3228
|
+
sonnet: "Sonnet",
|
|
3229
|
+
super: "Super"
|
|
3230
|
+
};
|
|
3231
|
+
if (specialCases[normalized]) return specialCases[normalized];
|
|
3232
|
+
if (/^v\d+(\.\d+)?$/.test(normalized)) return normalized.toUpperCase();
|
|
3233
|
+
if (/^\d+m$/i.test(token)) return token.toUpperCase();
|
|
3234
|
+
if (/^\d+[bk]$/i.test(token)) return token.toUpperCase();
|
|
3235
|
+
if (/^m\d+(\.\d+)?$/i.test(token)) return token.toUpperCase();
|
|
3236
|
+
if (/^\d/.test(token)) return token;
|
|
3237
|
+
return normalized.charAt(0).toUpperCase() + normalized.slice(1);
|
|
3238
|
+
}
|
|
3127
3239
|
function detectOpenCodeModels(home = os4.homedir(), runCommand = runOpenCodeModelsCommand) {
|
|
3128
3240
|
const commandResult = runCommand(home);
|
|
3129
3241
|
if (commandResult.error || commandResult.status !== 0) return null;
|
|
@@ -4183,6 +4295,66 @@ function isMissingResumeSession(ap) {
|
|
|
4183
4295
|
}
|
|
4184
4296
|
return false;
|
|
4185
4297
|
}
|
|
4298
|
+
function classifyActivityDetailForTrace(detail) {
|
|
4299
|
+
if (!detail) return void 0;
|
|
4300
|
+
if (detail === "Message received") return "message_received";
|
|
4301
|
+
if (detail === "Starting\u2026") return "starting";
|
|
4302
|
+
if (detail === "Running command\u2026") return "running_command";
|
|
4303
|
+
if (detail === "Checking messages\u2026") return "checking_messages";
|
|
4304
|
+
if (detail === "Compacting context") return "compacting_context";
|
|
4305
|
+
if (detail === "Context compaction finished") return "compaction_finished";
|
|
4306
|
+
if (detail === "Context compaction still running; no finish event observed") return "compaction_stale";
|
|
4307
|
+
if (detail === "Idle" || detail === "Process idle") return "idle";
|
|
4308
|
+
if (detail.startsWith("Restarting stalled ") && detail.endsWith(" runtime for queued message")) return "stalled_recovery";
|
|
4309
|
+
if (detail.startsWith("Runtime stalled: no runtime events for ")) return "runtime_stalled";
|
|
4310
|
+
return "other";
|
|
4311
|
+
}
|
|
4312
|
+
function buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes) {
|
|
4313
|
+
const context = [];
|
|
4314
|
+
if (ap.lastActivityDetail) {
|
|
4315
|
+
context.push(`after ${ap.lastActivityDetail}`);
|
|
4316
|
+
}
|
|
4317
|
+
if (ap.driver.busyDeliveryMode === "gated") {
|
|
4318
|
+
context.push(`phase=${ap.gatedSteering.phase}`);
|
|
4319
|
+
}
|
|
4320
|
+
if (ap.gatedSteering.outstandingToolUses > 0) {
|
|
4321
|
+
context.push(`tools=${ap.gatedSteering.outstandingToolUses}`);
|
|
4322
|
+
}
|
|
4323
|
+
if (ap.gatedSteering.compacting) {
|
|
4324
|
+
context.push("compacting");
|
|
4325
|
+
}
|
|
4326
|
+
if (ap.inbox.length > 0) {
|
|
4327
|
+
context.push(`queued=${ap.inbox.length}`);
|
|
4328
|
+
}
|
|
4329
|
+
const detail = [
|
|
4330
|
+
`Runtime stalled: no runtime events for ${staleForMinutes}m`,
|
|
4331
|
+
context.length > 0 ? ` (${context.join(", ")})` : ""
|
|
4332
|
+
].join("");
|
|
4333
|
+
return {
|
|
4334
|
+
detail,
|
|
4335
|
+
traceAttrs: {
|
|
4336
|
+
ageMs: staleForMs,
|
|
4337
|
+
staleForMinutes,
|
|
4338
|
+
lastActivity: ap.lastActivity,
|
|
4339
|
+
lastActivityDetailPresent: Boolean(ap.lastActivityDetail),
|
|
4340
|
+
lastActivityDetailKind: classifyActivityDetailForTrace(ap.lastActivityDetail),
|
|
4341
|
+
runtime: ap.config.runtime,
|
|
4342
|
+
model: ap.config.model,
|
|
4343
|
+
launchId: ap.launchId || void 0,
|
|
4344
|
+
sessionIdPresent: Boolean(ap.sessionId),
|
|
4345
|
+
inboxCount: ap.inbox.length,
|
|
4346
|
+
pendingNotificationCount: ap.pendingNotificationCount,
|
|
4347
|
+
processPidPresent: typeof ap.process.pid === "number",
|
|
4348
|
+
busyDeliveryMode: ap.driver.busyDeliveryMode,
|
|
4349
|
+
supportsStdinNotification: ap.driver.supportsStdinNotification,
|
|
4350
|
+
gatedPhase: ap.driver.busyDeliveryMode === "gated" ? ap.gatedSteering.phase : void 0,
|
|
4351
|
+
outstandingToolUses: ap.gatedSteering.outstandingToolUses,
|
|
4352
|
+
compacting: ap.gatedSteering.compacting,
|
|
4353
|
+
recentStderrCount: ap.recentStderr.length,
|
|
4354
|
+
recentStdoutCount: ap.recentStdout.length
|
|
4355
|
+
}
|
|
4356
|
+
};
|
|
4357
|
+
}
|
|
4186
4358
|
function getMessageDeliveryText(driver) {
|
|
4187
4359
|
return driver.supportsStdinNotification ? "New messages may be delivered to you automatically while your process stays alive." : "The daemon will automatically restart you when new messages arrive.";
|
|
4188
4360
|
}
|
|
@@ -5855,17 +6027,16 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
5855
6027
|
if (staleForMs < RUNTIME_PROGRESS_STALE_MS) return false;
|
|
5856
6028
|
ap.runtimeProgressStaleSince = Date.now();
|
|
5857
6029
|
const staleForMinutes = Math.max(1, Math.floor(staleForMs / 6e4));
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
staleForMinutes,
|
|
5861
|
-
lastActivity: ap.lastActivity
|
|
5862
|
-
});
|
|
6030
|
+
const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes);
|
|
6031
|
+
this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.stalled", diagnostic.traceAttrs);
|
|
5863
6032
|
this.endRuntimeTrace(ap, "error", {
|
|
5864
6033
|
outcome: "runtime-stalled",
|
|
5865
6034
|
ageMs: staleForMs,
|
|
5866
|
-
lastActivity: ap.lastActivity
|
|
6035
|
+
lastActivity: ap.lastActivity,
|
|
6036
|
+
lastActivityDetailPresent: Boolean(ap.lastActivityDetail),
|
|
6037
|
+
lastActivityDetailKind: classifyActivityDetailForTrace(ap.lastActivityDetail)
|
|
5867
6038
|
});
|
|
5868
|
-
this.broadcastActivity(agentId, "error",
|
|
6039
|
+
this.broadcastActivity(agentId, "error", diagnostic.detail);
|
|
5869
6040
|
return true;
|
|
5870
6041
|
}
|
|
5871
6042
|
recoverStaleProcessForQueuedMessageIfNeeded(agentId, ap) {
|
|
@@ -5881,10 +6052,9 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
5881
6052
|
if (staleForMs < RUNTIME_PROGRESS_STALE_MS && !ap.runtimeProgressStaleSince) return false;
|
|
5882
6053
|
const staleForMinutes = Math.max(1, Math.floor(staleForMs / 6e4));
|
|
5883
6054
|
ap.runtimeProgressStaleSince ??= Date.now();
|
|
6055
|
+
const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes);
|
|
5884
6056
|
this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.stalled", {
|
|
5885
|
-
|
|
5886
|
-
staleForMinutes,
|
|
5887
|
-
lastActivity: ap.lastActivity,
|
|
6057
|
+
...diagnostic.traceAttrs,
|
|
5888
6058
|
pendingMessages: ap.inbox.length,
|
|
5889
6059
|
recovery: "terminate_for_queued_message"
|
|
5890
6060
|
});
|
|
@@ -5892,6 +6062,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
5892
6062
|
outcome: "runtime-stalled",
|
|
5893
6063
|
ageMs: staleForMs,
|
|
5894
6064
|
lastActivity: ap.lastActivity,
|
|
6065
|
+
lastActivityDetailPresent: Boolean(ap.lastActivityDetail),
|
|
6066
|
+
lastActivityDetailKind: classifyActivityDetailForTrace(ap.lastActivityDetail),
|
|
5895
6067
|
pendingMessages: ap.inbox.length,
|
|
5896
6068
|
recovery: "terminate_for_queued_message"
|
|
5897
6069
|
});
|
package/dist/cli/index.js
CHANGED
|
@@ -1119,7 +1119,7 @@ function formatTaskStatusUpdated(taskNumber, status) {
|
|
|
1119
1119
|
}
|
|
1120
1120
|
|
|
1121
1121
|
// src/commands/task/list.ts
|
|
1122
|
-
var VALID_STATUSES = /* @__PURE__ */ new Set(["all", "todo", "in_progress", "in_review", "done"]);
|
|
1122
|
+
var VALID_STATUSES = /* @__PURE__ */ new Set(["all", "todo", "in_progress", "in_review", "done", "closed"]);
|
|
1123
1123
|
function registerTaskListCommand(parent) {
|
|
1124
1124
|
parent.command("list").description("List tasks in a channel").requiredOption("--channel <target>", "Channel target: '#channel'").option("--status <s>", "Filter: all|todo|in_progress|in_review|done (default: server-side)").action(async (opts) => {
|
|
1125
1125
|
let ctx;
|
|
@@ -1253,7 +1253,7 @@ function registerTaskUnclaimCommand(parent) {
|
|
|
1253
1253
|
}
|
|
1254
1254
|
|
|
1255
1255
|
// src/commands/task/update.ts
|
|
1256
|
-
var STATUSES = ["todo", "in_progress", "in_review", "done"];
|
|
1256
|
+
var STATUSES = ["todo", "in_progress", "in_review", "done", "closed"];
|
|
1257
1257
|
function registerTaskUpdateCommand(parent) {
|
|
1258
1258
|
parent.command("update").description("Update task status").requiredOption("--channel <target>", "Channel target: '#channel'").requiredOption("--number <n>", "Task number to update").requiredOption(
|
|
1259
1259
|
"--status <status>",
|
package/dist/core.js
CHANGED
package/dist/index.js
CHANGED