@tea-agent/loop-agent 0.40.0-next.4 → 0.40.0-next.6
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/CHANGELOG.md +20 -0
- package/dist/build-stamp.json +3 -3
- package/dist/executors/shell-executor.js +4 -1
- package/dist/infrastructure/harness/atomic-write.js +23 -0
- package/dist/worker/console/chat/chat-event-store.js +62 -4
- package/dist/worker/console/chat/context-panel.js +7 -0
- package/dist/worker/console/chat/deferred-turn.js +12 -0
- package/dist/worker/console/chat/pi-runtime.js +264 -16
- package/dist/worker/console/chat/provider-error.js +98 -0
- package/dist/worker/console/chat/routes.js +292 -29
- package/dist/worker/console/chat/session-stats.js +179 -0
- package/dist/worker/console/chat/session-store.js +93 -63
- package/dist/worker/console/chat/todos.js +115 -0
- package/dist/worker/console/chat/tool-preview.js +42 -0
- package/dist/worker/console/chat/turn-process.js +20 -55
- package/dist/worker/console/chat/user-questions.js +266 -0
- package/dist/worker/console/chat/workspace-landing.js +14 -0
- package/dist/worker/console/native-directory-picker.js +13 -0
- package/dist/worker/console/routes.js +309 -1
- package/dist/worker/console/security.js +4 -4
- package/dist/worker/console/server.js +529 -186
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CTx1TrNa.js → abnfDiagram-N423BO3Z-DGt5TRsk.js} +1 -1
- package/dist/worker/console/static/assets/{arc-B4i9cVxX.js → arc-DKBSJsXm.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BAXE8_Rl.js → architectureDiagram-T3A2C74G-BnhooRBs.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-C5Xh59at.js → blockDiagram-VBNYF7ZC-Bm9qkrJP.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B_asOzAu.js → c4Diagram-5PPSVZJV-B2cFh4bO.js} +1 -1
- package/dist/worker/console/static/assets/channel-DSgFX07x.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-wRO_iRNc.js → chunk-2GRJ4B5K-DhvWRI03.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-ByOaSh_G.js → chunk-2Q5K7J3B-chzTP_2w.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLzudan.js → chunk-5RXB4S5H-SdWIR12m.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-JCNGkXYT.js → chunk-5VM5RSS4-C2-8Eo_A.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BhrPXXMZ.js → chunk-6Q2QTUOP-DvbE1yQW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-TJ5JuEBT.js → chunk-GF5L2VYU-CEenyPTz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-VVthn_mD.js → chunk-JWPE2WC7-CcaZrq0k.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-D60-Mny4.js → chunk-KBJHAD2P-FGngOTto.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-zXv7aVye.js → chunk-RYQCIY6F-jT_yX3sf.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-By9VQoi1.js → chunk-XXDRQBXY-CjE9LQOM.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-unJObRls.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-unJObRls.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-C4zQLe-M.js → cose-bilkent-JH36ORCC-GQWns1tb.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-wh5N2ReN.js → cynefin-VYW2F7L2-CGRpxWNJ.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Dlu5wIqs.js → cynefinDiagram-MW4NZA55-Cd3uFGE4.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CrDgthc6.js → dagre-VZM6K2ZE-DmDHuUW0.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-zN1clg27.js → diagram-7IWD3JNH-kAr--hF3.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BN-o7J7-.js → diagram-B4RE2ZJO-woahL2Oh.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C8SuPt0d.js → diagram-LBJQPF4R-7syNVaNf.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BoizuHbZ.js → diagram-Q27KOJAE-BELPXiaY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BzUzXixG.js → diagram-UB23O5K3-CrPa4aXi.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Ev3lA4Cf.js → ebnfDiagram-BXEA7PRR-B48u2VVe.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-GALUzRbs.js → erDiagram-JOGREHBK-DhBTfwTF.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CZJN65Sb.js → flowDiagram-UKHOOZJN-CAeZ5nDU.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-JLB9OESl.js → ganttDiagram-PKOTCBZU-CkIFeFLN.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CcvCr4GD.js → gitGraphDiagram-DS77QQ5N-t0HGYDel.js} +1 -1
- package/dist/worker/console/static/assets/index-B4l5ag79.js +407 -0
- package/dist/worker/console/static/assets/index-CwVHWB71.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-HG5z7aVg.js → infoDiagram-6WML65LV-WM0HZhe4.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BHEu9chR.js → ishikawaDiagram-WSZJBQD7-CV5byHe0.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Cp_Up8-a.js → journeyDiagram-NVQOT4AX-lIyWkgnw.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DvVeY-em.js → kanban-definition-27J2QSJJ-BIH4YNRY.js} +1 -1
- package/dist/worker/console/static/assets/{linear-aGmcjgTn.js → linear-lQ0ZGrWc.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-Biyo-tqA.js → mermaid.core-BYdXtke8.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DyxY2pIb.js → mindmap-definition-FAOFIHXS-k93vkIa4.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CkdGuc50.js → pegDiagram-VL7TDLO6-Bm6AqvSy.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-NNQI9xVR.js → pieDiagram-7S7Q4E2Y-DnJW6Xpf.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-PAJkuz_G.js → quadrantDiagram-CIZ2JOQS-CMzm4ObL.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-ZwrQod0O.js → railroadDiagram-AXF67PYL-fwFF5dFQ.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D3ZfrzM2.js → requirementDiagram-LRYGKXZP-tzl9VDUc.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DDGFmWk5.js → sankeyDiagram-W5VNT64P-B26V09DD.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DO6mmXTA.js → sequenceDiagram-SI44F4Z6-D2npyCeP.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DMbCQiJt.js → sizeCapture-X5ZJPWSS-CTJtkRU2.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Di_YUEfC.js → stateDiagram-OKZ733FA-B8lk4Lzu.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BmOcMTJE.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-Bn2PphNJ.js → swimlanes-SLNWSIFB-C3yP53hH.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Beah-dq0.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DPh8pRsp.js → timeline-definition-Z64GVDOM-Bck7xjhe.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-GMfl26pW.js → vennDiagram-T6HMQDX7-CCntr1w7.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DTlmVrmF.js → wardleyDiagram-T6FBY63Y-DsCqCBZz.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-YGBjKAS5.js → xychartDiagram-ELKLHX3M-Br2l90OM.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +29 -4
- package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
- package/dist/worker/console/static-src/app/useOperatorActions.js +36 -6
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +10 -11
- package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
- package/dist/worker/console/static-src/app/useTaskWizard.js +2 -2
- package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +140 -8
- package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
- package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
- package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +168 -72
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +78 -17
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +184 -4
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
- package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +337 -0
- package/dist/worker/console/workspace-context.js +234 -0
- package/dist/worker/console/workspace-registry.js +214 -0
- package/dist/worker/observe/server.js +4 -0
- package/dist/worker/observe/static/api.js +26 -6
- package/dist/worker/observe/static/app.js +18 -70
- package/dist/worker/observe/static/index.html +1 -1
- package/dist/worker/observe/static/inspect-workspace.js +307 -0
- package/dist/worker/observe/static/operator-chrome.css +145 -20
- package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
- package/dist/worker/observe/static/operator-chrome.js +330 -100
- package/dist/worker/observe/static/router.d.ts +46 -0
- package/dist/worker/observe/static/router.js +25 -1
- package/dist/worker/observe/static/state.d.ts +50 -0
- package/dist/worker/observe/static/state.js +172 -0
- package/dist/worker/observe/static/views/dag-inspector.js +3 -2
- package/dist/worker/observe/static/views/dag.js +2 -1
- package/dist/worker/observe/static/views/dashboard.js +6 -4
- package/dist/worker/observe/static/views/night.js +2 -2
- package/dist/worker/observe/static/views/pool.js +1 -0
- package/dist/worker/observe/static/views/run.js +3 -1
- package/dist/worker/observe/static/views/task.js +1 -1
- package/dist/workflows/dag/backend-test-pytest-collection.js +11 -10
- package/dist/workflows/dag/interrupt-request.js +3 -3
- package/dist/workflows/dag/lifecycle.js +3 -3
- package/docs/README.md +1 -0
- package/docs/operations/local-development-environment.md +21 -0
- package/harness.json +3 -3
- package/package.json +3 -1
- package/dist/worker/console/static/assets/channel-Dj_4Moei.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C0YYAyCa.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C0YYAyCa.js +0 -1
- package/dist/worker/console/static/assets/index-CW88Fjbw.js +0 -406
- package/dist/worker/console/static/assets/index-DP0ZJl39.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DrdDvela.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DPkEAULl.js +0 -8
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** 与 state.js 对应的类型声明(供 vitest/TS 侧导入契约测试)。 */
|
|
2
|
+
|
|
3
|
+
export type ViewStateKind = "loading" | "empty" | "degraded" | "error";
|
|
4
|
+
|
|
5
|
+
export type ViewStateDescriptor = {
|
|
6
|
+
kind: ViewStateKind;
|
|
7
|
+
className: string;
|
|
8
|
+
role: string | null;
|
|
9
|
+
ariaLive: string | null;
|
|
10
|
+
message: string;
|
|
11
|
+
detail: string | null;
|
|
12
|
+
messageClass: string | null;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const uiState: {
|
|
16
|
+
lastSnapshot: unknown;
|
|
17
|
+
specEvidenceDetail: {
|
|
18
|
+
source: string;
|
|
19
|
+
path: string;
|
|
20
|
+
loading: boolean;
|
|
21
|
+
error: string | null;
|
|
22
|
+
data: unknown;
|
|
23
|
+
triggerId: string | null;
|
|
24
|
+
} | null;
|
|
25
|
+
dagNodeExecutionOutputCache: Map<string, unknown> | null;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function setWorkspaceScope(workspaceId: string | null): void;
|
|
30
|
+
export function workspaceScope(): string | null;
|
|
31
|
+
export function scopedApiUrl(url: string): string;
|
|
32
|
+
export function workspaceRequestSignal(): AbortSignal | undefined;
|
|
33
|
+
export function fetchWithWorkspaceScope(
|
|
34
|
+
url: string,
|
|
35
|
+
init?: RequestInit,
|
|
36
|
+
): Promise<Response>;
|
|
37
|
+
export function abortWorkspaceRequests(): void;
|
|
38
|
+
export function setWorkspaceActive(active: boolean): void;
|
|
39
|
+
export function stopTimers(): void;
|
|
40
|
+
export function pauseForegroundTimers(): void;
|
|
41
|
+
|
|
42
|
+
/** Multi-workspace atomic scope switch (2026-08-26, AC-006). */
|
|
43
|
+
export function applyWorkspaceScopeSwitch(
|
|
44
|
+
nextWorkspaceId: string | null,
|
|
45
|
+
routeValue?: (() => void) | string,
|
|
46
|
+
options?: {
|
|
47
|
+
route?: (hashValue: string) => void;
|
|
48
|
+
onTrace?: (trace: string[]) => void;
|
|
49
|
+
},
|
|
50
|
+
): string[];
|
|
@@ -116,6 +116,8 @@ export const uiState = {
|
|
|
116
116
|
/** Last-rendered spec-evidence list, used to restore the list synchronously. */
|
|
117
117
|
specEvidenceListEvidence: null,
|
|
118
118
|
pollingGeneration: 0,
|
|
119
|
+
/** Hosted Inspect workspace is foreground. Standalone defaults to active. */
|
|
120
|
+
workspaceActive: true,
|
|
119
121
|
};
|
|
120
122
|
|
|
121
123
|
/** Per-dagRunId graph viewport restore map (stable Map instance). */
|
|
@@ -279,16 +281,186 @@ export function isPageVisible() {
|
|
|
279
281
|
);
|
|
280
282
|
}
|
|
281
283
|
|
|
284
|
+
export function isWorkspaceActive() {
|
|
285
|
+
return uiState.workspaceActive !== false;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function setWorkspaceActive(active) {
|
|
289
|
+
uiState.workspaceActive = Boolean(active);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Multi-workspace scope (2026-08-23): every Observe GET must carry the
|
|
294
|
+
* current workspaceId (AC-002/AC-003). The scope is synced from the parent
|
|
295
|
+
* Console shell hash (`?workspaceId=`) or via postMessage for hosted mode;
|
|
296
|
+
* standalone pages default to null and all workspace-scoped routes fail closed
|
|
297
|
+
* until the host or hash publishes an explicit workspace id.
|
|
298
|
+
*/
|
|
299
|
+
let currentWorkspaceScope = null;
|
|
300
|
+
let currentWorkspaceRequestController =
|
|
301
|
+
typeof AbortController === "undefined" ? null : new AbortController();
|
|
302
|
+
|
|
303
|
+
export function setWorkspaceScope(workspaceId) {
|
|
304
|
+
currentWorkspaceScope =
|
|
305
|
+
typeof workspaceId === "string" && workspaceId.trim()
|
|
306
|
+
? workspaceId.trim()
|
|
307
|
+
: null;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function workspaceScope() {
|
|
311
|
+
return currentWorkspaceScope;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Signal shared by every workspace-scoped Observe request in the active scope. */
|
|
315
|
+
export function workspaceRequestSignal() {
|
|
316
|
+
if (
|
|
317
|
+
typeof AbortController !== "undefined" &&
|
|
318
|
+
(!currentWorkspaceRequestController ||
|
|
319
|
+
currentWorkspaceRequestController.signal.aborted)
|
|
320
|
+
) {
|
|
321
|
+
currentWorkspaceRequestController = new AbortController();
|
|
322
|
+
}
|
|
323
|
+
return currentWorkspaceRequestController?.signal;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function combinedRequestSignal(scopeSignal, requestSignal) {
|
|
327
|
+
const signals = [scopeSignal, requestSignal].filter(Boolean);
|
|
328
|
+
if (signals.length <= 1) return { signal: signals[0], cleanup: () => {} };
|
|
329
|
+
const controller = new AbortController();
|
|
330
|
+
const abort = () => controller.abort();
|
|
331
|
+
for (const signal of signals) {
|
|
332
|
+
if (signal.aborted) abort();
|
|
333
|
+
else signal.addEventListener("abort", abort, { once: true });
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
signal: controller.signal,
|
|
337
|
+
cleanup: () => {
|
|
338
|
+
for (const signal of signals) signal.removeEventListener("abort", abort);
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Fetch through the current workspace boundary and abort on any scope swap. */
|
|
344
|
+
export async function fetchWithWorkspaceScope(url, init = {}) {
|
|
345
|
+
const { signal: requestSignal, ...rest } = init;
|
|
346
|
+
const combined = combinedRequestSignal(
|
|
347
|
+
workspaceRequestSignal(),
|
|
348
|
+
requestSignal,
|
|
349
|
+
);
|
|
350
|
+
try {
|
|
351
|
+
return await fetch(scopedApiUrl(url), {
|
|
352
|
+
...rest,
|
|
353
|
+
...(combined.signal ? { signal: combined.signal } : {}),
|
|
354
|
+
});
|
|
355
|
+
} finally {
|
|
356
|
+
combined.cleanup();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** Abort every old-scope request and invalidate request identity guards. */
|
|
361
|
+
export function abortWorkspaceRequests() {
|
|
362
|
+
currentWorkspaceRequestController?.abort();
|
|
363
|
+
currentWorkspaceRequestController =
|
|
364
|
+
typeof AbortController === "undefined" ? null : new AbortController();
|
|
365
|
+
uiState.dagHistoryAbortController?.abort?.();
|
|
366
|
+
uiState.dagHistoryAbortController = null;
|
|
367
|
+
uiState.dagHistoryRequestSeq += 1;
|
|
368
|
+
uiState.dagHistoryPrefetchGeneration += 1;
|
|
369
|
+
uiState.dagNodeInputRequestSeq += 1;
|
|
370
|
+
uiState.dagNodeProcessRequestSeq += 1;
|
|
371
|
+
uiState.dagNodeExecutionOutputRequestSeq += 1;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** Multi-workspace atomic scope switch (2026-08-26, AC-006).
|
|
375
|
+
*
|
|
376
|
+
* Contract order — strictly sequential, no interleaving:
|
|
377
|
+
* 1. abort old — stop every poll/SSE so no late request can race the swap;
|
|
378
|
+
* 2. clear old — drop cached run/task/selection state of the old scope;
|
|
379
|
+
* 3. set scope — publish the new workspaceId for scopedApiUrl;
|
|
380
|
+
* 4. reload new — re-route/re-render with the new scope active.
|
|
381
|
+
*
|
|
382
|
+
* Observability: each stage appends to the returned trace so tests (and
|
|
383
|
+
* diagnostics) can assert the exact ordering; there is no window in which a
|
|
384
|
+
* new route is requested with the old scope or vice versa.
|
|
385
|
+
*/
|
|
386
|
+
export function applyWorkspaceScopeSwitch(
|
|
387
|
+
nextWorkspaceId,
|
|
388
|
+
routeValue,
|
|
389
|
+
options = {},
|
|
390
|
+
) {
|
|
391
|
+
const trace = [];
|
|
392
|
+
// 1. abort old
|
|
393
|
+
abortWorkspaceRequests();
|
|
394
|
+
stopTimers();
|
|
395
|
+
pauseForegroundTimers();
|
|
396
|
+
trace.push("abort-old");
|
|
397
|
+
// 2. clear old
|
|
398
|
+
uiState.lastSnapshot = null;
|
|
399
|
+
uiState.specEvidenceDetail = null;
|
|
400
|
+
uiState.specEvidenceListEvidence = null;
|
|
401
|
+
clearDagNodeExecutionOutputCache();
|
|
402
|
+
trace.push("clear-old");
|
|
403
|
+
// 3. set scope
|
|
404
|
+
setWorkspaceScope(nextWorkspaceId);
|
|
405
|
+
trace.push(`set-scope:${workspaceScope() ?? ""}`);
|
|
406
|
+
// 4. route/reload new
|
|
407
|
+
if (typeof routeValue === "function") routeValue();
|
|
408
|
+
else if (typeof routeValue === "string") options.route?.(routeValue);
|
|
409
|
+
trace.push("route-new");
|
|
410
|
+
if (options.onTrace) options.onTrace(trace);
|
|
411
|
+
return trace;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Append ?workspaceId= to an observe API URL (real request path kept). */
|
|
415
|
+
export function scopedApiUrl(url) {
|
|
416
|
+
const raw = String(url ?? "");
|
|
417
|
+
if (!currentWorkspaceScope || !raw.startsWith("/api/")) return raw;
|
|
418
|
+
const qIndex = raw.indexOf("?");
|
|
419
|
+
if (qIndex >= 0) {
|
|
420
|
+
const params = new URLSearchParams(raw.slice(qIndex + 1));
|
|
421
|
+
if (params.has("workspaceId")) return raw;
|
|
422
|
+
params.set("workspaceId", currentWorkspaceScope);
|
|
423
|
+
return `${raw.slice(0, qIndex)}?${params.toString()}`;
|
|
424
|
+
}
|
|
425
|
+
return `${raw}?workspaceId=${encodeURIComponent(currentWorkspaceScope)}`;
|
|
426
|
+
}
|
|
427
|
+
|
|
282
428
|
export function detailPollDelay(status, isVisible) {
|
|
283
429
|
const normalizedStatus = (status ?? "").toLowerCase().replace(/-/g, "_");
|
|
284
430
|
if (TERMINAL_RUN_STATUSES.has(normalizedStatus)) return null;
|
|
431
|
+
if (!isWorkspaceActive()) return null;
|
|
285
432
|
return isVisible ? ACTIVE_DETAIL_POLL_MS : HIDDEN_POLL_MS;
|
|
286
433
|
}
|
|
287
434
|
|
|
288
435
|
export function dashboardPollDelay() {
|
|
436
|
+
if (!isWorkspaceActive()) return null;
|
|
289
437
|
return isPageVisible() ? DASHBOARD_POLL_MS : HIDDEN_POLL_MS;
|
|
290
438
|
}
|
|
291
439
|
|
|
440
|
+
/** Stop pausable timers without destroying route/selection/scroll. */
|
|
441
|
+
export function pauseForegroundTimers() {
|
|
442
|
+
if (uiState.dashboardTimer) {
|
|
443
|
+
clearTimeout(uiState.dashboardTimer);
|
|
444
|
+
uiState.dashboardTimer = null;
|
|
445
|
+
}
|
|
446
|
+
if (uiState.runPollTimer) {
|
|
447
|
+
clearTimeout(uiState.runPollTimer);
|
|
448
|
+
uiState.runPollTimer = null;
|
|
449
|
+
}
|
|
450
|
+
if (uiState.dagPollTimer) {
|
|
451
|
+
clearTimeout(uiState.dagPollTimer);
|
|
452
|
+
uiState.dagPollTimer = null;
|
|
453
|
+
}
|
|
454
|
+
if (uiState.poolTimer) {
|
|
455
|
+
clearTimeout(uiState.poolTimer);
|
|
456
|
+
uiState.poolTimer = null;
|
|
457
|
+
}
|
|
458
|
+
if (uiState.taskPollTimer) {
|
|
459
|
+
clearTimeout(uiState.taskPollTimer);
|
|
460
|
+
uiState.taskPollTimer = null;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
292
464
|
export function updateDagGraphViewportState(
|
|
293
465
|
_previous,
|
|
294
466
|
dagRunId,
|
|
@@ -25,6 +25,7 @@ import { describeDagNodePurpose } from "../dag-node-purpose.js";
|
|
|
25
25
|
import { buildPromptRestartCandidateOptions } from "../prompt-restart-candidates.js";
|
|
26
26
|
import { copyText } from "../copy.js";
|
|
27
27
|
import {
|
|
28
|
+
fetchWithWorkspaceScope,
|
|
28
29
|
uiState,
|
|
29
30
|
makeSessionEventIdentity,
|
|
30
31
|
makeDagNodeInputIdentity,
|
|
@@ -1286,7 +1287,7 @@ export function frontendGateLedgerLines(input) {
|
|
|
1286
1287
|
/** DAG run 专属 prewrite-result 只读拉取(内联 fetch,不新增 api.js 依赖)。 */
|
|
1287
1288
|
async function fetchPrewriteResultJson(dagRunId) {
|
|
1288
1289
|
try {
|
|
1289
|
-
const res = await
|
|
1290
|
+
const res = await fetchWithWorkspaceScope(
|
|
1290
1291
|
`/api/dag-runs/${encodeURIComponent(dagRunId)}/prewrite-result`,
|
|
1291
1292
|
{ credentials: "same-origin" },
|
|
1292
1293
|
);
|
|
@@ -2012,7 +2013,7 @@ function effectiveExecutionKey(dagRunId, node) {
|
|
|
2012
2013
|
async function fetchExecutionOutput(dagRunId, nodeId, key) {
|
|
2013
2014
|
const url = `/api/dag-runs/${encodeURIComponent(dagRunId)}/nodes/${encodeURIComponent(nodeId)}/execution-output?key=${encodeURIComponent(key)}`;
|
|
2014
2015
|
try {
|
|
2015
|
-
const res = await
|
|
2016
|
+
const res = await fetchWithWorkspaceScope(url);
|
|
2016
2017
|
let body = null;
|
|
2017
2018
|
try {
|
|
2018
2019
|
body = await res.json();
|
|
@@ -364,7 +364,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
|
|
|
364
364
|
"page-action-btn",
|
|
365
365
|
"在操作台中止此运行 →",
|
|
366
366
|
);
|
|
367
|
-
interruptLink.href = `/#/recovery?dagRunId=${encodeURIComponent(dag.dagRunId)}&intent=interrupt`;
|
|
367
|
+
interruptLink.href = `/#/operate/recovery?dagRunId=${encodeURIComponent(dag.dagRunId)}&intent=interrupt`;
|
|
368
368
|
interruptLink.setAttribute("data-testid", "inspect-dag-interrupt-link");
|
|
369
369
|
interruptLink.title = "只跳转到操作台 Recovery,不会在观测页执行中止";
|
|
370
370
|
primaryEntries.push(["协作中止", interruptLink]);
|
|
@@ -482,6 +482,7 @@ export function startDagPolling(dagRunId, initial = true) {
|
|
|
482
482
|
const active = await renderDagDetail(dagRunId, isInitial);
|
|
483
483
|
if (generation !== uiState.pollingGeneration || !active) return;
|
|
484
484
|
const delay = detailPollDelay("running", isPageVisible());
|
|
485
|
+
if (delay == null) return;
|
|
485
486
|
uiState.dagPollTimer = setTimeout(() => {
|
|
486
487
|
uiState.dagPollTimer = null;
|
|
487
488
|
void poll(false);
|
|
@@ -84,7 +84,7 @@ let dashboardLoadingNode = null;
|
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* 「昨夜班次」条带:夜间结果在观测侧的唯一一级呈现(替代旧「夜间任务」tab)。
|
|
87
|
-
* 管理动作(晨审处置)始终落在操作侧 /#/night,保持 Inspect 只读不变式。
|
|
87
|
+
* 管理动作(晨审处置)始终落在操作侧 /#/operate/night,保持 Inspect 只读不变式。
|
|
88
88
|
*/
|
|
89
89
|
async function renderNightStrip() {
|
|
90
90
|
const strip = document.getElementById("dashboard-night");
|
|
@@ -118,14 +118,14 @@ async function renderNightStrip() {
|
|
|
118
118
|
|
|
119
119
|
const actions = el("div", "night-strip-actions");
|
|
120
120
|
const detail = el("a", "page-action-btn", "夜间详情");
|
|
121
|
-
detail.href = "
|
|
121
|
+
detail.href = "/#/inspect/night";
|
|
122
122
|
detail.addEventListener("click", (e) => {
|
|
123
123
|
e.preventDefault();
|
|
124
124
|
navigate("/night");
|
|
125
125
|
});
|
|
126
126
|
actions.appendChild(detail);
|
|
127
127
|
const manage = el("a", "page-action-btn night-strip-manage", "晨审处置 →");
|
|
128
|
-
manage.href = "/#/night";
|
|
128
|
+
manage.href = "/#/operate/night";
|
|
129
129
|
manage.title = "夜间计划的管理与晨审处置在操作台完成(Inspect 保持只读)";
|
|
130
130
|
actions.appendChild(manage);
|
|
131
131
|
strip.appendChild(actions);
|
|
@@ -738,10 +738,12 @@ export function startDashboardPolling(scrollTo) {
|
|
|
738
738
|
const poll = async (initialScrollTo) => {
|
|
739
739
|
await renderDashboard(initialScrollTo);
|
|
740
740
|
if (generation !== uiState.pollingGeneration) return;
|
|
741
|
+
const delay = dashboardPollDelay();
|
|
742
|
+
if (delay == null) return;
|
|
741
743
|
uiState.dashboardTimer = setTimeout(() => {
|
|
742
744
|
uiState.dashboardTimer = null;
|
|
743
745
|
void poll();
|
|
744
|
-
},
|
|
746
|
+
}, delay);
|
|
745
747
|
};
|
|
746
748
|
void poll(scrollTo);
|
|
747
749
|
}
|
|
@@ -46,8 +46,8 @@ export async function renderNightJobs(scheduleId) {
|
|
|
46
46
|
showView("night");
|
|
47
47
|
bindNightToolbar();
|
|
48
48
|
const crumbs = [
|
|
49
|
-
{ label: UI_TEXT.dashboard, href: "
|
|
50
|
-
{ label: UI_TEXT.nightJobs, href: "
|
|
49
|
+
{ label: UI_TEXT.dashboard, href: "/#/inspect" },
|
|
50
|
+
{ label: UI_TEXT.nightJobs, href: "/#/inspect/night" },
|
|
51
51
|
];
|
|
52
52
|
if (scheduleId) crumbs.push({ label: scheduleId });
|
|
53
53
|
setBreadcrumb(crumbs);
|
|
@@ -93,6 +93,7 @@ function startPoolAutoPolling() {
|
|
|
93
93
|
if (generation !== uiState.pollingGeneration) return;
|
|
94
94
|
if (!poolAutoRefreshEnabled()) return;
|
|
95
95
|
const delay = isPageVisible() ? POOL_POLL_MS : dashboardPollDelay();
|
|
96
|
+
if (delay == null) return;
|
|
96
97
|
uiState.poolTimer = setTimeout(() => {
|
|
97
98
|
uiState.poolTimer = null;
|
|
98
99
|
void poll();
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
} from "../relations.js";
|
|
51
51
|
import { copyText, renderRecommendedCommand } from "../copy.js";
|
|
52
52
|
import {
|
|
53
|
+
fetchWithWorkspaceScope,
|
|
53
54
|
isPageVisible,
|
|
54
55
|
detailPollDelay,
|
|
55
56
|
dashboardPollDelay,
|
|
@@ -126,7 +127,7 @@ export function renderInlineArtifactList(container, artifacts) {
|
|
|
126
127
|
list.appendChild(li);
|
|
127
128
|
void (async () => {
|
|
128
129
|
try {
|
|
129
|
-
const res = await
|
|
130
|
+
const res = await fetchWithWorkspaceScope(artifactUrl(artifactPath));
|
|
130
131
|
const text = await res.text();
|
|
131
132
|
if (!res.ok) {
|
|
132
133
|
let message = text;
|
|
@@ -444,6 +445,7 @@ export function startRunPolling(workerRunId, initial = true) {
|
|
|
444
445
|
const active = await renderRun(workerRunId, isInitial);
|
|
445
446
|
if (generation !== uiState.pollingGeneration || !active) return;
|
|
446
447
|
const delay = detailPollDelay("running", isPageVisible());
|
|
448
|
+
if (delay == null) return;
|
|
447
449
|
uiState.runPollTimer = setTimeout(() => {
|
|
448
450
|
uiState.runPollTimer = null;
|
|
449
451
|
void poll(false);
|
|
@@ -86,7 +86,7 @@ export async function renderTaskDetail(featureId, taskId) {
|
|
|
86
86
|
showView("task");
|
|
87
87
|
setBreadcrumb([
|
|
88
88
|
{ label: UI_TEXT.dashboard, href: "#/" },
|
|
89
|
-
{ label: "资源池", href: "
|
|
89
|
+
{ label: "资源池", href: "/#/inspect/pool" },
|
|
90
90
|
{ label: displayLabel },
|
|
91
91
|
]);
|
|
92
92
|
|
|
@@ -258,13 +258,14 @@ function bounded(value) {
|
|
|
258
258
|
? normalized
|
|
259
259
|
: `${normalized.slice(0, MAX_DIAGNOSTIC_CHARS)}\n...[truncated]`;
|
|
260
260
|
}
|
|
261
|
-
function collectionItems(stdout) {
|
|
261
|
+
function collectionItems(stdout, layout) {
|
|
262
|
+
const rootPrefix = `${(layout ?? resolveBackendTestLayout(undefined)).testRoot}/`;
|
|
262
263
|
return [...new Set(stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => {
|
|
263
264
|
if (!line.includes("::"))
|
|
264
265
|
return false;
|
|
265
266
|
if (/^(ERROR|FAILED|E\s+)/.test(line))
|
|
266
267
|
return false;
|
|
267
|
-
return
|
|
268
|
+
return line.replaceAll("\\", "/").startsWith(rootPrefix);
|
|
268
269
|
}).map((line) => line.replaceAll("\\", "/")))];
|
|
269
270
|
}
|
|
270
271
|
function escapeRegExp(value) {
|
|
@@ -416,7 +417,7 @@ function classifyCollectionFailure(output, evidence) {
|
|
|
416
417
|
return { status: "BLOCKED", kind: "unclassified-collection-error", detail: "collection failure cannot be safely attributed to generated testcase assets" };
|
|
417
418
|
}
|
|
418
419
|
export function assessBackendPytestCollection(input) {
|
|
419
|
-
const items = collectionItems(input.stdout);
|
|
420
|
+
const items = collectionItems(input.stdout, input.layout);
|
|
420
421
|
const fixtureResolution = input.fixtureResolution ?? { exitCode: 0, stdout: "fixture resolution assumed by direct assessor", stderr: "" };
|
|
421
422
|
if (input.exitCode === 0 && fixtureResolution.exitCode === 0) {
|
|
422
423
|
return backendPytestCollectionFactsSchema.parse({
|
|
@@ -740,7 +741,7 @@ export async function materializeBackendTestExecutionReadiness(input) {
|
|
|
740
741
|
if (input.effective.phase !== "effective" || input.effective.status !== "PASS" || input.effective.fixtureResolutionStatus !== "PASS") {
|
|
741
742
|
throw new Error("backend-test execution readiness requires effective collection and fixture-resolution PASS");
|
|
742
743
|
}
|
|
743
|
-
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.effective.mappedScripts);
|
|
744
|
+
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.effective.mappedScripts, { layout: input.layout });
|
|
744
745
|
assertSameInventory(input.effective, current);
|
|
745
746
|
const eligibility = input.eligibility ?? { eligibleItemIds: input.effective.collectedItemIds, excludedItems: [] };
|
|
746
747
|
const status = eligibility.eligibleItemIds.length === 0
|
|
@@ -839,7 +840,7 @@ async function firstUnreadableAssetPath(workspaceRoot, readiness) {
|
|
|
839
840
|
}
|
|
840
841
|
return undefined;
|
|
841
842
|
}
|
|
842
|
-
export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, readiness) {
|
|
843
|
+
export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, readiness, layout) {
|
|
843
844
|
if (!["PASS", "PARTIAL"].includes(readiness.status)) {
|
|
844
845
|
const counts = formatReadinessCounts(readiness);
|
|
845
846
|
const reasonTally = readiness.eligibleItemIds.length === 0 && readiness.excludedItems.length > 0
|
|
@@ -862,7 +863,7 @@ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, re
|
|
|
862
863
|
}
|
|
863
864
|
let current;
|
|
864
865
|
try {
|
|
865
|
-
current = await buildBackendPytestAssetInventory(workspaceRoot, readiness.mappedScripts);
|
|
866
|
+
current = await buildBackendPytestAssetInventory(workspaceRoot, readiness.mappedScripts, { layout });
|
|
866
867
|
}
|
|
867
868
|
catch {
|
|
868
869
|
const fallbackPath = [...readiness.mappedScripts].sort()[0] ?? Object.keys(readiness.assetHashes).sort()[0] ?? "unknown";
|
|
@@ -897,11 +898,11 @@ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, re
|
|
|
897
898
|
}
|
|
898
899
|
}
|
|
899
900
|
}
|
|
900
|
-
export async function assertBackendPytestCollectionFresh(workspaceRoot, effective) {
|
|
901
|
+
export async function assertBackendPytestCollectionFresh(workspaceRoot, effective, layout) {
|
|
901
902
|
if (effective.phase !== "effective" || effective.status !== "PASS") {
|
|
902
903
|
throw new Error("backend pytest execution requires effective collection PASS facts");
|
|
903
904
|
}
|
|
904
|
-
const current = await buildBackendPytestAssetInventory(workspaceRoot, effective.mappedScripts);
|
|
905
|
+
const current = await buildBackendPytestAssetInventory(workspaceRoot, effective.mappedScripts, { layout });
|
|
905
906
|
const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
|
|
906
907
|
if (priorityOnly.length > 0)
|
|
907
908
|
throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
|
|
@@ -909,7 +910,7 @@ export async function assertBackendPytestCollectionFresh(workspaceRoot, effectiv
|
|
|
909
910
|
}
|
|
910
911
|
export async function materializeEffectiveBackendPytestCollection(input) {
|
|
911
912
|
if (input.initial.status === "PASS") {
|
|
912
|
-
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.initial.mappedScripts);
|
|
913
|
+
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.initial.mappedScripts, { layout: input.layout });
|
|
913
914
|
const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
|
|
914
915
|
if (priorityOnly.length > 0)
|
|
915
916
|
throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
|
|
@@ -927,7 +928,7 @@ export async function materializeEffectiveBackendPytestCollection(input) {
|
|
|
927
928
|
if (input.final.status !== "PASS")
|
|
928
929
|
throw new Error("backend pytest collection still fails after bounded repair");
|
|
929
930
|
await assertBackendPytestRepairSafety(input.workspaceRoot, input.initial, input.final);
|
|
930
|
-
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.final.mappedScripts);
|
|
931
|
+
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.final.mappedScripts, { layout: input.layout });
|
|
931
932
|
const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
|
|
932
933
|
if (priorityOnly.length > 0)
|
|
933
934
|
throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { watch } from "node:fs";
|
|
2
|
-
import { mkdir
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
3
|
import { hostname as localHostname } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { writeJsonAtomic } from "../../infrastructure/harness/atomic-write.js";
|
|
5
|
+
import { readJsonWithTransientRetry, writeJsonAtomic, } from "../../infrastructure/harness/atomic-write.js";
|
|
6
6
|
import { assessDagRunLiveness, getDagRunDir, locateDagRun, readDagRunState, } from "./lifecycle.js";
|
|
7
7
|
export const INTERRUPT_ARTIFACT_REL = path.posix.join(".runtime", "interrupt.json");
|
|
8
8
|
export const INTERRUPT_REASON_CODES = [
|
|
@@ -140,7 +140,7 @@ export function parseInterruptRequest(raw) {
|
|
|
140
140
|
}
|
|
141
141
|
export async function readInterruptRequest(runDir) {
|
|
142
142
|
try {
|
|
143
|
-
const raw =
|
|
143
|
+
const raw = await readJsonWithTransientRetry(interruptArtifactPath(runDir));
|
|
144
144
|
return parseInterruptRequest(raw);
|
|
145
145
|
}
|
|
146
146
|
catch (error) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { access, mkdir, readFile, readdir, rename } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { hostname as localHostname } from "node:os";
|
|
4
|
-
import { writeJsonAtomic, } from "../../infrastructure/harness/atomic-write.js";
|
|
4
|
+
import { readJsonWithTransientRetry, writeJsonAtomic, } from "../../infrastructure/harness/atomic-write.js";
|
|
5
5
|
import { parseDagSpec } from "./types.js";
|
|
6
6
|
import { normalizeDagFailureCategory, } from "./failure-category.js";
|
|
7
7
|
import { dagProductLineFailureCategoryValues, routeDagFailure, } from "./failure-routing.js";
|
|
@@ -43,14 +43,14 @@ export async function dagRunDirExists(runDir) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
export async function readDagRunState(runDir) {
|
|
46
|
-
const raw =
|
|
46
|
+
const raw = await readJsonWithTransientRetry(path.join(runDir, "state.json"));
|
|
47
47
|
return raw;
|
|
48
48
|
}
|
|
49
49
|
export async function writeDagRunState(runDir, state, options) {
|
|
50
50
|
await writeJsonAtomic(path.join(runDir, "state.json"), state, options);
|
|
51
51
|
}
|
|
52
52
|
export async function readDagRunSpec(runDir) {
|
|
53
|
-
const raw =
|
|
53
|
+
const raw = await readJsonWithTransientRetry(path.join(runDir, "run.json"));
|
|
54
54
|
return parseDagSpec(raw);
|
|
55
55
|
}
|
|
56
56
|
export async function locateDagRun(cwd, runId) {
|
package/docs/README.md
CHANGED
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
| `design/active/` | 仍会影响后续决策的设计输入、路线与契约 |
|
|
74
74
|
| `design/visual-references/` | 长期视觉参考,不表达实现状态 |
|
|
75
75
|
| `design/archive/` | 历史设计和已被实现/替代的阶段性设计 |
|
|
76
|
+
| `superpowers/specs/` | Superpowers 工作流产出的阶段性实现设计输入 |
|
|
76
77
|
| `exec-plans/active/` | 仍需推进或明确保持 open 的任务合同 |
|
|
77
78
|
| `exec-plans/completed/` | 已完成任务合同归档 |
|
|
78
79
|
| `progress/` | 仍需下一次会话接手的当前 handoff 入口 |
|
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
本文记录仅与特定开发环境有关、但可能反复影响验证结果的问题。它不是通用工程规则;标准验证命令仍以 [`verification-matrix.md`](../governance/verification-matrix.md) 为准。
|
|
4
4
|
|
|
5
|
+
## Operator Console 前端快速迭代
|
|
6
|
+
|
|
7
|
+
对 `src/worker/console/static-src/` 内的对话样式和前端交互做高频调整时,使用固定 8790 的开发入口:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run console:dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
它从当前源码启动真实 Console 后端,并在内部 `8791` 常驻 Vite dev server。浏览器始终访问 `http://127.0.0.1:8790/`:API、HttpOnly Cookie、确认令牌和 Origin 校验仍由真实 Console 处理,前端 HTML/模块请求才由 8790 转发给 Vite。CSS 保存后原地热替换,TSX 保存后自动整页刷新;不生成 `static-dev` bundle,也不重复运行生产 build。
|
|
14
|
+
|
|
15
|
+
常用参数:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm run console:dev -- --no-open
|
|
19
|
+
npm run console:dev -- --port 8792 --reload-port 8793 --no-open
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
默认端口是 Console `8790`、内部 Vite/HMR `8791`;两者都只允许 loopback。端口已占用时命令会失败并报告端口,不会停止或接管已有进程。前端类型检查在后台持续输出诊断,但不阻塞 HMR;后端源码变化时只重启 Console 子进程,Vite 保持常驻。
|
|
23
|
+
|
|
24
|
+
该命令只优化编辑反馈,不构成验收。独立交互修复完成后仍需运行定向 Vitest;交付前按验证矩阵运行 typecheck、正式 `npm run console:build` / `npm run build`。正式构建继续写入 `dist/worker/console/static/`,不会包含 `/@vite/client`、8791 或开发代理代码。
|
|
25
|
+
|
|
5
26
|
## Git hooks(本仓库)
|
|
6
27
|
|
|
7
28
|
每个 clone 安装一次:
|
package/harness.json
CHANGED
|
@@ -82,9 +82,9 @@
|
|
|
82
82
|
"executors": {
|
|
83
83
|
"pi": {
|
|
84
84
|
"description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,支持 provider/model 字符串或带 thinking 的对象;斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
|
|
85
|
-
"LOW": "
|
|
86
|
-
|
|
87
|
-
"HIGH": "
|
|
85
|
+
"LOW": "wizard-local/minimax-m3",
|
|
86
|
+
"MED": "wizard-local/glm-5.3",
|
|
87
|
+
"HIGH": "wizard-local/gpt-5.6-sol"
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tea-agent/loop-agent",
|
|
3
|
-
"version": "0.40.0-next.
|
|
3
|
+
"version": "0.40.0-next.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"build": "npm run brand:sync && npm run clean && tsc -p tsconfig.build.json && node -e \"const fs=require('node:fs');const p='dist/worker/observe/static';fs.mkdirSync(p,{recursive:true});fs.cpSync('src/worker/observe/static',p,{recursive:true});\" && npm run console:build && node scripts/write-build-stamp.mjs",
|
|
55
55
|
"console:typecheck": "tsc -p src/worker/console/tsconfig.json",
|
|
56
56
|
"console:build": "npm run console:typecheck && vite build --config src/worker/console/vite.config.ts",
|
|
57
|
+
"console:dev": "node --import tsx/esm scripts/console-dev.mjs",
|
|
57
58
|
"prepack": "npm run build",
|
|
58
59
|
"prepublishOnly": "node scripts/check-npm-publish-policy.mjs && npm run typecheck && npm test && npm run build",
|
|
59
60
|
"lint": "npm run typecheck",
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
"verify:tree": "node scripts/pre-push-verify.mjs --verify-current-tree"
|
|
72
73
|
},
|
|
73
74
|
"dependencies": {
|
|
75
|
+
"@deepseek-ai/dsh-host-directory-picker-native": "0.1.1-rc.2",
|
|
74
76
|
"@earendil-works/pi-ai": "0.83.0",
|
|
75
77
|
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
76
78
|
"commander": "^12.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{ag as o,ah as n}from"./mermaid.core-Biyo-tqA.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-TJ5JuEBT.js";import{_ as i}from"./mermaid.core-Biyo-tqA.js";import"./chunk-5VM5RSS4-JCNGkXYT.js";import"./chunk-XXDRQBXY-By9VQoi1.js";import"./chunk-KBJHAD2P-D60-Mny4.js";import"./chunk-2GRJ4B5K-wRO_iRNc.js";import"./index-CW88Fjbw.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-TJ5JuEBT.js";import{_ as i}from"./mermaid.core-Biyo-tqA.js";import"./chunk-5VM5RSS4-JCNGkXYT.js";import"./chunk-XXDRQBXY-By9VQoi1.js";import"./chunk-KBJHAD2P-D60-Mny4.js";import"./chunk-2GRJ4B5K-wRO_iRNc.js";import"./index-CW88Fjbw.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
|