bosun 0.42.2 → 0.42.4
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/.env.example +9 -0
- package/agent/agent-event-bus.mjs +10 -0
- package/agent/agent-supervisor.mjs +20 -0
- package/bosun-tui.mjs +107 -105
- package/cli.mjs +10 -0
- package/config/config.mjs +25 -0
- package/config/executor-config.mjs +124 -1
- package/infra/container-runner.mjs +565 -1
- package/infra/monitor.mjs +18 -0
- package/infra/tracing.mjs +544 -240
- package/infra/tui-bridge.mjs +13 -1
- package/kanban/kanban-adapter.mjs +128 -4
- package/lib/repo-map.mjs +114 -3
- package/package.json +11 -4
- package/server/ui-server.mjs +3 -0
- package/task/task-archiver.mjs +18 -6
- package/task/task-attachments.mjs +14 -10
- package/task/task-cli.mjs +24 -4
- package/task/task-executor.mjs +19 -0
- package/task/task-store.mjs +194 -37
- package/telegram/telegram-bot.mjs +4 -1
- package/tui/app.mjs +131 -171
- package/tui/components/status-header.mjs +178 -75
- package/tui/lib/header-config.mjs +68 -0
- package/tui/lib/ws-bridge.mjs +61 -9
- package/tui/screens/agents.mjs +127 -0
- package/tui/screens/tasks.mjs +1 -48
- package/ui/app.js +8 -5
- package/ui/components/kanban-board.js +65 -3
- package/ui/components/session-list.js +18 -32
- package/ui/demo-defaults.js +52 -2
- package/ui/modules/session-api.js +100 -0
- package/ui/modules/state.js +71 -15
- package/ui/tabs/workflows.js +25 -1
- package/ui/tui/App.js +298 -0
- package/ui/tui/TasksScreen.js +564 -0
- package/ui/tui/constants.js +55 -0
- package/ui/tui/tasks-screen-helpers.js +301 -0
- package/ui/tui/useTasks.js +61 -0
- package/ui/tui/useWebSocket.js +166 -0
- package/ui/tui/useWorkflows.js +30 -0
- package/workflow/workflow-engine.mjs +412 -7
- package/workflow/workflow-nodes.mjs +616 -75
- package/workflow-templates/agents.mjs +3 -0
- package/workflow-templates/planning.mjs +7 -0
- package/workflow-templates/sub-workflows.mjs +5 -0
- package/workflow-templates/task-execution.mjs +3 -0
- package/workspace/command-diagnostics.mjs +1 -1
- package/workspace/context-cache.mjs +182 -9
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
formatSessionFreshnessTimestamp,
|
|
16
16
|
getSessionLifecycleState,
|
|
17
17
|
getSessionManualRetryState,
|
|
18
|
+
getSessionListState,
|
|
18
19
|
getSessionRecencyTimestamp,
|
|
19
20
|
getSessionRuntimeState,
|
|
20
21
|
markSessionLoadFailure,
|
|
@@ -120,15 +121,15 @@ export async function loadSessions(filter = {}, _opts = {}) {
|
|
|
120
121
|
if (value == null || value === "") continue;
|
|
121
122
|
params.set(key, String(value));
|
|
122
123
|
}
|
|
124
|
+
const currentSelectedSessionId = String(selectedSessionId.value || "").trim();
|
|
123
125
|
const res = await apiFetch(`/api/sessions?${params}`, { _silent: true });
|
|
124
126
|
if (res?.sessions) {
|
|
125
127
|
sessionsData.value = res.sessions;
|
|
126
128
|
const sessionIds = new Set(
|
|
127
129
|
res.sessions.map((session) => String(session?.id || "")).filter(Boolean),
|
|
128
130
|
);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
131
|
+
const selectedSessionStillExists = !currentSelectedSessionId || sessionIds.has(currentSelectedSessionId);
|
|
132
|
+
selectedSessionId.value = selectedSessionStillExists ? currentSelectedSessionId : null;
|
|
132
133
|
}
|
|
133
134
|
clearSessionRetryTimer();
|
|
134
135
|
const responseMeta = createSessionLoadMeta({
|
|
@@ -146,8 +147,9 @@ export async function loadSessions(filter = {}, _opts = {}) {
|
|
|
146
147
|
});
|
|
147
148
|
sessionLoadMeta.value = nextMeta;
|
|
148
149
|
scheduleSessionRetry(nextMeta);
|
|
150
|
+
const nextErrorState = classifySessionRequestError(error);
|
|
149
151
|
const hasCachedData = Array.isArray(sessionsData.peek()) && sessionsData.peek().length > 0;
|
|
150
|
-
sessionsError.value = hasCachedData
|
|
152
|
+
sessionsError.value = hasCachedData ? null : nextErrorState;
|
|
151
153
|
} finally {
|
|
152
154
|
sessionsLoading.value = false;
|
|
153
155
|
}
|
|
@@ -163,26 +165,7 @@ function _bindSessionStore(targetId, messages, pagination) {
|
|
|
163
165
|
export async function loadSessionMessages(id, opts = {}) {
|
|
164
166
|
const targetSessionId = String(id || "").trim();
|
|
165
167
|
if (!targetSessionId) return { ok: false, error: "invalid" };
|
|
166
|
-
|
|
167
|
-
const raw = String(err?.message || "").trim();
|
|
168
|
-
if (!raw) return "";
|
|
169
|
-
try {
|
|
170
|
-
const parsed = JSON.parse(raw);
|
|
171
|
-
if (parsed && typeof parsed.error === "string") {
|
|
172
|
-
return String(parsed.error).trim();
|
|
173
|
-
}
|
|
174
|
-
} catch {
|
|
175
|
-
// Not a JSON API error body.
|
|
176
|
-
}
|
|
177
|
-
return raw;
|
|
178
|
-
};
|
|
179
|
-
const isScopedSessionNotFound = (err) => {
|
|
180
|
-
const message = parseApiError(err).toLowerCase();
|
|
181
|
-
return (
|
|
182
|
-
message.includes("session not found") ||
|
|
183
|
-
message.includes("request failed (404)")
|
|
184
|
-
);
|
|
185
|
-
};
|
|
168
|
+
|
|
186
169
|
const buildMessagesUrl = (path, limit, offset) => {
|
|
187
170
|
try {
|
|
188
171
|
const parsed = new URL(path, globalThis.location?.origin || "http://localhost");
|
|
@@ -217,10 +200,7 @@ export async function loadSessionMessages(id, opts = {}) {
|
|
|
217
200
|
try {
|
|
218
201
|
res = await fetchSessionAtPath(baseUrl, limit, opts.offset);
|
|
219
202
|
} catch (err) {
|
|
220
|
-
const shouldRetryAll =
|
|
221
|
-
Boolean(fallbackUrl) &&
|
|
222
|
-
fallbackUrl !== baseUrl &&
|
|
223
|
-
isScopedSessionNotFound(err);
|
|
203
|
+
const shouldRetryAll = shouldFallbackToAllSessions(err, baseUrl, fallbackUrl);
|
|
224
204
|
if (!shouldRetryAll) throw err;
|
|
225
205
|
res = await fetchSessionAtPath(fallbackUrl, limit, opts.offset);
|
|
226
206
|
}
|
|
@@ -927,7 +907,12 @@ export function SessionList({
|
|
|
927
907
|
const loadMeta = sessionLoadMeta.value || createSessionLoadMeta();
|
|
928
908
|
const isLoadingSessions = sessionsLoading.value === true;
|
|
929
909
|
const error = sessionsError.value;
|
|
930
|
-
const
|
|
910
|
+
const listState = getSessionListState({
|
|
911
|
+
sessions: allSessions,
|
|
912
|
+
error,
|
|
913
|
+
loadMeta,
|
|
914
|
+
});
|
|
915
|
+
const showStaleBanner = listState.key === "stale";
|
|
931
916
|
const [retryCountdownNow, setRetryCountdownNow] = useState(() => Date.now());
|
|
932
917
|
const hasSearch = search.trim().length > 0;
|
|
933
918
|
const resolvedSessionView =
|
|
@@ -1193,7 +1178,7 @@ export function SessionList({
|
|
|
1193
1178
|
? "Manual retry is disabled while automatic backoff is active."
|
|
1194
1179
|
: "");
|
|
1195
1180
|
|
|
1196
|
-
if (
|
|
1181
|
+
if (listState.isError && !showStaleBanner) {
|
|
1197
1182
|
return html`
|
|
1198
1183
|
<${Paper} elevation=${0} sx=${{ height: "100%", display: "flex", flexDirection: "column" }}>
|
|
1199
1184
|
<${Box} sx=${{ p: 1.5, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
|
@@ -1201,8 +1186,8 @@ export function SessionList({
|
|
|
1201
1186
|
</${Box}>
|
|
1202
1187
|
<${Divider} />
|
|
1203
1188
|
<${Box} sx=${{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", p: 3, gap: 1.5 }}>
|
|
1204
|
-
<${Alert} severity
|
|
1205
|
-
Sessions not available
|
|
1189
|
+
<${Alert} severity=${listState.key === "not_found" ? "info" : "error"} variant="outlined" sx=${{ mb: 1 }}>
|
|
1190
|
+
${listState.message || "Sessions not available"}
|
|
1206
1191
|
</${Alert}>
|
|
1207
1192
|
<${Button}
|
|
1208
1193
|
variant="outlined"
|
|
@@ -1453,3 +1438,4 @@ export function SessionList({
|
|
|
1453
1438
|
`;
|
|
1454
1439
|
}
|
|
1455
1440
|
|
|
1441
|
+
|
package/ui/demo-defaults.js
CHANGED
|
@@ -4669,7 +4669,9 @@
|
|
|
4669
4669
|
"label": "Plan Implementation",
|
|
4670
4670
|
"config": {
|
|
4671
4671
|
"prompt": "Analyze the task requirements and create a step-by-step implementation plan. Identify which files need to be modified, what tests need to be written, and any API contracts to maintain.",
|
|
4672
|
-
"outputVariable": "plan"
|
|
4672
|
+
"outputVariable": "plan",
|
|
4673
|
+
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
4674
|
+
"repoMapFileLimit": 8
|
|
4673
4675
|
},
|
|
4674
4676
|
"position": {
|
|
4675
4677
|
"x": 400,
|
|
@@ -7052,6 +7054,8 @@
|
|
|
7052
7054
|
"taskCount": "{{taskCount}}",
|
|
7053
7055
|
"context": "{{plannerContext}}",
|
|
7054
7056
|
"prompt": "{{prompt}}",
|
|
7057
|
+
"repoMapQuery": "{{plannerContext}} {{prompt}}",
|
|
7058
|
+
"repoMapFileLimit": 8,
|
|
7055
7059
|
"dedup": true,
|
|
7056
7060
|
"timeoutMs": 960000,
|
|
7057
7061
|
"agentTimeoutMs": 900000,
|
|
@@ -7351,6 +7355,8 @@
|
|
|
7351
7355
|
"taskCount": "{{taskCount}}",
|
|
7352
7356
|
"context": "{{plannerContext}}",
|
|
7353
7357
|
"prompt": "{{prompt}}",
|
|
7358
|
+
"repoMapQuery": "{{plannerContext}} {{prompt}}",
|
|
7359
|
+
"repoMapFileLimit": 8,
|
|
7354
7360
|
"timeoutMs": 960000,
|
|
7355
7361
|
"agentTimeoutMs": 900000,
|
|
7356
7362
|
"maxRetries": 0,
|
|
@@ -14339,6 +14345,7 @@
|
|
|
14339
14345
|
"resolveMode": "library",
|
|
14340
14346
|
"failOnError": false,
|
|
14341
14347
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
14348
|
+
"repoMapFileLimit": 8,
|
|
14342
14349
|
"mode": "plan",
|
|
14343
14350
|
"executionRole": "architect"
|
|
14344
14351
|
},
|
|
@@ -14367,6 +14374,7 @@
|
|
|
14367
14374
|
"resolveMode": "library",
|
|
14368
14375
|
"failOnError": false,
|
|
14369
14376
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
14377
|
+
"repoMapFileLimit": 8,
|
|
14370
14378
|
"executionRole": "editor",
|
|
14371
14379
|
"architectPlan": "{{$ctx.getNodeOutput('plan')?.summary || $ctx.getNodeOutput('plan')?.output || ''}}"
|
|
14372
14380
|
},
|
|
@@ -14395,6 +14403,7 @@
|
|
|
14395
14403
|
"resolveMode": "library",
|
|
14396
14404
|
"failOnError": false,
|
|
14397
14405
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
14406
|
+
"repoMapFileLimit": 8,
|
|
14398
14407
|
"executionRole": "editor",
|
|
14399
14408
|
"architectPlan": "{{$ctx.getNodeOutput('plan')?.summary || $ctx.getNodeOutput('plan')?.output || ''}}"
|
|
14400
14409
|
},
|
|
@@ -14729,6 +14738,7 @@
|
|
|
14729
14738
|
"resolveMode": "library",
|
|
14730
14739
|
"failOnError": false,
|
|
14731
14740
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
14741
|
+
"repoMapFileLimit": 8,
|
|
14732
14742
|
"mode": "plan",
|
|
14733
14743
|
"executionRole": "architect"
|
|
14734
14744
|
},
|
|
@@ -14757,6 +14767,7 @@
|
|
|
14757
14767
|
"resolveMode": "library",
|
|
14758
14768
|
"failOnError": false,
|
|
14759
14769
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
14770
|
+
"repoMapFileLimit": 8,
|
|
14760
14771
|
"executionRole": "editor",
|
|
14761
14772
|
"architectPlan": "{{$ctx.getNodeOutput('plan-pipeline')?.summary || $ctx.getNodeOutput('plan-pipeline')?.output || ''}}"
|
|
14762
14773
|
},
|
|
@@ -14785,6 +14796,7 @@
|
|
|
14785
14796
|
"resolveMode": "library",
|
|
14786
14797
|
"failOnError": false,
|
|
14787
14798
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
14799
|
+
"repoMapFileLimit": 8,
|
|
14788
14800
|
"executionRole": "editor",
|
|
14789
14801
|
"architectPlan": "{{$ctx.getNodeOutput('plan-pipeline')?.summary || $ctx.getNodeOutput('plan-pipeline')?.output || ''}}"
|
|
14790
14802
|
},
|
|
@@ -15240,6 +15252,7 @@
|
|
|
15240
15252
|
"resolveMode": "library",
|
|
15241
15253
|
"failOnError": false,
|
|
15242
15254
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15255
|
+
"repoMapFileLimit": 8,
|
|
15243
15256
|
"mode": "plan",
|
|
15244
15257
|
"executionRole": "architect"
|
|
15245
15258
|
},
|
|
@@ -15268,6 +15281,7 @@
|
|
|
15268
15281
|
"resolveMode": "library",
|
|
15269
15282
|
"failOnError": false,
|
|
15270
15283
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15284
|
+
"repoMapFileLimit": 8,
|
|
15271
15285
|
"executionRole": "editor",
|
|
15272
15286
|
"architectPlan": "{{$ctx.getNodeOutput('reproduce')?.summary || $ctx.getNodeOutput('reproduce')?.output || ''}}"
|
|
15273
15287
|
},
|
|
@@ -15296,6 +15310,7 @@
|
|
|
15296
15310
|
"resolveMode": "library",
|
|
15297
15311
|
"failOnError": false,
|
|
15298
15312
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15313
|
+
"repoMapFileLimit": 8,
|
|
15299
15314
|
"executionRole": "editor",
|
|
15300
15315
|
"architectPlan": "{{$ctx.getNodeOutput('reproduce')?.summary || $ctx.getNodeOutput('reproduce')?.output || ''}}"
|
|
15301
15316
|
},
|
|
@@ -15425,6 +15440,7 @@
|
|
|
15425
15440
|
"resolveMode": "library",
|
|
15426
15441
|
"failOnError": false,
|
|
15427
15442
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15443
|
+
"repoMapFileLimit": 8,
|
|
15428
15444
|
"mode": "plan",
|
|
15429
15445
|
"executionRole": "architect"
|
|
15430
15446
|
},
|
|
@@ -15453,6 +15469,7 @@
|
|
|
15453
15469
|
"resolveMode": "library",
|
|
15454
15470
|
"failOnError": false,
|
|
15455
15471
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15472
|
+
"repoMapFileLimit": 8,
|
|
15456
15473
|
"executionRole": "editor",
|
|
15457
15474
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-requirements')?.summary || $ctx.getNodeOutput('analyse-requirements')?.output || ''}}"
|
|
15458
15475
|
},
|
|
@@ -15481,6 +15498,7 @@
|
|
|
15481
15498
|
"resolveMode": "library",
|
|
15482
15499
|
"failOnError": false,
|
|
15483
15500
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15501
|
+
"repoMapFileLimit": 8,
|
|
15484
15502
|
"executionRole": "editor",
|
|
15485
15503
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-requirements')?.summary || $ctx.getNodeOutput('analyse-requirements')?.output || ''}}"
|
|
15486
15504
|
},
|
|
@@ -15794,6 +15812,7 @@
|
|
|
15794
15812
|
"resolveMode": "library",
|
|
15795
15813
|
"failOnError": false,
|
|
15796
15814
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15815
|
+
"repoMapFileLimit": 8,
|
|
15797
15816
|
"mode": "plan",
|
|
15798
15817
|
"executionRole": "architect"
|
|
15799
15818
|
},
|
|
@@ -15822,6 +15841,7 @@
|
|
|
15822
15841
|
"resolveMode": "library",
|
|
15823
15842
|
"failOnError": false,
|
|
15824
15843
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15844
|
+
"repoMapFileLimit": 8,
|
|
15825
15845
|
"executionRole": "editor",
|
|
15826
15846
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-design')?.summary || $ctx.getNodeOutput('analyse-design')?.output || ''}}"
|
|
15827
15847
|
},
|
|
@@ -15850,6 +15870,7 @@
|
|
|
15850
15870
|
"resolveMode": "library",
|
|
15851
15871
|
"failOnError": false,
|
|
15852
15872
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15873
|
+
"repoMapFileLimit": 8,
|
|
15853
15874
|
"executionRole": "editor",
|
|
15854
15875
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-design')?.summary || $ctx.getNodeOutput('analyse-design')?.output || ''}}"
|
|
15855
15876
|
},
|
|
@@ -15973,6 +15994,7 @@
|
|
|
15973
15994
|
"resolveMode": "library",
|
|
15974
15995
|
"failOnError": false,
|
|
15975
15996
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
15997
|
+
"repoMapFileLimit": 8,
|
|
15976
15998
|
"mode": "plan",
|
|
15977
15999
|
"executionRole": "architect"
|
|
15978
16000
|
},
|
|
@@ -16001,6 +16023,7 @@
|
|
|
16001
16023
|
"resolveMode": "library",
|
|
16002
16024
|
"failOnError": false,
|
|
16003
16025
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
16026
|
+
"repoMapFileLimit": 8,
|
|
16004
16027
|
"executionRole": "editor",
|
|
16005
16028
|
"architectPlan": "{{$ctx.getNodeOutput('plan-architecture')?.summary || $ctx.getNodeOutput('plan-architecture')?.output || ''}}"
|
|
16006
16029
|
},
|
|
@@ -16029,6 +16052,7 @@
|
|
|
16029
16052
|
"resolveMode": "library",
|
|
16030
16053
|
"failOnError": false,
|
|
16031
16054
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
16055
|
+
"repoMapFileLimit": 8,
|
|
16032
16056
|
"executionRole": "editor",
|
|
16033
16057
|
"architectPlan": "{{$ctx.getNodeOutput('plan-architecture')?.summary || $ctx.getNodeOutput('plan-architecture')?.output || ''}}"
|
|
16034
16058
|
},
|
|
@@ -16057,6 +16081,7 @@
|
|
|
16057
16081
|
"resolveMode": "library",
|
|
16058
16082
|
"failOnError": false,
|
|
16059
16083
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
16084
|
+
"repoMapFileLimit": 8,
|
|
16060
16085
|
"executionRole": "editor",
|
|
16061
16086
|
"architectPlan": "{{$ctx.getNodeOutput('plan-architecture')?.summary || $ctx.getNodeOutput('plan-architecture')?.output || ''}}"
|
|
16062
16087
|
},
|
|
@@ -25398,7 +25423,9 @@
|
|
|
25398
25423
|
"label": "Plan Implementation",
|
|
25399
25424
|
"config": {
|
|
25400
25425
|
"prompt": "Analyze the task requirements and create a step-by-step implementation plan. Identify which files need to be modified, what tests need to be written, and any API contracts to maintain.",
|
|
25401
|
-
"outputVariable": "plan"
|
|
25426
|
+
"outputVariable": "plan",
|
|
25427
|
+
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
25428
|
+
"repoMapFileLimit": 8
|
|
25402
25429
|
},
|
|
25403
25430
|
"position": {
|
|
25404
25431
|
"x": 400,
|
|
@@ -27652,6 +27679,8 @@
|
|
|
27652
27679
|
"taskCount": "{{taskCount}}",
|
|
27653
27680
|
"context": "{{plannerContext}}",
|
|
27654
27681
|
"prompt": "{{prompt}}",
|
|
27682
|
+
"repoMapQuery": "{{plannerContext}} {{prompt}}",
|
|
27683
|
+
"repoMapFileLimit": 8,
|
|
27655
27684
|
"dedup": true,
|
|
27656
27685
|
"timeoutMs": 960000,
|
|
27657
27686
|
"agentTimeoutMs": 900000,
|
|
@@ -27933,6 +27962,8 @@
|
|
|
27933
27962
|
"taskCount": "{{taskCount}}",
|
|
27934
27963
|
"context": "{{plannerContext}}",
|
|
27935
27964
|
"prompt": "{{prompt}}",
|
|
27965
|
+
"repoMapQuery": "{{plannerContext}} {{prompt}}",
|
|
27966
|
+
"repoMapFileLimit": 8,
|
|
27936
27967
|
"timeoutMs": 960000,
|
|
27937
27968
|
"agentTimeoutMs": 900000,
|
|
27938
27969
|
"maxRetries": 0,
|
|
@@ -34533,6 +34564,7 @@
|
|
|
34533
34564
|
"resolveMode": "library",
|
|
34534
34565
|
"failOnError": false,
|
|
34535
34566
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
34567
|
+
"repoMapFileLimit": 8,
|
|
34536
34568
|
"mode": "plan",
|
|
34537
34569
|
"executionRole": "architect"
|
|
34538
34570
|
},
|
|
@@ -34561,6 +34593,7 @@
|
|
|
34561
34593
|
"resolveMode": "library",
|
|
34562
34594
|
"failOnError": false,
|
|
34563
34595
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
34596
|
+
"repoMapFileLimit": 8,
|
|
34564
34597
|
"executionRole": "editor",
|
|
34565
34598
|
"architectPlan": "{{$ctx.getNodeOutput('plan')?.summary || $ctx.getNodeOutput('plan')?.output || ''}}"
|
|
34566
34599
|
},
|
|
@@ -34589,6 +34622,7 @@
|
|
|
34589
34622
|
"resolveMode": "library",
|
|
34590
34623
|
"failOnError": false,
|
|
34591
34624
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
34625
|
+
"repoMapFileLimit": 8,
|
|
34592
34626
|
"executionRole": "editor",
|
|
34593
34627
|
"architectPlan": "{{$ctx.getNodeOutput('plan')?.summary || $ctx.getNodeOutput('plan')?.output || ''}}"
|
|
34594
34628
|
},
|
|
@@ -34901,6 +34935,7 @@
|
|
|
34901
34935
|
"resolveMode": "library",
|
|
34902
34936
|
"failOnError": false,
|
|
34903
34937
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
34938
|
+
"repoMapFileLimit": 8,
|
|
34904
34939
|
"mode": "plan",
|
|
34905
34940
|
"executionRole": "architect"
|
|
34906
34941
|
},
|
|
@@ -34929,6 +34964,7 @@
|
|
|
34929
34964
|
"resolveMode": "library",
|
|
34930
34965
|
"failOnError": false,
|
|
34931
34966
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
34967
|
+
"repoMapFileLimit": 8,
|
|
34932
34968
|
"executionRole": "editor",
|
|
34933
34969
|
"architectPlan": "{{$ctx.getNodeOutput('plan-pipeline')?.summary || $ctx.getNodeOutput('plan-pipeline')?.output || ''}}"
|
|
34934
34970
|
},
|
|
@@ -34957,6 +34993,7 @@
|
|
|
34957
34993
|
"resolveMode": "library",
|
|
34958
34994
|
"failOnError": false,
|
|
34959
34995
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
34996
|
+
"repoMapFileLimit": 8,
|
|
34960
34997
|
"executionRole": "editor",
|
|
34961
34998
|
"architectPlan": "{{$ctx.getNodeOutput('plan-pipeline')?.summary || $ctx.getNodeOutput('plan-pipeline')?.output || ''}}"
|
|
34962
34999
|
},
|
|
@@ -35386,6 +35423,7 @@
|
|
|
35386
35423
|
"resolveMode": "library",
|
|
35387
35424
|
"failOnError": false,
|
|
35388
35425
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35426
|
+
"repoMapFileLimit": 8,
|
|
35389
35427
|
"mode": "plan",
|
|
35390
35428
|
"executionRole": "architect"
|
|
35391
35429
|
},
|
|
@@ -35414,6 +35452,7 @@
|
|
|
35414
35452
|
"resolveMode": "library",
|
|
35415
35453
|
"failOnError": false,
|
|
35416
35454
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35455
|
+
"repoMapFileLimit": 8,
|
|
35417
35456
|
"executionRole": "editor",
|
|
35418
35457
|
"architectPlan": "{{$ctx.getNodeOutput('reproduce')?.summary || $ctx.getNodeOutput('reproduce')?.output || ''}}"
|
|
35419
35458
|
},
|
|
@@ -35442,6 +35481,7 @@
|
|
|
35442
35481
|
"resolveMode": "library",
|
|
35443
35482
|
"failOnError": false,
|
|
35444
35483
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35484
|
+
"repoMapFileLimit": 8,
|
|
35445
35485
|
"executionRole": "editor",
|
|
35446
35486
|
"architectPlan": "{{$ctx.getNodeOutput('reproduce')?.summary || $ctx.getNodeOutput('reproduce')?.output || ''}}"
|
|
35447
35487
|
},
|
|
@@ -35558,6 +35598,7 @@
|
|
|
35558
35598
|
"resolveMode": "library",
|
|
35559
35599
|
"failOnError": false,
|
|
35560
35600
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35601
|
+
"repoMapFileLimit": 8,
|
|
35561
35602
|
"mode": "plan",
|
|
35562
35603
|
"executionRole": "architect"
|
|
35563
35604
|
},
|
|
@@ -35586,6 +35627,7 @@
|
|
|
35586
35627
|
"resolveMode": "library",
|
|
35587
35628
|
"failOnError": false,
|
|
35588
35629
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35630
|
+
"repoMapFileLimit": 8,
|
|
35589
35631
|
"executionRole": "editor",
|
|
35590
35632
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-requirements')?.summary || $ctx.getNodeOutput('analyse-requirements')?.output || ''}}"
|
|
35591
35633
|
},
|
|
@@ -35614,6 +35656,7 @@
|
|
|
35614
35656
|
"resolveMode": "library",
|
|
35615
35657
|
"failOnError": false,
|
|
35616
35658
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35659
|
+
"repoMapFileLimit": 8,
|
|
35617
35660
|
"executionRole": "editor",
|
|
35618
35661
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-requirements')?.summary || $ctx.getNodeOutput('analyse-requirements')?.output || ''}}"
|
|
35619
35662
|
},
|
|
@@ -35906,6 +35949,7 @@
|
|
|
35906
35949
|
"resolveMode": "library",
|
|
35907
35950
|
"failOnError": false,
|
|
35908
35951
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35952
|
+
"repoMapFileLimit": 8,
|
|
35909
35953
|
"mode": "plan",
|
|
35910
35954
|
"executionRole": "architect"
|
|
35911
35955
|
},
|
|
@@ -35934,6 +35978,7 @@
|
|
|
35934
35978
|
"resolveMode": "library",
|
|
35935
35979
|
"failOnError": false,
|
|
35936
35980
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
35981
|
+
"repoMapFileLimit": 8,
|
|
35937
35982
|
"executionRole": "editor",
|
|
35938
35983
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-design')?.summary || $ctx.getNodeOutput('analyse-design')?.output || ''}}"
|
|
35939
35984
|
},
|
|
@@ -35962,6 +36007,7 @@
|
|
|
35962
36007
|
"resolveMode": "library",
|
|
35963
36008
|
"failOnError": false,
|
|
35964
36009
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
36010
|
+
"repoMapFileLimit": 8,
|
|
35965
36011
|
"executionRole": "editor",
|
|
35966
36012
|
"architectPlan": "{{$ctx.getNodeOutput('analyse-design')?.summary || $ctx.getNodeOutput('analyse-design')?.output || ''}}"
|
|
35967
36013
|
},
|
|
@@ -36078,6 +36124,7 @@
|
|
|
36078
36124
|
"resolveMode": "library",
|
|
36079
36125
|
"failOnError": false,
|
|
36080
36126
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
36127
|
+
"repoMapFileLimit": 8,
|
|
36081
36128
|
"mode": "plan",
|
|
36082
36129
|
"executionRole": "architect"
|
|
36083
36130
|
},
|
|
@@ -36106,6 +36153,7 @@
|
|
|
36106
36153
|
"resolveMode": "library",
|
|
36107
36154
|
"failOnError": false,
|
|
36108
36155
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
36156
|
+
"repoMapFileLimit": 8,
|
|
36109
36157
|
"executionRole": "editor",
|
|
36110
36158
|
"architectPlan": "{{$ctx.getNodeOutput('plan-architecture')?.summary || $ctx.getNodeOutput('plan-architecture')?.output || ''}}"
|
|
36111
36159
|
},
|
|
@@ -36134,6 +36182,7 @@
|
|
|
36134
36182
|
"resolveMode": "library",
|
|
36135
36183
|
"failOnError": false,
|
|
36136
36184
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
36185
|
+
"repoMapFileLimit": 8,
|
|
36137
36186
|
"executionRole": "editor",
|
|
36138
36187
|
"architectPlan": "{{$ctx.getNodeOutput('plan-architecture')?.summary || $ctx.getNodeOutput('plan-architecture')?.output || ''}}"
|
|
36139
36188
|
},
|
|
@@ -36162,6 +36211,7 @@
|
|
|
36162
36211
|
"resolveMode": "library",
|
|
36163
36212
|
"failOnError": false,
|
|
36164
36213
|
"repoMapQuery": "{{taskTitle}} {{taskDescription}}",
|
|
36214
|
+
"repoMapFileLimit": 8,
|
|
36165
36215
|
"executionRole": "editor",
|
|
36166
36216
|
"architectPlan": "{{$ctx.getNodeOutput('plan-architecture')?.summary || $ctx.getNodeOutput('plan-architecture')?.output || ''}}"
|
|
36167
36217
|
},
|
|
@@ -210,6 +210,58 @@ export function deriveSessionStaleReason(error) {
|
|
|
210
210
|
message: raw,
|
|
211
211
|
};
|
|
212
212
|
}
|
|
213
|
+
export function classifySessionRequestError(error) {
|
|
214
|
+
const raw = String(error?.message || error || "").trim();
|
|
215
|
+
const lower = raw.toLowerCase();
|
|
216
|
+
const code = String(error?.code || "").trim().toLowerCase();
|
|
217
|
+
const status = Number(error?.status || error?.statusCode || 0);
|
|
218
|
+
if (!raw && !code && !status) {
|
|
219
|
+
return {
|
|
220
|
+
raw,
|
|
221
|
+
isNotFound: false,
|
|
222
|
+
isTransient: false,
|
|
223
|
+
key: null,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
const isNotFound =
|
|
227
|
+
status === 404
|
|
228
|
+
|| code === "not_found"
|
|
229
|
+
|| lower.includes("not_found")
|
|
230
|
+
|| lower.includes("session not found")
|
|
231
|
+
|| lower.includes("request failed (404)")
|
|
232
|
+
|| lower.includes("not found");
|
|
233
|
+
const isTransient =
|
|
234
|
+
!isNotFound && (
|
|
235
|
+
code === "request_failed"
|
|
236
|
+
|| code === "timeout"
|
|
237
|
+
|| code === "offline"
|
|
238
|
+
|| status === 408
|
|
239
|
+
|| status === 429
|
|
240
|
+
|| status >= 500
|
|
241
|
+
|| lower.includes("timeout")
|
|
242
|
+
|| lower.includes("timed out")
|
|
243
|
+
|| lower.includes("network")
|
|
244
|
+
|| lower.includes("offline")
|
|
245
|
+
|| lower.includes("request failed")
|
|
246
|
+
|| lower.includes("gateway")
|
|
247
|
+
|| lower.includes("unavailable")
|
|
248
|
+
);
|
|
249
|
+
return {
|
|
250
|
+
raw,
|
|
251
|
+
isNotFound,
|
|
252
|
+
isTransient,
|
|
253
|
+
key: isNotFound ? "not_found" : isTransient ? "unavailable" : "fatal",
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function isScopedSessionNotFound(error) {
|
|
258
|
+
return classifySessionRequestError(error).isNotFound;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function shouldFallbackToAllSessions(error, primaryPath, fallbackPath) {
|
|
262
|
+
if (!fallbackPath || fallbackPath === primaryPath) return false;
|
|
263
|
+
return isScopedSessionNotFound(error);
|
|
264
|
+
}
|
|
213
265
|
|
|
214
266
|
export function getSessionManualRetryState(meta, options = {}) {
|
|
215
267
|
const now = Number(options?.now || Date.now()) || Date.now();
|
|
@@ -301,6 +353,52 @@ export function resetSessionRetryMeta(previousMeta) {
|
|
|
301
353
|
};
|
|
302
354
|
}
|
|
303
355
|
|
|
356
|
+
export function getSessionListState(input = {}) {
|
|
357
|
+
const sessions = Array.isArray(input?.sessions) ? input.sessions.filter(Boolean) : [];
|
|
358
|
+
const loadMeta = createSessionLoadMeta(input?.loadMeta || {});
|
|
359
|
+
const hasSessions = sessions.length > 0;
|
|
360
|
+
const isStale = Boolean(loadMeta.stale && (loadMeta.lastSuccessAt || hasSessions));
|
|
361
|
+
const errorState = input?.error && typeof input.error === "object"
|
|
362
|
+
? input.error
|
|
363
|
+
: classifySessionRequestError(input?.error);
|
|
364
|
+
const errorKey = String(errorState?.key || "").trim().toLowerCase() || null;
|
|
365
|
+
|
|
366
|
+
if (isStale) {
|
|
367
|
+
return {
|
|
368
|
+
key: "stale",
|
|
369
|
+
isError: false,
|
|
370
|
+
canRetry: true,
|
|
371
|
+
hasSessions,
|
|
372
|
+
message: "Session list is showing stale data.",
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (errorKey === "not_found") {
|
|
376
|
+
return {
|
|
377
|
+
key: "not_found",
|
|
378
|
+
isError: true,
|
|
379
|
+
canRetry: true,
|
|
380
|
+
hasSessions: false,
|
|
381
|
+
message: "Sessions not found",
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
if (errorKey) {
|
|
385
|
+
return {
|
|
386
|
+
key: errorKey,
|
|
387
|
+
isError: true,
|
|
388
|
+
canRetry: true,
|
|
389
|
+
hasSessions,
|
|
390
|
+
message: errorKey === "fatal" ? "Sessions failed to load" : "Sessions not available",
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
key: "ready",
|
|
395
|
+
isError: false,
|
|
396
|
+
canRetry: false,
|
|
397
|
+
hasSessions,
|
|
398
|
+
message: "",
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
304
402
|
function normalizeWorkspaceHint(value) {
|
|
305
403
|
const raw = String(value || "").trim();
|
|
306
404
|
if (!raw) return "";
|
|
@@ -457,3 +555,5 @@ export function buildSessionApiPath(sessionId, action = "", opts = {}) {
|
|
|
457
555
|
|
|
458
556
|
|
|
459
557
|
|
|
558
|
+
|
|
559
|
+
|