@tea-agent/loop-agent 0.33.6 → 0.33.7-beta.0

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +23 -23
  2. package/dist/application/task-lifecycle/advance.js +4 -254
  3. package/dist/application/task-lifecycle/gates.js +0 -50
  4. package/dist/application/task-lifecycle/observe.js +2 -11
  5. package/dist/commands/init-upgrade.js +1 -32
  6. package/dist/commands/init.js +3 -94
  7. package/dist/executors/shell-executor.js +91 -4
  8. package/dist/executors/shell-write-guard.js +8 -26
  9. package/dist/shared/operator/capabilities.js +42 -72
  10. package/dist/task/source-prepare/index.js +0 -2
  11. package/dist/task/source-prepare/parse-intent.js +10 -58
  12. package/dist/task/source-prepare/prepare.js +16 -180
  13. package/dist/task/source-prepare/reference-integrity.js +2 -18
  14. package/dist/worker/console/app-data.js +0 -2
  15. package/dist/worker/console/chat/chat-event-store.js +25 -190
  16. package/dist/worker/console/chat/instruction-skills.js +217 -0
  17. package/dist/worker/console/chat/pi-console-config.js +32 -250
  18. package/dist/worker/console/chat/pi-runtime.js +71 -625
  19. package/dist/worker/console/chat/resource-loader.js +4 -5
  20. package/dist/worker/console/chat/routes.js +146 -324
  21. package/dist/worker/console/chat/runtime-context.js +12 -48
  22. package/dist/worker/console/chat/runtime-selection.js +0 -59
  23. package/dist/worker/console/chat/shortcuts.js +0 -1
  24. package/dist/worker/console/chat/tool-adapter.js +3 -9
  25. package/dist/worker/console/chat/tools.js +1 -5
  26. package/dist/worker/console/operator-actions.js +68 -559
  27. package/dist/worker/console/server.js +15 -8
  28. package/dist/worker/console/static/assets/index-CnUXAqxG.css +1 -0
  29. package/dist/worker/console/static/assets/index-CteJFFL2.js +29 -0
  30. package/dist/worker/console/static/index.html +2 -2
  31. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +8 -45
  32. package/dist/worker/console/static-src/operator-chat/refs.js +0 -9
  33. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +0 -16
  34. package/dist/worker/console/static-src/operator-chat/useChatStream.js +184 -210
  35. package/dist/worker/console/static-src/operator-chat/useChatThread.js +5 -49
  36. package/dist/worker/console/static-src/operator-chat/useComposer.js +0 -17
  37. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +74 -225
  38. package/dist/worker/delivery/final-verification.js +5 -13
  39. package/dist/worker/delivery/package.js +19 -31
  40. package/dist/worker/delivery/verification-bundle.js +4 -6
  41. package/dist/worker/observe/static/operator-chrome.css +2 -5
  42. package/dist/worker/observe/static/operator-chrome.js +1 -6
  43. package/dist/worker/observe/static/styles.css +9 -39
  44. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +462 -33
  45. package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
  46. package/dist/workflows/dag/backend-test-markdown-workflow.js +25 -1
  47. package/dist/workflows/dag/backend-test-module-stem.js +5 -0
  48. package/dist/workflows/dag/backend-test-pytest-collection.js +345 -24
  49. package/dist/workflows/dag/backend-test-scenario-param.js +269 -82
  50. package/dist/workflows/dag/backend-test-writer-completeness.js +47 -16
  51. package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
  52. package/dist/workflows/dag/frontend-worktree-diff.js +27 -12
  53. package/dist/workflows/dag/init-hybrid.js +46 -34
  54. package/dist/workflows/dag/types.js +7 -0
  55. package/dist/workflows/dag/workspace-checkpoint.js +27 -8
  56. package/docs/templates/backend-test-dag.json +32 -29
  57. package/harness.json +1 -1
  58. package/package.json +1 -1
  59. package/skills/loop-agent/references/command-reference.md +1 -3
  60. package/skills/loop-agent/references/source-and-plan-practice.md +0 -13
  61. package/skills/loop-agent/references/task-workflow.md +0 -4
  62. package/dist/shared/resilient-git.js +0 -133
  63. package/dist/task/source-prepare/artifact-meta.js +0 -137
  64. package/dist/task/source-prepare/semantic-intake.js +0 -404
  65. package/dist/worker/console/dag-execution-receipt.js +0 -380
  66. package/dist/worker/console/static/assets/index-BUOLppPr.js +0 -28
  67. package/dist/worker/console/static/assets/index-C1KzazY5.css +0 -1
  68. package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +0 -257
  69. package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +0 -196
@@ -6,8 +6,8 @@
6
6
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
7
  <link rel="stylesheet" href="/inspect/operator-chrome.css" />
8
8
  <title>Loop 操作台 · Operator Console</title>
