@askexenow/exe-os 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -79
- package/dist/bin/backfill-responses.js +160 -8
- package/dist/bin/backfill-vectors.js +130 -1
- package/dist/bin/cleanup-stale-review-tasks.js +130 -1
- package/dist/bin/cli.js +10111 -7540
- package/dist/bin/exe-agent.js +159 -1
- package/dist/bin/exe-assign.js +235 -16
- package/dist/bin/exe-boot.js +344 -472
- package/dist/bin/exe-call.js +145 -1
- package/dist/bin/exe-cloud.js +11 -0
- package/dist/bin/exe-dispatch.js +37 -24
- package/dist/bin/exe-doctor.js +130 -1
- package/dist/bin/exe-export-behaviors.js +150 -7
- package/dist/bin/exe-forget.js +822 -665
- package/dist/bin/exe-gateway.js +470 -62
- package/dist/bin/exe-heartbeat.js +133 -2
- package/dist/bin/exe-kill.js +150 -7
- package/dist/bin/exe-launch-agent.js +150 -7
- package/dist/bin/exe-new-employee.js +756 -224
- package/dist/bin/exe-pending-messages.js +132 -2
- package/dist/bin/exe-pending-notifications.js +130 -1
- package/dist/bin/exe-pending-reviews.js +132 -2
- package/dist/bin/exe-review.js +160 -8
- package/dist/bin/exe-search.js +2473 -2008
- package/dist/bin/exe-session-cleanup.js +238 -51
- package/dist/bin/exe-settings.js +11 -0
- package/dist/bin/exe-status.js +130 -1
- package/dist/bin/exe-team.js +130 -1
- package/dist/bin/git-sweep.js +272 -16
- package/dist/bin/graph-backfill.js +150 -7
- package/dist/bin/graph-export.js +150 -7
- package/dist/bin/install.js +5 -0
- package/dist/bin/scan-tasks.js +238 -19
- package/dist/bin/setup.js +1776 -10
- package/dist/bin/shard-migrate.js +150 -7
- package/dist/bin/update.js +9 -6
- package/dist/bin/wiki-sync.js +150 -7
- package/dist/gateway/index.js +470 -62
- package/dist/hooks/bug-report-worker.js +195 -35
- package/dist/hooks/commit-complete.js +272 -16
- package/dist/hooks/error-recall.js +2313 -1847
- package/dist/hooks/exe-heartbeat-hook.js +5 -0
- package/dist/hooks/ingest-worker.js +330 -58
- package/dist/hooks/ingest.js +11 -0
- package/dist/hooks/instructions-loaded.js +199 -10
- package/dist/hooks/notification.js +199 -10
- package/dist/hooks/post-compact.js +199 -10
- package/dist/hooks/pre-compact.js +199 -10
- package/dist/hooks/pre-tool-use.js +199 -10
- package/dist/hooks/prompt-ingest-worker.js +179 -14
- package/dist/hooks/prompt-submit.js +781 -285
- package/dist/hooks/response-ingest-worker.js +1900 -1405
- package/dist/hooks/session-end.js +456 -12
- package/dist/hooks/session-start.js +2188 -1724
- package/dist/hooks/stop.js +200 -10
- package/dist/hooks/subagent-stop.js +199 -10
- package/dist/hooks/summary-worker.js +604 -334
- package/dist/index.js +554 -61
- package/dist/lib/cloud-sync.js +5 -0
- package/dist/lib/config.js +13 -0
- package/dist/lib/consolidation.js +5 -0
- package/dist/lib/database.js +104 -0
- package/dist/lib/device-registry.js +109 -0
- package/dist/lib/embedder.js +13 -0
- package/dist/lib/employee-templates.js +53 -26
- package/dist/lib/employees.js +5 -0
- package/dist/lib/exe-daemon-client.js +5 -0
- package/dist/lib/exe-daemon.js +493 -79
- package/dist/lib/file-grep.js +20 -4
- package/dist/lib/hybrid-search.js +1435 -190
- package/dist/lib/identity-templates.js +126 -5
- package/dist/lib/identity.js +5 -0
- package/dist/lib/license.js +5 -0
- package/dist/lib/messaging.js +37 -24
- package/dist/lib/schedules.js +130 -1
- package/dist/lib/skill-learning.js +11 -0
- package/dist/lib/status-brief.js +5 -0
- package/dist/lib/store.js +199 -10
- package/dist/lib/task-router.js +72 -6
- package/dist/lib/tasks.js +179 -50
- package/dist/lib/tmux-routing.js +179 -46
- package/dist/mcp/server.js +2129 -1855
- package/dist/mcp/tools/create-task.js +86 -36
- package/dist/mcp/tools/deactivate-behavior.js +5 -0
- package/dist/mcp/tools/list-tasks.js +39 -11
- package/dist/mcp/tools/send-message.js +37 -24
- package/dist/mcp/tools/update-task.js +153 -38
- package/dist/runtime/index.js +451 -59
- package/dist/tui/App.js +454 -59
- package/package.json +1 -1
|
@@ -101,6 +101,11 @@ function normalizeSessionLifecycle(raw) {
|
|
|
101
101
|
const userSL = raw.sessionLifecycle ?? {};
|
|
102
102
|
raw.sessionLifecycle = { ...defaultSL, ...userSL };
|
|
103
103
|
}
|
|
104
|
+
function normalizeAutoUpdate(raw) {
|
|
105
|
+
const defaultAU = DEFAULT_CONFIG.autoUpdate;
|
|
106
|
+
const userAU = raw.autoUpdate ?? {};
|
|
107
|
+
raw.autoUpdate = { ...defaultAU, ...userAU };
|
|
108
|
+
}
|
|
104
109
|
async function loadConfig() {
|
|
105
110
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
106
111
|
await mkdir(dir, { recursive: true });
|
|
@@ -123,6 +128,7 @@ async function loadConfig() {
|
|
|
123
128
|
}
|
|
124
129
|
normalizeScalingRoadmap(migratedCfg);
|
|
125
130
|
normalizeSessionLifecycle(migratedCfg);
|
|
131
|
+
normalizeAutoUpdate(migratedCfg);
|
|
126
132
|
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
127
133
|
if (config.dbPath.startsWith("~")) {
|
|
128
134
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -198,6 +204,11 @@ var init_config = __esm({
|
|
|
198
204
|
idleKillTicksRequired: 3,
|
|
199
205
|
idleKillIntercomAckWindowMs: 1e4,
|
|
200
206
|
maxAutoInstances: 10
|
|
207
|
+
},
|
|
208
|
+
autoUpdate: {
|
|
209
|
+
checkOnBoot: true,
|
|
210
|
+
autoInstall: false,
|
|
211
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
201
212
|
}
|
|
202
213
|
};
|
|
203
214
|
CONFIG_MIGRATIONS = [
|
|
@@ -271,6 +282,36 @@ import path3 from "path";
|
|
|
271
282
|
import { execSync } from "child_process";
|
|
272
283
|
import { mkdir as mkdir2, writeFile as writeFile2, appendFile } from "fs/promises";
|
|
273
284
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
285
|
+
async function writeCheckpoint(input) {
|
|
286
|
+
const client = getClient();
|
|
287
|
+
const row = await resolveTask(client, input.taskId);
|
|
288
|
+
const taskId = String(row.id);
|
|
289
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
290
|
+
const blockedByIds = [];
|
|
291
|
+
if (row.blocked_by) {
|
|
292
|
+
blockedByIds.push(String(row.blocked_by));
|
|
293
|
+
}
|
|
294
|
+
const checkpoint = {
|
|
295
|
+
step: input.step,
|
|
296
|
+
context_summary: input.contextSummary,
|
|
297
|
+
files_touched: input.filesTouched ?? [],
|
|
298
|
+
blocked_by_ids: blockedByIds,
|
|
299
|
+
last_checkpoint_at: now
|
|
300
|
+
};
|
|
301
|
+
const result = await client.execute({
|
|
302
|
+
sql: `UPDATE tasks SET checkpoint = ?, checkpoint_count = checkpoint_count + 1, updated_at = ? WHERE id = ?`,
|
|
303
|
+
args: [JSON.stringify(checkpoint), now, taskId]
|
|
304
|
+
});
|
|
305
|
+
if (result.rowsAffected === 0) {
|
|
306
|
+
throw new Error(`Checkpoint write failed: task ${taskId} not found`);
|
|
307
|
+
}
|
|
308
|
+
const countResult = await client.execute({
|
|
309
|
+
sql: "SELECT checkpoint_count FROM tasks WHERE id = ?",
|
|
310
|
+
args: [taskId]
|
|
311
|
+
});
|
|
312
|
+
const checkpointCount = Number(countResult.rows[0]?.checkpoint_count ?? 1);
|
|
313
|
+
return { checkpointCount };
|
|
314
|
+
}
|
|
274
315
|
async function resolveTask(client, identifier) {
|
|
275
316
|
let result = await client.execute({
|
|
276
317
|
sql: "SELECT * FROM tasks WHERE id = ?",
|
|
@@ -319,8 +360,13 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
319
360
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
320
361
|
try {
|
|
321
362
|
const since = new Date(taskCreatedAt).toISOString();
|
|
363
|
+
const branch = execSync(
|
|
364
|
+
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
365
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
366
|
+
).trim();
|
|
367
|
+
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
322
368
|
const commitCount = execSync(
|
|
323
|
-
`git log --oneline --since="${since}" 2>/dev/null | wc -l`,
|
|
369
|
+
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
324
370
|
{ encoding: "utf8", timeout: 5e3 }
|
|
325
371
|
).trim();
|
|
326
372
|
const count = parseInt(commitCount, 10);
|
|
@@ -379,6 +425,14 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
379
425
|
const claimedBy = cur?.assigned_tmux ? ` (claimed by ${cur.assigned_tmux})` : "";
|
|
380
426
|
throw new Error(`${TASK_ALREADY_CLAIMED_PREFIX}: task ${taskId} is ${status}${claimedBy}`);
|
|
381
427
|
}
|
|
428
|
+
try {
|
|
429
|
+
await writeCheckpoint({
|
|
430
|
+
taskId,
|
|
431
|
+
step: "claimed",
|
|
432
|
+
contextSummary: `Task claimed by session. Transitioning open \u2192 in_progress.`
|
|
433
|
+
});
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
382
436
|
return { row, taskFile, now, taskId };
|
|
383
437
|
}
|
|
384
438
|
if (input.result) {
|
|
@@ -392,6 +446,14 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
392
446
|
args: [input.status, now, taskId]
|
|
393
447
|
});
|
|
394
448
|
}
|
|
449
|
+
try {
|
|
450
|
+
await writeCheckpoint({
|
|
451
|
+
taskId,
|
|
452
|
+
step: `status_transition:${input.status}`,
|
|
453
|
+
contextSummary: input.result ? `Transitioned to ${input.status}. Result: ${input.result.slice(0, 500)}` : `Transitioned to ${input.status}.`
|
|
454
|
+
});
|
|
455
|
+
} catch {
|
|
456
|
+
}
|
|
395
457
|
return { row, taskFile, now, taskId };
|
|
396
458
|
}
|
|
397
459
|
var DELEGATION_KEYWORDS, TASK_ALREADY_CLAIMED_PREFIX;
|
|
@@ -639,11 +701,12 @@ function queueIntercom(targetSession, reason) {
|
|
|
639
701
|
}
|
|
640
702
|
writeQueue(queue);
|
|
641
703
|
}
|
|
642
|
-
var QUEUE_PATH, INTERCOM_LOG;
|
|
704
|
+
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
643
705
|
var init_intercom_queue = __esm({
|
|
644
706
|
"src/lib/intercom-queue.ts"() {
|
|
645
707
|
"use strict";
|
|
646
708
|
QUEUE_PATH = path6.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
709
|
+
TTL_MS = 60 * 60 * 1e3;
|
|
647
710
|
INTERCOM_LOG = path6.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
648
711
|
}
|
|
649
712
|
});
|
|
@@ -687,11 +750,25 @@ var init_worktree = __esm({
|
|
|
687
750
|
});
|
|
688
751
|
|
|
689
752
|
// src/lib/tmux-routing.ts
|
|
690
|
-
import { execFileSync as execFileSync2, execSync as execSync5 } from "child_process";
|
|
691
753
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync8, appendFileSync } from "fs";
|
|
692
754
|
import path9 from "path";
|
|
693
755
|
import os5 from "os";
|
|
694
756
|
import { fileURLToPath } from "url";
|
|
757
|
+
function getMySession() {
|
|
758
|
+
return getTransport().getMySession();
|
|
759
|
+
}
|
|
760
|
+
function extractRootExe(name) {
|
|
761
|
+
const match = name.match(/(exe\d+)$/);
|
|
762
|
+
return match?.[1] ?? null;
|
|
763
|
+
}
|
|
764
|
+
function getParentExe(sessionKey) {
|
|
765
|
+
try {
|
|
766
|
+
const data = JSON.parse(readFileSync7(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
767
|
+
return data.parentExe || null;
|
|
768
|
+
} catch {
|
|
769
|
+
return null;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
695
772
|
function getDispatchedBy(sessionKey) {
|
|
696
773
|
try {
|
|
697
774
|
const data = JSON.parse(readFileSync7(
|
|
@@ -703,6 +780,19 @@ function getDispatchedBy(sessionKey) {
|
|
|
703
780
|
return null;
|
|
704
781
|
}
|
|
705
782
|
}
|
|
783
|
+
function resolveExeSession() {
|
|
784
|
+
const mySession = getMySession();
|
|
785
|
+
if (!mySession) return null;
|
|
786
|
+
try {
|
|
787
|
+
const key = getSessionKey();
|
|
788
|
+
const parentExe = getParentExe(key);
|
|
789
|
+
if (parentExe) {
|
|
790
|
+
return extractRootExe(parentExe) ?? parentExe;
|
|
791
|
+
}
|
|
792
|
+
} catch {
|
|
793
|
+
}
|
|
794
|
+
return extractRootExe(mySession) ?? mySession;
|
|
795
|
+
}
|
|
706
796
|
function readDebounceState() {
|
|
707
797
|
try {
|
|
708
798
|
if (!existsSync8(DEBOUNCE_FILE)) return {};
|
|
@@ -747,6 +837,11 @@ function getSessionState(sessionName) {
|
|
|
747
837
|
if (!transport.isAlive(sessionName)) return "offline";
|
|
748
838
|
try {
|
|
749
839
|
const pane = transport.capturePane(sessionName, 5);
|
|
840
|
+
if (!pane.includes("\u276F") && !pane.includes("Claude Code") && !BUSY_PATTERN.test(pane) && !/Running…/.test(pane)) {
|
|
841
|
+
if (/\$\s*$/.test(pane) || /% $/.test(pane.trimEnd())) {
|
|
842
|
+
return "no_claude";
|
|
843
|
+
}
|
|
844
|
+
}
|
|
750
845
|
if (/Running…/.test(pane)) return "tool";
|
|
751
846
|
if (BUSY_PATTERN.test(pane)) return "thinking";
|
|
752
847
|
return "idle";
|
|
@@ -754,10 +849,6 @@ function getSessionState(sessionName) {
|
|
|
754
849
|
return "offline";
|
|
755
850
|
}
|
|
756
851
|
}
|
|
757
|
-
function isSessionBusy(sessionName) {
|
|
758
|
-
const state = getSessionState(sessionName);
|
|
759
|
-
return state === "thinking" || state === "tool";
|
|
760
|
-
}
|
|
761
852
|
function isExeSession(sessionName) {
|
|
762
853
|
return /^exe\d*$/.test(sessionName);
|
|
763
854
|
}
|
|
@@ -777,7 +868,14 @@ function sendIntercom(targetSession) {
|
|
|
777
868
|
logIntercom(`SKIP \u2192 ${targetSession} (session not found)`);
|
|
778
869
|
return "failed";
|
|
779
870
|
}
|
|
780
|
-
|
|
871
|
+
const sessionState = getSessionState(targetSession);
|
|
872
|
+
if (sessionState === "no_claude") {
|
|
873
|
+
queueIntercom(targetSession, "claude not running in session");
|
|
874
|
+
recordDebounce(targetSession);
|
|
875
|
+
logIntercom(`QUEUED \u2192 ${targetSession} (no claude process \u2014 raw shell detected)`);
|
|
876
|
+
return "queued";
|
|
877
|
+
}
|
|
878
|
+
if (sessionState === "thinking" || sessionState === "tool") {
|
|
781
879
|
queueIntercom(targetSession, "session busy at send time");
|
|
782
880
|
recordDebounce(targetSession);
|
|
783
881
|
logIntercom(`QUEUED \u2192 ${targetSession} (session busy, will retry from queue)`);
|
|
@@ -789,18 +887,7 @@ function sendIntercom(targetSession) {
|
|
|
789
887
|
}
|
|
790
888
|
transport.sendKeys(targetSession, "/exe-intercom");
|
|
791
889
|
recordDebounce(targetSession);
|
|
792
|
-
|
|
793
|
-
try {
|
|
794
|
-
execSync5(`sleep ${INTERCOM_POLL_INTERVAL_S}`);
|
|
795
|
-
} catch {
|
|
796
|
-
}
|
|
797
|
-
const state = getSessionState(targetSession);
|
|
798
|
-
if (state === "thinking" || state === "tool") {
|
|
799
|
-
logIntercom(`ACKNOWLEDGED \u2192 ${targetSession} (state=${state}, poll=${i + 1})`);
|
|
800
|
-
return "acknowledged";
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
logIntercom(`DELIVERED \u2192 ${targetSession} (no state transition after ${INTERCOM_POLL_MAX_ATTEMPTS}s)`);
|
|
890
|
+
logIntercom(`DELIVERED \u2192 ${targetSession} (fire-and-forget)`);
|
|
804
891
|
return "delivered";
|
|
805
892
|
} catch {
|
|
806
893
|
logIntercom(`FAIL \u2192 ${targetSession}`);
|
|
@@ -817,9 +904,19 @@ function notifyParentExe(sessionKey) {
|
|
|
817
904
|
process.stderr.write(`[intercom] notifyParentExe \u2192 ${target}
|
|
818
905
|
`);
|
|
819
906
|
const result = sendIntercom(target);
|
|
820
|
-
|
|
907
|
+
if (result === "failed") {
|
|
908
|
+
const rootExe = resolveExeSession();
|
|
909
|
+
if (rootExe && rootExe !== target) {
|
|
910
|
+
process.stderr.write(`[intercom] notifyParentExe: dispatcher ${target} dead, falling back to root exe ${rootExe}
|
|
911
|
+
`);
|
|
912
|
+
const fallback = sendIntercom(rootExe);
|
|
913
|
+
return fallback !== "failed";
|
|
914
|
+
}
|
|
915
|
+
return false;
|
|
916
|
+
}
|
|
917
|
+
return true;
|
|
821
918
|
}
|
|
822
|
-
var SESSION_CACHE, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN
|
|
919
|
+
var SESSION_CACHE, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
823
920
|
var init_tmux_routing = __esm({
|
|
824
921
|
"src/lib/tmux-routing.ts"() {
|
|
825
922
|
"use strict";
|
|
@@ -838,8 +935,6 @@ var init_tmux_routing = __esm({
|
|
|
838
935
|
DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
|
|
839
936
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
840
937
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
841
|
-
INTERCOM_POLL_INTERVAL_S = 1;
|
|
842
|
-
INTERCOM_POLL_MAX_ATTEMPTS = 8;
|
|
843
938
|
}
|
|
844
939
|
});
|
|
845
940
|
|
|
@@ -850,23 +945,38 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
850
945
|
if (String(row.assigned_by) !== "system" || !taskFile.includes("review-")) return;
|
|
851
946
|
try {
|
|
852
947
|
const client = getClient();
|
|
853
|
-
const
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
if (parts.length >= 3 && parts[0] === "review") {
|
|
857
|
-
const agent = parts[1];
|
|
858
|
-
const slug = parts.slice(2).join("-");
|
|
859
|
-
const originalTaskFile = `exe/${agent}/${slug}.md`;
|
|
948
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
949
|
+
const parentId = row.parent_task_id ? String(row.parent_task_id) : null;
|
|
950
|
+
if (parentId) {
|
|
860
951
|
const result = await client.execute({
|
|
861
|
-
sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE
|
|
862
|
-
args: [
|
|
952
|
+
sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE id = ? AND status = 'needs_review'",
|
|
953
|
+
args: [now, parentId]
|
|
863
954
|
});
|
|
864
955
|
if (result.rowsAffected > 0) {
|
|
865
956
|
process.stderr.write(
|
|
866
|
-
`[review-cleanup] Cascaded original task to done: ${
|
|
957
|
+
`[review-cleanup] Cascaded original task to done via parent_task_id: ${parentId}
|
|
867
958
|
`
|
|
868
959
|
);
|
|
869
960
|
}
|
|
961
|
+
} else {
|
|
962
|
+
const fileName = taskFile.split("/").pop() ?? "";
|
|
963
|
+
const reviewPrefix = fileName.replace(".md", "");
|
|
964
|
+
const parts = reviewPrefix.split("-");
|
|
965
|
+
if (parts.length >= 3 && parts[0] === "review") {
|
|
966
|
+
const agent = parts[1];
|
|
967
|
+
const slug = parts.slice(2).join("-");
|
|
968
|
+
const originalTaskFile = `exe/${agent}/${slug}.md`;
|
|
969
|
+
const result = await client.execute({
|
|
970
|
+
sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE task_file = ? AND status = 'needs_review'",
|
|
971
|
+
args: [now, originalTaskFile]
|
|
972
|
+
});
|
|
973
|
+
if (result.rowsAffected > 0) {
|
|
974
|
+
process.stderr.write(
|
|
975
|
+
`[review-cleanup] Cascaded original task to done (legacy path): ${originalTaskFile}
|
|
976
|
+
`
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
870
980
|
}
|
|
871
981
|
} catch (err) {
|
|
872
982
|
process.stderr.write(
|
|
@@ -1341,10 +1451,11 @@ async function updateTask(input) {
|
|
|
1341
1451
|
try {
|
|
1342
1452
|
const client = getClient();
|
|
1343
1453
|
const taskTitle = String(row.title);
|
|
1454
|
+
const escaped = taskTitle.replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
1344
1455
|
await client.execute({
|
|
1345
1456
|
sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
|
|
1346
|
-
WHERE title LIKE ? AND status IN ('open', 'in_progress')`,
|
|
1347
|
-
args: [now, `%left
|
|
1457
|
+
WHERE title LIKE ? ESCAPE '\\' AND status IN ('open', 'in_progress')`,
|
|
1458
|
+
args: [now, `%left '${escaped}' as in\\_progress%`]
|
|
1348
1459
|
});
|
|
1349
1460
|
} catch {
|
|
1350
1461
|
}
|
|
@@ -1402,6 +1513,10 @@ async function updateTask(input) {
|
|
|
1402
1513
|
taskFile,
|
|
1403
1514
|
createdAt: String(row.created_at),
|
|
1404
1515
|
updatedAt: now,
|
|
1516
|
+
budgetTokens: row.budget_tokens !== void 0 && row.budget_tokens !== null ? Number(row.budget_tokens) : null,
|
|
1517
|
+
budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
|
|
1518
|
+
tokensUsed: Number(row.tokens_used ?? 0),
|
|
1519
|
+
tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
|
|
1405
1520
|
nextTask
|
|
1406
1521
|
};
|
|
1407
1522
|
}
|
|
@@ -1438,7 +1553,7 @@ __export(active_agent_exports, {
|
|
|
1438
1553
|
writeActiveAgent: () => writeActiveAgent
|
|
1439
1554
|
});
|
|
1440
1555
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
|
|
1441
|
-
import { execSync as
|
|
1556
|
+
import { execSync as execSync5 } from "child_process";
|
|
1442
1557
|
import path13 from "path";
|
|
1443
1558
|
function getMarkerPath() {
|
|
1444
1559
|
return path13.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
@@ -1488,7 +1603,7 @@ function getActiveAgent() {
|
|
|
1488
1603
|
} catch {
|
|
1489
1604
|
}
|
|
1490
1605
|
try {
|
|
1491
|
-
const sessionName =
|
|
1606
|
+
const sessionName = execSync5(
|
|
1492
1607
|
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
1493
1608
|
{ encoding: "utf8", timeout: 2e3 }
|
|
1494
1609
|
).trim();
|