panopticon-cli 0.4.31 → 0.4.33
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/{agents-GQDAKTEQ.js → agents-VLK4BMVA.js} +10 -7
- package/dist/chunk-7SN4L4PH.js +150 -0
- package/dist/chunk-7SN4L4PH.js.map +1 -0
- package/dist/chunk-7XNJJBH6.js +538 -0
- package/dist/chunk-7XNJJBH6.js.map +1 -0
- package/dist/chunk-AQXETQHW.js +113 -0
- package/dist/chunk-AQXETQHW.js.map +1 -0
- package/dist/{chunk-TMXN7THF.js → chunk-ASY7T35E.js} +170 -64
- package/dist/chunk-ASY7T35E.js.map +1 -0
- package/dist/chunk-B3PF6JPQ.js +212 -0
- package/dist/chunk-B3PF6JPQ.js.map +1 -0
- package/dist/{chunk-HNEWTIR3.js → chunk-BKCWRMUX.js} +100 -40
- package/dist/chunk-BKCWRMUX.js.map +1 -0
- package/dist/chunk-CFCUOV3Q.js +669 -0
- package/dist/chunk-CFCUOV3Q.js.map +1 -0
- package/dist/chunk-CWELWPWQ.js +32 -0
- package/dist/chunk-CWELWPWQ.js.map +1 -0
- package/dist/chunk-DI7ABPNQ.js +352 -0
- package/dist/chunk-DI7ABPNQ.js.map +1 -0
- package/dist/{chunk-VU4FLXV5.js → chunk-FQ66DECN.js} +31 -4
- package/dist/chunk-FQ66DECN.js.map +1 -0
- package/dist/{review-status-GWQYY77L.js → chunk-GFP3PIPB.js} +14 -7
- package/dist/chunk-GFP3PIPB.js.map +1 -0
- package/dist/chunk-JQBV3Q2W.js +29 -0
- package/dist/chunk-JQBV3Q2W.js.map +1 -0
- package/dist/{chunk-BWGFN44T.js → chunk-JT4O4YVM.js} +28 -16
- package/dist/chunk-JT4O4YVM.js.map +1 -0
- package/dist/{chunk-VIWUCJ4V.js → chunk-KJ2TRXNK.js} +34 -36
- package/dist/chunk-KJ2TRXNK.js.map +1 -0
- package/dist/{chunk-JY7R7V4G.js → chunk-OMNXYPXC.js} +2 -2
- package/dist/chunk-OMNXYPXC.js.map +1 -0
- package/dist/chunk-PELXV435.js +215 -0
- package/dist/chunk-PELXV435.js.map +1 -0
- package/dist/chunk-PI7Y3PSN.js +797 -0
- package/dist/chunk-PI7Y3PSN.js.map +1 -0
- package/dist/chunk-RBUO57TC.js +154 -0
- package/dist/chunk-RBUO57TC.js.map +1 -0
- package/dist/chunk-XFR2DLMR.js +600 -0
- package/dist/chunk-XFR2DLMR.js.map +1 -0
- package/dist/chunk-XKT5MHPT.js +677 -0
- package/dist/chunk-XKT5MHPT.js.map +1 -0
- package/dist/{chunk-HCTJFIJJ.js → chunk-YLPSQAM2.js} +2 -2
- package/dist/{chunk-HCTJFIJJ.js.map → chunk-YLPSQAM2.js.map} +1 -1
- package/dist/{chunk-6HXKTOD7.js → chunk-ZTFNYOC7.js} +53 -38
- package/dist/chunk-ZTFNYOC7.js.map +1 -0
- package/dist/cli/index.js +4362 -2922
- package/dist/cli/index.js.map +1 -1
- package/dist/{config-BOAMSKTF.js → config-4CJNUE3O.js} +7 -3
- package/dist/dashboard/prompts/merge-agent.md +217 -0
- package/dist/dashboard/prompts/review-agent.md +409 -0
- package/dist/dashboard/prompts/sync-main.md +84 -0
- package/dist/dashboard/prompts/test-agent.md +283 -0
- package/dist/dashboard/prompts/work-agent.md +247 -0
- package/dist/dashboard/public/assets/index-UjZq6ykz.css +32 -0
- package/dist/dashboard/public/assets/index-kAJqtLDO.js +708 -0
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard/server.js +15272 -3169
- package/dist/{dns-L3L2BB27.js → dns-7BDJSD3E.js} +4 -2
- package/dist/{feedback-writer-AAKF5BTK.js → feedback-writer-LVZ5TFYZ.js} +8 -4
- package/dist/feedback-writer-LVZ5TFYZ.js.map +1 -0
- package/dist/hume-WMAUBBV2.js +13 -0
- package/dist/index.d.ts +153 -40
- package/dist/index.js +65 -23
- package/dist/index.js.map +1 -1
- package/dist/{projects-VXRUCMLM.js → projects-JEIVIYC6.js} +3 -3
- package/dist/rally-RKFSWC7E.js +10 -0
- package/dist/{remote-agents-Z3R2A5BN.js → remote-agents-TFSMW7GN.js} +2 -2
- package/dist/{remote-workspace-2G6V2KNP.js → remote-workspace-AHVHQEES.js} +8 -8
- package/dist/review-status-EPFG4XM7.js +19 -0
- package/dist/shadow-state-5MDP6YXH.js +30 -0
- package/dist/shadow-state-5MDP6YXH.js.map +1 -0
- package/dist/{specialist-context-6SE5VRRC.js → specialist-context-T3NBMCIE.js} +8 -7
- package/dist/{specialist-context-6SE5VRRC.js.map → specialist-context-T3NBMCIE.js.map} +1 -1
- package/dist/{specialist-logs-EXLOQHQ2.js → specialist-logs-CVKD3YJ3.js} +7 -6
- package/dist/specialist-logs-CVKD3YJ3.js.map +1 -0
- package/dist/{specialists-BRUHPAXE.js → specialists-TKAP6T6Z.js} +7 -6
- package/dist/specialists-TKAP6T6Z.js.map +1 -0
- package/dist/tldr-daemon-T3THOUGT.js +21 -0
- package/dist/tldr-daemon-T3THOUGT.js.map +1 -0
- package/dist/traefik-QX4ZV4YG.js +19 -0
- package/dist/traefik-QX4ZV4YG.js.map +1 -0
- package/dist/tunnel-W2GZBLEV.js +13 -0
- package/dist/tunnel-W2GZBLEV.js.map +1 -0
- package/dist/workspace-manager-KLHUCIZV.js +22 -0
- package/dist/workspace-manager-KLHUCIZV.js.map +1 -0
- package/package.json +2 -2
- package/scripts/heartbeat-hook +37 -10
- package/scripts/patches/llm-tldr-tsx-support.py +109 -0
- package/scripts/pre-tool-hook +26 -15
- package/scripts/record-cost-event.js +177 -43
- package/scripts/record-cost-event.ts +87 -3
- package/scripts/statusline.sh +169 -0
- package/scripts/stop-hook +14 -11
- package/scripts/tldr-post-edit +72 -0
- package/scripts/tldr-read-enforcer +275 -0
- package/skills/check-merged/SKILL.md +143 -0
- package/skills/crash-investigation/SKILL.md +301 -0
- package/skills/github-cli/SKILL.md +185 -0
- package/skills/pan-reopen/SKILL.md +65 -0
- package/skills/pan-sync-main/SKILL.md +87 -0
- package/skills/pan-tldr/SKILL.md +149 -0
- package/skills/react-best-practices/SKILL.md +125 -0
- package/skills/spec-readiness/REPORT-TEMPLATE.md +158 -0
- package/skills/spec-readiness/SCORING-REFERENCE.md +369 -0
- package/skills/spec-readiness/SKILL.md +400 -0
- package/skills/spec-readiness-setup/SKILL.md +361 -0
- package/skills/workspace-status/SKILL.md +56 -0
- package/templates/traefik/dynamic/panopticon.yml.template +0 -5
- package/templates/traefik/traefik.yml +0 -8
- package/dist/chunk-3XAB4IXF.js +0 -51
- package/dist/chunk-3XAB4IXF.js.map +0 -1
- package/dist/chunk-6HXKTOD7.js.map +0 -1
- package/dist/chunk-BBCUK6N2.js +0 -241
- package/dist/chunk-BBCUK6N2.js.map +0 -1
- package/dist/chunk-BWGFN44T.js.map +0 -1
- package/dist/chunk-ELK6Q7QI.js +0 -545
- package/dist/chunk-ELK6Q7QI.js.map +0 -1
- package/dist/chunk-HNEWTIR3.js.map +0 -1
- package/dist/chunk-JY7R7V4G.js.map +0 -1
- package/dist/chunk-LYSBSZYV.js +0 -1523
- package/dist/chunk-LYSBSZYV.js.map +0 -1
- package/dist/chunk-TMXN7THF.js.map +0 -1
- package/dist/chunk-VIWUCJ4V.js.map +0 -1
- package/dist/chunk-VU4FLXV5.js.map +0 -1
- package/dist/dashboard/public/assets/index-C7X6LP5Z.css +0 -32
- package/dist/dashboard/public/assets/index-izWbAt7V.js +0 -645
- package/dist/feedback-writer-AAKF5BTK.js.map +0 -1
- package/dist/review-status-GWQYY77L.js.map +0 -1
- package/dist/traefik-CUJM6K5Z.js +0 -12
- /package/dist/{agents-GQDAKTEQ.js.map → agents-VLK4BMVA.js.map} +0 -0
- /package/dist/{config-BOAMSKTF.js.map → config-4CJNUE3O.js.map} +0 -0
- /package/dist/{dns-L3L2BB27.js.map → dns-7BDJSD3E.js.map} +0 -0
- /package/dist/{projects-VXRUCMLM.js.map → hume-WMAUBBV2.js.map} +0 -0
- /package/dist/{remote-agents-Z3R2A5BN.js.map → projects-JEIVIYC6.js.map} +0 -0
- /package/dist/{specialist-logs-EXLOQHQ2.js.map → rally-RKFSWC7E.js.map} +0 -0
- /package/dist/{specialists-BRUHPAXE.js.map → remote-agents-TFSMW7GN.js.map} +0 -0
- /package/dist/{remote-workspace-2G6V2KNP.js.map → remote-workspace-AHVHQEES.js.map} +0 -0
- /package/dist/{traefik-CUJM6K5Z.js.map → review-status-EPFG4XM7.js.map} +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
init_esm_shims
|
|
3
|
+
} from "./chunk-ZHC57RCV.js";
|
|
4
|
+
|
|
5
|
+
// src/lib/shadow-state.ts
|
|
6
|
+
init_esm_shims();
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
var SHADOW_STATE_DIR = join(homedir(), ".panopticon", "shadow-state");
|
|
11
|
+
function ensureShadowStateDir() {
|
|
12
|
+
if (!existsSync(SHADOW_STATE_DIR)) {
|
|
13
|
+
mkdirSync(SHADOW_STATE_DIR, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function getShadowStatePath(issueId) {
|
|
17
|
+
const normalizedId = issueId.toUpperCase().replace(/[^A-Z0-9-]/g, "");
|
|
18
|
+
return join(SHADOW_STATE_DIR, `${normalizedId}.json`);
|
|
19
|
+
}
|
|
20
|
+
function getShadowState(issueId) {
|
|
21
|
+
const filePath = getShadowStatePath(issueId);
|
|
22
|
+
if (!existsSync(filePath)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const content = readFileSync(filePath, "utf-8");
|
|
27
|
+
return JSON.parse(content);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`Error reading shadow state for ${issueId}:`, error);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function isShadowed(issueId) {
|
|
34
|
+
return getShadowState(issueId) !== null;
|
|
35
|
+
}
|
|
36
|
+
function createShadowState(issueId, initialTrackerStatus = "open", triggeredBy = "unknown") {
|
|
37
|
+
ensureShadowStateDir();
|
|
38
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
39
|
+
const shadowState = {
|
|
40
|
+
issueId: issueId.toUpperCase(),
|
|
41
|
+
shadowStatus: initialTrackerStatus,
|
|
42
|
+
trackerStatus: initialTrackerStatus,
|
|
43
|
+
trackerStatusUpdatedAt: now,
|
|
44
|
+
shadowedAt: now,
|
|
45
|
+
history: []
|
|
46
|
+
};
|
|
47
|
+
const filePath = getShadowStatePath(issueId);
|
|
48
|
+
writeFileSync(filePath, JSON.stringify(shadowState, null, 2), "utf-8");
|
|
49
|
+
return shadowState;
|
|
50
|
+
}
|
|
51
|
+
function updateShadowState(issueId, newStatus, triggeredBy, targetCanonicalState) {
|
|
52
|
+
ensureShadowStateDir();
|
|
53
|
+
let state = getShadowState(issueId);
|
|
54
|
+
if (!state) {
|
|
55
|
+
state = {
|
|
56
|
+
issueId: issueId.toUpperCase(),
|
|
57
|
+
shadowStatus: newStatus,
|
|
58
|
+
targetCanonicalState,
|
|
59
|
+
trackerStatus: newStatus,
|
|
60
|
+
trackerStatusUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
61
|
+
shadowedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62
|
+
history: []
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (state.shadowStatus !== newStatus) {
|
|
66
|
+
const transition = {
|
|
67
|
+
from: state.shadowStatus,
|
|
68
|
+
to: newStatus,
|
|
69
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
70
|
+
by: triggeredBy,
|
|
71
|
+
syncedToTracker: false
|
|
72
|
+
};
|
|
73
|
+
state.history.push(transition);
|
|
74
|
+
state.shadowStatus = newStatus;
|
|
75
|
+
}
|
|
76
|
+
if (targetCanonicalState) {
|
|
77
|
+
state.targetCanonicalState = targetCanonicalState;
|
|
78
|
+
}
|
|
79
|
+
const filePath = getShadowStatePath(issueId);
|
|
80
|
+
writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
81
|
+
return state;
|
|
82
|
+
}
|
|
83
|
+
function updateTrackerStatusCache(issueId, trackerStatus) {
|
|
84
|
+
const state = getShadowState(issueId);
|
|
85
|
+
if (!state) {
|
|
86
|
+
throw new Error(`Cannot update tracker status: ${issueId} is not in shadow mode`);
|
|
87
|
+
}
|
|
88
|
+
state.trackerStatus = trackerStatus;
|
|
89
|
+
state.trackerStatusUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
90
|
+
const filePath = getShadowStatePath(issueId);
|
|
91
|
+
writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
92
|
+
return state;
|
|
93
|
+
}
|
|
94
|
+
function markAsSynced(issueId, syncedState, previousTrackerState) {
|
|
95
|
+
const state = getShadowState(issueId);
|
|
96
|
+
if (!state) {
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: `Issue ${issueId} is not in shadow mode`
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
103
|
+
let entriesSynced = 0;
|
|
104
|
+
for (const entry of state.history) {
|
|
105
|
+
if (!entry.syncedToTracker) {
|
|
106
|
+
entry.syncedToTracker = true;
|
|
107
|
+
entriesSynced++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
state.syncedAt = now;
|
|
111
|
+
state.trackerStatus = syncedState;
|
|
112
|
+
state.trackerStatusUpdatedAt = now;
|
|
113
|
+
const filePath = getShadowStatePath(issueId);
|
|
114
|
+
writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
115
|
+
return {
|
|
116
|
+
success: true,
|
|
117
|
+
syncedState,
|
|
118
|
+
previousState: previousTrackerState,
|
|
119
|
+
entriesSynced
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function listShadowedIssues() {
|
|
123
|
+
if (!existsSync(SHADOW_STATE_DIR)) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const files = readdirSync(SHADOW_STATE_DIR);
|
|
127
|
+
const states = [];
|
|
128
|
+
for (const file of files) {
|
|
129
|
+
if (!file.endsWith(".json")) continue;
|
|
130
|
+
try {
|
|
131
|
+
const content = readFileSync(join(SHADOW_STATE_DIR, file), "utf-8");
|
|
132
|
+
const state = JSON.parse(content);
|
|
133
|
+
states.push(state);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error(`Error reading shadow state file ${file}:`, error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return states.sort(
|
|
139
|
+
(a, b) => new Date(b.shadowedAt).getTime() - new Date(a.shadowedAt).getTime()
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function removeShadowState(issueId, syncFirst = false) {
|
|
143
|
+
const filePath = getShadowStatePath(issueId);
|
|
144
|
+
if (!existsSync(filePath)) {
|
|
145
|
+
return {
|
|
146
|
+
success: false,
|
|
147
|
+
error: `Issue ${issueId} is not in shadow mode`
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
unlinkSync(filePath);
|
|
152
|
+
return {
|
|
153
|
+
success: true,
|
|
154
|
+
synced: syncFirst
|
|
155
|
+
};
|
|
156
|
+
} catch (error) {
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
error: `Failed to remove shadow state: ${error.message}`
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function getDisplayStatus(issueId, trackerStatus) {
|
|
164
|
+
const state = getShadowState(issueId);
|
|
165
|
+
if (!state) {
|
|
166
|
+
return {
|
|
167
|
+
status: trackerStatus,
|
|
168
|
+
isShadowed: false
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
status: state.shadowStatus,
|
|
173
|
+
isShadowed: true,
|
|
174
|
+
trackerStatus: state.trackerStatus,
|
|
175
|
+
outOfSync: state.shadowStatus !== state.trackerStatus
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function needsSync(issueId) {
|
|
179
|
+
const state = getShadowState(issueId);
|
|
180
|
+
if (!state) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
return state.shadowStatus !== state.trackerStatus;
|
|
184
|
+
}
|
|
185
|
+
function getUnsyncedHistory(issueId) {
|
|
186
|
+
const state = getShadowState(issueId);
|
|
187
|
+
if (!state) {
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
return state.history.filter((entry) => !entry.syncedToTracker);
|
|
191
|
+
}
|
|
192
|
+
function getPendingSyncCount() {
|
|
193
|
+
return listShadowedIssues().filter(
|
|
194
|
+
(state) => state.shadowStatus !== state.trackerStatus
|
|
195
|
+
).length;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export {
|
|
199
|
+
getShadowState,
|
|
200
|
+
isShadowed,
|
|
201
|
+
createShadowState,
|
|
202
|
+
updateShadowState,
|
|
203
|
+
updateTrackerStatusCache,
|
|
204
|
+
markAsSynced,
|
|
205
|
+
listShadowedIssues,
|
|
206
|
+
removeShadowState,
|
|
207
|
+
getDisplayStatus,
|
|
208
|
+
needsSync,
|
|
209
|
+
getUnsyncedHistory,
|
|
210
|
+
getPendingSyncCount
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=chunk-B3PF6JPQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/shadow-state.ts"],"sourcesContent":["/**\n * Shadow State Storage Module\n *\n * Manages shadow state for issues - tracking status locally without updating\n * the issue tracker until explicitly synced.\n *\n * Storage Location: ~/.panopticon/shadow-state/\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { IssueState } from './tracker/interface.js';\n\n// Storage directory for shadow state files\nconst SHADOW_STATE_DIR = join(homedir(), '.panopticon', 'shadow-state');\n\n/**\n * Shadow history entry - tracks state transitions\n */\nexport interface ShadowHistoryEntry {\n /** Previous state */\n from: IssueState;\n /** New state */\n to: IssueState;\n /** When the transition occurred */\n at: string;\n /** Command that triggered the transition (e.g., \"pan work plan\", \"dashboard\") */\n by: string;\n /** Whether this transition was synced to the tracker */\n syncedToTracker: boolean;\n}\n\n/**\n * Canonical state for Kanban column placement\n */\nexport type CanonicalState = 'backlog' | 'todo' | 'in_progress' | 'in_review' | 'done' | 'canceled';\n\n/**\n * Shadow state for an issue\n */\nexport interface ShadowState {\n /** Issue ID (e.g., \"MIN-123\") */\n issueId: string;\n /** Panopticon's view of the issue status */\n shadowStatus: IssueState;\n /** Target canonical state for Kanban column placement */\n targetCanonicalState?: CanonicalState;\n /** Last known tracker status (cached) */\n trackerStatus: IssueState;\n /** When tracker status was last fetched */\n trackerStatusUpdatedAt: string;\n /** When shadow mode was enabled for this issue */\n shadowedAt: string;\n /** When shadow state was last synced to tracker */\n syncedAt?: string;\n /** Audit trail of state transitions */\n history: ShadowHistoryEntry[];\n}\n\n/**\n * Result of a sync operation\n */\nexport interface SyncResult {\n success: boolean;\n /** The state that was synced */\n syncedState?: IssueState;\n /** Previous tracker state */\n previousState?: IssueState;\n /** Error message if sync failed */\n error?: string;\n /** Number of history entries marked as synced */\n entriesSynced?: number;\n}\n\n/**\n * Ensure the shadow state directory exists\n */\nfunction ensureShadowStateDir(): void {\n if (!existsSync(SHADOW_STATE_DIR)) {\n mkdirSync(SHADOW_STATE_DIR, { recursive: true });\n }\n}\n\n/**\n * Get the file path for a shadow state file\n */\nfunction getShadowStatePath(issueId: string): string {\n // Normalize issue ID for filename (uppercase, replace special chars)\n const normalizedId = issueId.toUpperCase().replace(/[^A-Z0-9-]/g, '');\n return join(SHADOW_STATE_DIR, `${normalizedId}.json`);\n}\n\n/**\n * Get shadow state for an issue\n * @returns ShadowState or null if not shadowed\n */\nexport function getShadowState(issueId: string): ShadowState | null {\n const filePath = getShadowStatePath(issueId);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as ShadowState;\n } catch (error) {\n console.error(`Error reading shadow state for ${issueId}:`, error);\n return null;\n }\n}\n\n/**\n * Check if an issue is in shadow mode\n */\nexport function isShadowed(issueId: string): boolean {\n return getShadowState(issueId) !== null;\n}\n\n/**\n * Create a new shadow state for an issue\n */\nexport function createShadowState(\n issueId: string,\n initialTrackerStatus: IssueState = 'open',\n triggeredBy: string = 'unknown'\n): ShadowState {\n ensureShadowStateDir();\n\n const now = new Date().toISOString();\n\n const shadowState: ShadowState = {\n issueId: issueId.toUpperCase(),\n shadowStatus: initialTrackerStatus,\n trackerStatus: initialTrackerStatus,\n trackerStatusUpdatedAt: now,\n shadowedAt: now,\n history: [],\n };\n\n const filePath = getShadowStatePath(issueId);\n writeFileSync(filePath, JSON.stringify(shadowState, null, 2), 'utf-8');\n\n return shadowState;\n}\n\n/**\n * Update shadow state for an issue\n */\nexport function updateShadowState(\n issueId: string,\n newStatus: IssueState,\n triggeredBy: string,\n targetCanonicalState?: CanonicalState\n): ShadowState {\n ensureShadowStateDir();\n\n let state = getShadowState(issueId);\n\n // Create new shadow state if it doesn't exist\n if (!state) {\n state = {\n issueId: issueId.toUpperCase(),\n shadowStatus: newStatus,\n targetCanonicalState,\n trackerStatus: newStatus,\n trackerStatusUpdatedAt: new Date().toISOString(),\n shadowedAt: new Date().toISOString(),\n history: [],\n };\n }\n\n // Only record transition if status changed\n if (state.shadowStatus !== newStatus) {\n const transition: ShadowHistoryEntry = {\n from: state.shadowStatus,\n to: newStatus,\n at: new Date().toISOString(),\n by: triggeredBy,\n syncedToTracker: false,\n };\n\n state.history.push(transition);\n state.shadowStatus = newStatus;\n }\n\n // Always update target canonical state if provided\n if (targetCanonicalState) {\n state.targetCanonicalState = targetCanonicalState;\n }\n\n const filePath = getShadowStatePath(issueId);\n writeFileSync(filePath, JSON.stringify(state, null, 2), 'utf-8');\n\n return state;\n}\n\n/**\n * Update tracker status cache (refresh from tracker)\n */\nexport function updateTrackerStatusCache(\n issueId: string,\n trackerStatus: IssueState\n): ShadowState {\n const state = getShadowState(issueId);\n\n if (!state) {\n throw new Error(`Cannot update tracker status: ${issueId} is not in shadow mode`);\n }\n\n state.trackerStatus = trackerStatus;\n state.trackerStatusUpdatedAt = new Date().toISOString();\n\n const filePath = getShadowStatePath(issueId);\n writeFileSync(filePath, JSON.stringify(state, null, 2), 'utf-8');\n\n return state;\n}\n\n/**\n * Sync shadow state to tracker (mark as synced)\n * This is called after successfully updating the tracker\n */\nexport function markAsSynced(\n issueId: string,\n syncedState: IssueState,\n previousTrackerState?: IssueState\n): SyncResult {\n const state = getShadowState(issueId);\n\n if (!state) {\n return {\n success: false,\n error: `Issue ${issueId} is not in shadow mode`,\n };\n }\n\n const now = new Date().toISOString();\n let entriesSynced = 0;\n\n // Mark all unsynced history entries as synced\n for (const entry of state.history) {\n if (!entry.syncedToTracker) {\n entry.syncedToTracker = true;\n entriesSynced++;\n }\n }\n\n // Update sync timestamp and tracker status\n state.syncedAt = now;\n state.trackerStatus = syncedState;\n state.trackerStatusUpdatedAt = now;\n\n const filePath = getShadowStatePath(issueId);\n writeFileSync(filePath, JSON.stringify(state, null, 2), 'utf-8');\n\n return {\n success: true,\n syncedState,\n previousState: previousTrackerState,\n entriesSynced,\n };\n}\n\n/**\n * List all shadowed issues\n */\nexport function listShadowedIssues(): ShadowState[] {\n if (!existsSync(SHADOW_STATE_DIR)) {\n return [];\n }\n\n const files = readdirSync(SHADOW_STATE_DIR);\n const states: ShadowState[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n\n try {\n const content = readFileSync(join(SHADOW_STATE_DIR, file), 'utf-8');\n const state = JSON.parse(content) as ShadowState;\n states.push(state);\n } catch (error) {\n console.error(`Error reading shadow state file ${file}:`, error);\n }\n }\n\n // Sort by shadowedAt (newest first)\n return states.sort((a, b) =>\n new Date(b.shadowedAt).getTime() - new Date(a.shadowedAt).getTime()\n );\n}\n\n/**\n * Remove shadow state for an issue (unshadow)\n * @param syncFirst - If true, attempts to sync to tracker before removing\n */\nexport function removeShadowState(\n issueId: string,\n syncFirst: boolean = false\n): { success: boolean; error?: string; synced?: boolean } {\n const filePath = getShadowStatePath(issueId);\n\n if (!existsSync(filePath)) {\n return {\n success: false,\n error: `Issue ${issueId} is not in shadow mode`,\n };\n }\n\n try {\n // If syncFirst is true, we should have already synced by this point\n // This parameter is just for API clarity\n\n unlinkSync(filePath);\n return {\n success: true,\n synced: syncFirst,\n };\n } catch (error: any) {\n return {\n success: false,\n error: `Failed to remove shadow state: ${error.message}`,\n };\n }\n}\n\n/**\n * Get the display status for an issue\n * Returns shadow status with tracker status info if in shadow mode\n */\nexport function getDisplayStatus(\n issueId: string,\n trackerStatus: IssueState\n): {\n status: IssueState;\n isShadowed: boolean;\n trackerStatus?: IssueState;\n outOfSync?: boolean;\n} {\n const state = getShadowState(issueId);\n\n if (!state) {\n return {\n status: trackerStatus,\n isShadowed: false,\n };\n }\n\n return {\n status: state.shadowStatus,\n isShadowed: true,\n trackerStatus: state.trackerStatus,\n outOfSync: state.shadowStatus !== state.trackerStatus,\n };\n}\n\n/**\n * Check if an issue needs to be synced to tracker\n * (shadow status differs from tracker status)\n */\nexport function needsSync(issueId: string): boolean {\n const state = getShadowState(issueId);\n\n if (!state) {\n return false;\n }\n\n return state.shadowStatus !== state.trackerStatus;\n}\n\n/**\n * Get unsynced history entries for an issue\n */\nexport function getUnsyncedHistory(issueId: string): ShadowHistoryEntry[] {\n const state = getShadowState(issueId);\n\n if (!state) {\n return [];\n }\n\n return state.history.filter(entry => !entry.syncedToTracker);\n}\n\n/**\n * Get the count of issues that need sync\n */\nexport function getPendingSyncCount(): number {\n return listShadowedIssues().filter(state =>\n state.shadowStatus !== state.trackerStatus\n ).length;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -12,25 +12,28 @@ import {
|
|
|
12
12
|
killSession,
|
|
13
13
|
sendKeysAsync,
|
|
14
14
|
sessionExists
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-KJ2TRXNK.js";
|
|
16
16
|
import {
|
|
17
17
|
createTrackerFromConfig,
|
|
18
|
+
init_factory
|
|
19
|
+
} from "./chunk-XFR2DLMR.js";
|
|
20
|
+
import {
|
|
18
21
|
getProviderEnv,
|
|
19
22
|
getProviderForModel,
|
|
20
|
-
init_factory,
|
|
21
23
|
init_providers,
|
|
22
24
|
init_settings,
|
|
23
|
-
loadSettings
|
|
24
|
-
|
|
25
|
+
loadSettings,
|
|
26
|
+
setupCredentialFileAuth
|
|
27
|
+
} from "./chunk-7XNJJBH6.js";
|
|
25
28
|
import {
|
|
26
29
|
init_config,
|
|
27
30
|
loadConfig
|
|
28
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-FQ66DECN.js";
|
|
29
32
|
import {
|
|
30
33
|
AGENTS_DIR,
|
|
31
34
|
PANOPTICON_HOME,
|
|
32
35
|
init_paths
|
|
33
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-ZTFNYOC7.js";
|
|
34
37
|
import {
|
|
35
38
|
__esm,
|
|
36
39
|
init_esm_shims
|
|
@@ -291,17 +294,11 @@ var init_config2 = __esm({
|
|
|
291
294
|
specialist_models: {
|
|
292
295
|
merge_agent: "sonnet",
|
|
293
296
|
review_agent: "sonnet",
|
|
294
|
-
test_agent: "haiku"
|
|
295
|
-
planning_agent: "opus"
|
|
297
|
+
test_agent: "haiku"
|
|
296
298
|
}
|
|
297
299
|
},
|
|
298
300
|
handoffs: {
|
|
299
301
|
auto_triggers: {
|
|
300
|
-
planning_complete: {
|
|
301
|
-
enabled: true,
|
|
302
|
-
from_model: "opus",
|
|
303
|
-
to_model: "sonnet"
|
|
304
|
-
},
|
|
305
302
|
stuck_escalation: {
|
|
306
303
|
enabled: true,
|
|
307
304
|
haiku_to_sonnet_minutes: 10,
|
|
@@ -351,6 +348,12 @@ import { join as join3 } from "path";
|
|
|
351
348
|
import { homedir } from "os";
|
|
352
349
|
import { exec } from "child_process";
|
|
353
350
|
import { promisify } from "util";
|
|
351
|
+
function normalizeAgentId(agentId) {
|
|
352
|
+
if (AGENT_PREFIXES.some((p) => agentId.startsWith(p))) {
|
|
353
|
+
return agentId;
|
|
354
|
+
}
|
|
355
|
+
return `agent-${agentId.toLowerCase()}`;
|
|
356
|
+
}
|
|
354
357
|
function getProviderEnvForModel(model) {
|
|
355
358
|
const provider = getProviderForModel(model);
|
|
356
359
|
if (provider.name === "anthropic") return {};
|
|
@@ -377,7 +380,7 @@ function clearReadySignal(agentId) {
|
|
|
377
380
|
async function waitForReadySignal(agentId, timeoutSeconds = 30) {
|
|
378
381
|
const readyPath = getReadySignalPath(agentId);
|
|
379
382
|
for (let i = 0; i < timeoutSeconds; i++) {
|
|
380
|
-
await new Promise((
|
|
383
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
381
384
|
if (existsSync3(readyPath)) {
|
|
382
385
|
try {
|
|
383
386
|
const content = readFileSync3(readyPath, "utf-8");
|
|
@@ -408,33 +411,53 @@ function saveAgentState(state) {
|
|
|
408
411
|
JSON.stringify(state, null, 2)
|
|
409
412
|
);
|
|
410
413
|
}
|
|
414
|
+
function getAgentRuntimeFile(agentId) {
|
|
415
|
+
return join3(getAgentDir(agentId), "runtime.json");
|
|
416
|
+
}
|
|
411
417
|
function getAgentRuntimeState(agentId) {
|
|
418
|
+
const runtimeFile = getAgentRuntimeFile(agentId);
|
|
412
419
|
const stateFile = join3(getAgentDir(agentId), "state.json");
|
|
413
|
-
if (
|
|
420
|
+
if (existsSync3(runtimeFile)) {
|
|
421
|
+
try {
|
|
422
|
+
const content = readFileSync3(runtimeFile, "utf8");
|
|
423
|
+
return JSON.parse(content);
|
|
424
|
+
} catch {
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (existsSync3(stateFile)) {
|
|
428
|
+
try {
|
|
429
|
+
const content = readFileSync3(stateFile, "utf8");
|
|
430
|
+
const parsed = JSON.parse(content);
|
|
431
|
+
if (parsed.state && parsed.lastActivity) {
|
|
432
|
+
return parsed;
|
|
433
|
+
}
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (!existsSync3(stateFile) && !existsSync3(runtimeFile)) {
|
|
414
438
|
return {
|
|
415
439
|
state: "uninitialized",
|
|
416
440
|
lastActivity: (/* @__PURE__ */ new Date()).toISOString()
|
|
417
441
|
};
|
|
418
442
|
}
|
|
419
|
-
|
|
420
|
-
const content = readFileSync3(stateFile, "utf8");
|
|
421
|
-
return JSON.parse(content);
|
|
422
|
-
} catch {
|
|
423
|
-
return null;
|
|
424
|
-
}
|
|
443
|
+
return null;
|
|
425
444
|
}
|
|
426
445
|
function saveAgentRuntimeState(agentId, state) {
|
|
427
446
|
const dir = getAgentDir(agentId);
|
|
428
447
|
mkdirSync3(dir, { recursive: true });
|
|
429
|
-
const
|
|
448
|
+
const runtimeFile = getAgentRuntimeFile(agentId);
|
|
449
|
+
let existing = null;
|
|
450
|
+
if (existsSync3(runtimeFile)) {
|
|
451
|
+
try {
|
|
452
|
+
existing = JSON.parse(readFileSync3(runtimeFile, "utf8"));
|
|
453
|
+
} catch {
|
|
454
|
+
}
|
|
455
|
+
}
|
|
430
456
|
const merged = {
|
|
431
457
|
...existing || { state: "uninitialized", lastActivity: (/* @__PURE__ */ new Date()).toISOString() },
|
|
432
458
|
...state
|
|
433
459
|
};
|
|
434
|
-
writeFileSync3(
|
|
435
|
-
join3(dir, "state.json"),
|
|
436
|
-
JSON.stringify(merged, null, 2)
|
|
437
|
-
);
|
|
460
|
+
writeFileSync3(runtimeFile, JSON.stringify(merged, null, 2));
|
|
438
461
|
}
|
|
439
462
|
function appendActivity(agentId, entry) {
|
|
440
463
|
const dir = getAgentDir(agentId);
|
|
@@ -496,9 +519,6 @@ function determineModel(options) {
|
|
|
496
519
|
return getModelId(workType);
|
|
497
520
|
}
|
|
498
521
|
if (options.agentType && options.agentType !== "work-agent") {
|
|
499
|
-
if (options.agentType === "planning-agent") {
|
|
500
|
-
return getModelId("planning-agent");
|
|
501
|
-
}
|
|
502
522
|
const workType = `specialist-${options.agentType}`;
|
|
503
523
|
return getModelId(workType);
|
|
504
524
|
}
|
|
@@ -514,16 +534,16 @@ function determineModel(options) {
|
|
|
514
534
|
const defaultModel = cloisterConfig.model_selection?.default_model || "sonnet";
|
|
515
535
|
const modelMap = {
|
|
516
536
|
"opus": "claude-opus-4-6",
|
|
517
|
-
"sonnet": "claude-sonnet-4-
|
|
537
|
+
"sonnet": "claude-sonnet-4-6",
|
|
518
538
|
"haiku": "claude-haiku-4-5"
|
|
519
539
|
};
|
|
520
|
-
return modelMap[defaultModel] || "claude-sonnet-4-
|
|
540
|
+
return modelMap[defaultModel] || "claude-sonnet-4-6";
|
|
521
541
|
} catch {
|
|
522
|
-
return "claude-sonnet-4-
|
|
542
|
+
return "claude-sonnet-4-6";
|
|
523
543
|
}
|
|
524
544
|
} catch (error) {
|
|
525
545
|
console.warn("Warning: Could not resolve model using work type router, using default");
|
|
526
|
-
return options.model || "claude-sonnet-4-
|
|
546
|
+
return options.model || "claude-sonnet-4-6";
|
|
527
547
|
}
|
|
528
548
|
}
|
|
529
549
|
async function transitionIssueToInProgress(issueId) {
|
|
@@ -581,9 +601,26 @@ async function spawnAgent(options) {
|
|
|
581
601
|
writeFileSync3(promptFile, prompt);
|
|
582
602
|
}
|
|
583
603
|
checkAndSetupHooks();
|
|
604
|
+
try {
|
|
605
|
+
const venvPath = join3(options.workspace, ".venv");
|
|
606
|
+
if (existsSync3(venvPath)) {
|
|
607
|
+
const { getTldrDaemonService } = await import("./tldr-daemon-T3THOUGT.js");
|
|
608
|
+
const tldrService = getTldrDaemonService(options.workspace, venvPath);
|
|
609
|
+
const status = await tldrService.getStatus();
|
|
610
|
+
if (!status.running) {
|
|
611
|
+
await tldrService.start(true);
|
|
612
|
+
console.log(`[${agentId}] Started TLDR daemon for workspace`);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
} catch {
|
|
616
|
+
}
|
|
584
617
|
writeTaskCache(agentId, options.issueId);
|
|
585
618
|
clearReadySignal(agentId);
|
|
586
619
|
const providerEnv = getProviderEnvForModel(selectedModel);
|
|
620
|
+
const provider = getProviderForModel(selectedModel);
|
|
621
|
+
if (provider.authType === "credential-file") {
|
|
622
|
+
setupCredentialFileAuth(provider, options.workspace);
|
|
623
|
+
}
|
|
587
624
|
let claudeCmd;
|
|
588
625
|
if (prompt) {
|
|
589
626
|
const launcherScript = join3(getAgentDir(agentId), "launcher.sh");
|
|
@@ -596,11 +633,18 @@ exec claude --dangerously-skip-permissions --model ${state.model} "$prompt"
|
|
|
596
633
|
} else {
|
|
597
634
|
claudeCmd = `claude --dangerously-skip-permissions --model ${state.model}`;
|
|
598
635
|
}
|
|
636
|
+
try {
|
|
637
|
+
const { preTrustDirectory } = await import("./workspace-manager-KLHUCIZV.js");
|
|
638
|
+
preTrustDirectory(options.workspace);
|
|
639
|
+
} catch {
|
|
640
|
+
}
|
|
599
641
|
createSession(agentId, options.workspace, claudeCmd, {
|
|
600
642
|
env: {
|
|
601
643
|
PANOPTICON_AGENT_ID: agentId,
|
|
602
644
|
PANOPTICON_ISSUE_ID: options.issueId,
|
|
603
645
|
PANOPTICON_SESSION_TYPE: options.phase || "implementation",
|
|
646
|
+
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
|
|
647
|
+
// Disable suggested prompts for autonomous agents (PAN-251)
|
|
604
648
|
...providerEnv
|
|
605
649
|
// Add provider-specific env vars (BASE_URL, AUTH_TOKEN, etc.)
|
|
606
650
|
}
|
|
@@ -633,7 +677,7 @@ function listRunningAgents() {
|
|
|
633
677
|
return agents;
|
|
634
678
|
}
|
|
635
679
|
function stopAgent(agentId) {
|
|
636
|
-
const normalizedId =
|
|
680
|
+
const normalizedId = normalizeAgentId(agentId);
|
|
637
681
|
if (sessionExists(normalizedId)) {
|
|
638
682
|
try {
|
|
639
683
|
const output = capturePane(normalizedId, 5e3);
|
|
@@ -654,7 +698,7 @@ function stopAgent(agentId) {
|
|
|
654
698
|
}
|
|
655
699
|
}
|
|
656
700
|
async function messageAgent(agentId, message) {
|
|
657
|
-
const normalizedId =
|
|
701
|
+
const normalizedId = normalizeAgentId(agentId);
|
|
658
702
|
const runtimeState = getAgentRuntimeState(normalizedId);
|
|
659
703
|
if (runtimeState?.state === "suspended") {
|
|
660
704
|
console.log(`[agents] Auto-resuming suspended agent ${normalizedId} to deliver message`);
|
|
@@ -664,7 +708,7 @@ async function messageAgent(agentId, message) {
|
|
|
664
708
|
}
|
|
665
709
|
return;
|
|
666
710
|
}
|
|
667
|
-
const { loadRemoteAgentState, sendToRemoteAgent } = await import("./remote-agents-
|
|
711
|
+
const { loadRemoteAgentState, sendToRemoteAgent } = await import("./remote-agents-TFSMW7GN.js");
|
|
668
712
|
const remoteState = loadRemoteAgentState(normalizedId);
|
|
669
713
|
if (remoteState && remoteState.vmName) {
|
|
670
714
|
console.log(`[agents] Sending message to remote agent ${normalizedId} on ${remoteState.vmName}`);
|
|
@@ -697,7 +741,7 @@ ${message}
|
|
|
697
741
|
);
|
|
698
742
|
}
|
|
699
743
|
async function resumeAgent(agentId, message) {
|
|
700
|
-
const normalizedId =
|
|
744
|
+
const normalizedId = normalizeAgentId(agentId);
|
|
701
745
|
const runtimeState = getAgentRuntimeState(normalizedId);
|
|
702
746
|
if (!runtimeState || runtimeState.state !== "suspended") {
|
|
703
747
|
return {
|
|
@@ -728,10 +772,17 @@ async function resumeAgent(agentId, message) {
|
|
|
728
772
|
try {
|
|
729
773
|
clearReadySignal(normalizedId);
|
|
730
774
|
const providerEnv = agentState.model ? getProviderEnvForModel(agentState.model) : {};
|
|
775
|
+
if (agentState.model) {
|
|
776
|
+
const provider = getProviderForModel(agentState.model);
|
|
777
|
+
if (provider.authType === "credential-file") {
|
|
778
|
+
setupCredentialFileAuth(provider, agentState.workspace);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
731
781
|
const claudeCmd = `claude --resume "${sessionId}" --dangerously-skip-permissions`;
|
|
732
782
|
createSession(normalizedId, agentState.workspace, claudeCmd, {
|
|
733
783
|
env: {
|
|
734
784
|
PANOPTICON_AGENT_ID: normalizedId,
|
|
785
|
+
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
|
|
735
786
|
...providerEnv
|
|
736
787
|
}
|
|
737
788
|
});
|
|
@@ -768,7 +819,7 @@ function detectCrashedAgents() {
|
|
|
768
819
|
);
|
|
769
820
|
}
|
|
770
821
|
function recoverAgent(agentId) {
|
|
771
|
-
const normalizedId =
|
|
822
|
+
const normalizedId = normalizeAgentId(agentId);
|
|
772
823
|
const state = getAgentState(normalizedId);
|
|
773
824
|
if (!state) {
|
|
774
825
|
return null;
|
|
@@ -793,10 +844,17 @@ function recoverAgent(agentId) {
|
|
|
793
844
|
writeFileSync3(healthFile, JSON.stringify(health, null, 2));
|
|
794
845
|
const recoveryPrompt = generateRecoveryPrompt(state);
|
|
795
846
|
const providerEnv = state.model ? getProviderEnvForModel(state.model) : {};
|
|
847
|
+
if (state.model) {
|
|
848
|
+
const provider = getProviderForModel(state.model);
|
|
849
|
+
if (provider.authType === "credential-file") {
|
|
850
|
+
setupCredentialFileAuth(provider, state.workspace);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
796
853
|
const claudeCmd = `claude --dangerously-skip-permissions --model ${state.model} "${recoveryPrompt.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
|
|
797
854
|
createSession(normalizedId, state.workspace, claudeCmd, {
|
|
798
855
|
env: {
|
|
799
856
|
PANOPTICON_AGENT_ID: normalizedId,
|
|
857
|
+
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: "false",
|
|
800
858
|
...providerEnv
|
|
801
859
|
}
|
|
802
860
|
});
|
|
@@ -900,7 +958,7 @@ function writeTaskCache(agentId, issueId) {
|
|
|
900
958
|
}, null, 2)
|
|
901
959
|
);
|
|
902
960
|
}
|
|
903
|
-
var execAsync;
|
|
961
|
+
var execAsync, AGENT_PREFIXES;
|
|
904
962
|
var init_agents = __esm({
|
|
905
963
|
"src/lib/agents.ts"() {
|
|
906
964
|
init_esm_shims();
|
|
@@ -915,6 +973,7 @@ var init_agents = __esm({
|
|
|
915
973
|
init_config();
|
|
916
974
|
init_factory();
|
|
917
975
|
execAsync = promisify(exec);
|
|
976
|
+
AGENT_PREFIXES = ["agent-", "planning-"];
|
|
918
977
|
}
|
|
919
978
|
});
|
|
920
979
|
|
|
@@ -929,6 +988,7 @@ export {
|
|
|
929
988
|
getAgentDir,
|
|
930
989
|
getAgentState,
|
|
931
990
|
saveAgentState,
|
|
991
|
+
getAgentRuntimeFile,
|
|
932
992
|
getAgentRuntimeState,
|
|
933
993
|
saveAgentRuntimeState,
|
|
934
994
|
appendActivity,
|
|
@@ -945,4 +1005,4 @@ export {
|
|
|
945
1005
|
autoRecoverAgents,
|
|
946
1006
|
init_agents
|
|
947
1007
|
};
|
|
948
|
-
//# sourceMappingURL=chunk-
|
|
1008
|
+
//# sourceMappingURL=chunk-BKCWRMUX.js.map
|