9
- <script type="module" crossorigin src="/assets/index-BUOLppPr.js"></script>
10
- <link rel="stylesheet" crossorigin href="/assets/index-C1KzazY5.css">
9
+ <script type="module" crossorigin src="/assets/index-CteJFFL2.js"></script>
10
+ <link rel="stylesheet" crossorigin href="/assets/index-CnUXAqxG.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="root"></div>
@@ -9,47 +9,20 @@ import { requestId } from "./format.js";
9
9
  * original request would have. `assistantId` is the in-flight assistant
10
10
  * message id to patch for streaming text; reconnect creates one if none. */
11
11
  export function createChatSseEventApplier(deps) {
12
- const { refs, onReconcile, setError, setProcessOpen, setInterview, setHumanGateCards, setArtifactCards, setStreaming, setStreamingAssistantId, setUnread, setOperationCards, setUsage, setMessages, setToolCalls, } = deps;
12
+ const { refs, setError, setProcessOpen, setInterview, setHumanGateCards, setArtifactCards, setStreaming, setStreamingAssistantId, setUnread, setOperationCards, setUsage, setMessages, setToolCalls, } = deps;
13
13
  return (eventName, data, assistantId, options) => {
14
- if (options?.generation !== undefined &&
15
- refs.sessionGenerationRef.current !== options.generation)
16
- return;
17
14
  const replay = options?.replay === true;
18
- if (eventName === "stream_ready")
19
- return;
20
15
  if (eventName === "reconcile") {
21
- // Cursor aged out of the server ring (or the turn changed under us):
22
- // retained history may be incomplete. Surface recovery via the callback
23
- // (reload canonical facts -> new cursor -> reconnect) instead of a fatal
24
- // global error; the snapshot replay frames that follow are still applied
25
- // as ordinary blocks (deduped by eventId, replay text skipped).
16
+ // Cursor aged out of the server ring: history may be incomplete.
17
+ // Surface a non-fatal notice rather than silently rendering a gap.
26
18
  const reason = typeof data.reason === "string" ? data.reason : "cursor_expired";
27
- onReconcile?.({
28
- reason,
29
- ...(typeof data.minSeq === "number" ? { minSeq: data.minSeq } : {}),
30
- ...(typeof data.epoch === "string" ? { epoch: data.epoch } : {}),
31
- ...(typeof data.latestTurnId === "string"
32
- ? { latestTurnId: data.latestTurnId }
33
- : {}),
34
- ...(typeof data.latestEventId === "string"
35
- ? { latestEventId: data.latestEventId }
36
- : data.latestEventId === null
37
- ? { latestEventId: null }
38
- : {}),
39
- });
19
+ setError(`会话事件窗口已过期(${reason}),建议刷新历史或新建会话。`);
40
20
  return;
41
21
  }
42
22
  const payload = data.data && typeof data.data === "object"
43
23
  ? data.data
44
24
  : data;
45
25
  const turnId = typeof data.turnId === "string" ? data.turnId : undefined;
46
- if (turnId &&
47
- (eventName === "agent_start" || eventName === "message_update") &&
48
- refs.settledTurnIdsRef.current.has(turnId)) {
49
- // A delayed start/text frame from a completed turn must not create a
50
- // ghost bubble or set streaming again (M5.4).
51
- return;
52
- }
53
26
  let resolvedAssistantId = assistantId;
54
27
  if (turnId) {
55
28
  const mapped = refs.turnAssistantIdsRef.current.get(turnId);
@@ -129,26 +102,16 @@ export function createChatSseEventApplier(deps) {
129
102
  turnId !== refs.activeTurnIdRef.current) {
130
103
  return;
131
104
  }
132
- if (turnId) {
133
- refs.settledTurnIdsRef.current.delete(turnId);
105
+ if (turnId)
134
106
  refs.activeTurnIdRef.current = turnId;
135
- }
136
- refs.streamingRef.current = true;
137
107
  setStreaming(true);
138
108
  setStreamingAssistantId(resolvedAssistantId);
139
109
  return;
140
110
  }
141
111
  if (eventName === "agent_settled" || eventName === "agent_end") {
142
- if (turnId)
143
- refs.settledTurnIdsRef.current.add(turnId);
144
- // `agent_end` means the SDK run ended, but the Console keeps the only
145
- // GET stream through an idle grace for agent_settled/state reconciliation
146
- // (M4.4). It must not prematurely close the visible turn.
147
- if (eventName === "agent_end")
148
- return;
149
- if (turnId === refs.activeTurnIdRef.current)
150
- refs.activeTurnIdRef.current = null;
151
- refs.streamingRef.current = false;
112
+ // Both are terminal: agent_end = SDK run finished, agent_settled =
113
+ // post-turn continuation idle. Clear streaming and drop an empty
114
+ // placeholder bubble so a settled turn never shows a stuck "…" row.
152
115
  setStreaming(false);
153
116
  setStreamingAssistantId(null);
154
117
  if (eventName === "agent_settled" &&
@@ -7,9 +7,6 @@ export function useChatRefs() {
7
7
  const inlineStreamSessionIdsRef = useRef(new Set());
8
8
  const assistantIdRef = useRef(null);
9
9
  const lastEventIdRef = useRef(null);
10
- const sessionGenerationRef = useRef(0);
11
- const eventsStreamStateRef = useRef(null);
12
- const settledTurnIdsRef = useRef(new Set());
13
10
  const seenEventIdsRef = useRef(new Set());
14
11
  const turnAssistantIdsRef = useRef(new Map());
15
12
  const reconnectAbortRef = useRef(null);
@@ -27,9 +24,6 @@ export function useChatRefs() {
27
24
  inlineStreamSessionIdsRef,
28
25
  assistantIdRef,
29
26
  lastEventIdRef,
30
- sessionGenerationRef,
31
- eventsStreamStateRef,
32
- settledTurnIdsRef,
33
27
  seenEventIdsRef,
34
28
  turnAssistantIdsRef,
35
29
  reconnectAbortRef,
@@ -45,9 +39,6 @@ export function useChatRefs() {
45
39
  inlineStreamSessionIdsRef,
46
40
  assistantIdRef,
47
41
  lastEventIdRef,
48
- sessionGenerationRef,
49
- eventsStreamStateRef,
50
- settledTurnIdsRef,
51
42
  seenEventIdsRef,
52
43
  turnAssistantIdsRef,
53
44
  reconnectAbortRef,
@@ -17,23 +17,12 @@ export function useChatSessions(params) {
17
17
  // newer user choice.
18
18
  const sessionSelectionVersionRef = useRef(0);
19
19
  const resetActiveProjection = useCallback(() => {
20
- // M4.5/M5.2: selection is a hard ownership boundary. Abort every request
21
- // owned by the old projection, then invalidate its async callbacks.
22
- refs.sessionGenerationRef.current += 1;
23
- refs.abortRef.current?.abort();
24
- refs.reconnectAbortRef.current?.abort();
25
- for (const controller of refs.sessionAbortControllersRef.current.values())
26
- controller.abort();
27
- refs.sessionAbortControllersRef.current.clear();
28
- refs.reconnectAbortRef.current = null;
29
- refs.eventsStreamStateRef.current = null;
30
20
  refs.streamingRef.current = false;
31
21
  refs.abortRef.current = null;
32
22
  refs.assistantIdRef.current = null;
33
23
  refs.lastEventIdRef.current = null;
34
24
  refs.seenEventIdsRef.current = new Set();
35
25
  refs.turnAssistantIdsRef.current = new Map();
36
- refs.settledTurnIdsRef.current = new Set();
37
26
  refs.activeTurnIdRef.current = null;
38
27
  resetForNewSession();
39
28
  setInput("");
@@ -135,13 +124,11 @@ export function useChatSessions(params) {
135
124
  sessionId: body.session.sessionId,
136
125
  ...runtimeSelectionFromRecord(body.session),
137
126
  };
138
- resetActiveProjection();
139
127
  refs.sessionRef.current = next;
140
128
  refs.streamingRef.current = Boolean(body.session.activeTurnId);
141
129
  refs.activeTurnIdRef.current = body.session.activeTurnId ?? null;
142
130
  refs.seenEventIdsRef.current = new Set();
143
131
  refs.turnAssistantIdsRef.current = new Map();
144
- refs.settledTurnIdsRef.current = new Set();
145
132
  refs.lastEventIdRef.current = null;
146
133
  setSession(next);
147
134
  refs.assistantIdRef.current = null;
@@ -172,7 +159,6 @@ export function useChatSessions(params) {
172
159
  setPreviews,
173
160
  setInput,
174
161
  applyActivatedSession,
175
- resetActiveProjection,
176
162
  setActivePreviewPath,
177
163
  setError,
178
164
  ]);
@@ -203,7 +189,6 @@ export function useChatSessions(params) {
203
189
  sessionId: body.session.sessionId,
204
190
  ...runtimeSelectionFromRecord(body.session),
205
191
  };
206
- refs.sessionGenerationRef.current += 1;
207
192
  refs.sessionRef.current = restored;
208
193
  // Do not seed Last-Event-ID here: session messages are restored
209
194
  // from the durable store, but tool/gate/operation projections live
@@ -212,7 +197,6 @@ export function useChatSessions(params) {
212
197
  refs.activeTurnIdRef.current = body.session.activeTurnId ?? null;
213
198
  refs.seenEventIdsRef.current = new Set();
214
199
  refs.turnAssistantIdsRef.current = new Map();
215
- refs.settledTurnIdsRef.current = new Set();
216
200
  refs.lastEventIdRef.current = null;
217
201
  setSession(restored);
218
202
  setInput(body.session.composerDraft ?? "");