@tea-agent/loop-agent 0.34.2 → 0.34.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.
Files changed (29) hide show
  1. package/AGENTS.md +7 -2
  2. package/CHANGELOG.md +65 -22
  3. package/dist/application/task-lifecycle/advance.js +5 -1
  4. package/dist/task/source-prepare/index.js +1 -0
  5. package/dist/task/source-prepare/placeholder-paths.js +77 -0
  6. package/dist/task/source-prepare/semantic-intake.js +192 -27
  7. package/dist/worker/console/app-data.js +2 -0
  8. package/dist/worker/console/chat/chat-event-store.js +85 -3
  9. package/dist/worker/console/chat/pi-runtime.js +230 -62
  10. package/dist/worker/console/chat/resource-preferences-store.js +152 -0
  11. package/dist/worker/console/chat/routes.js +401 -18
  12. package/dist/worker/console/chat/turn-execution-registry.js +82 -0
  13. package/dist/worker/console/dag-execution-receipt.js +14 -1
  14. package/dist/worker/console/prd-intake-bridge.js +51 -10
  15. package/dist/worker/console/server.js +4 -0
  16. package/dist/worker/console/static/assets/index-B6Qdbk8V.js +29 -0
  17. package/dist/worker/console/static/assets/index-Bt0NUxcQ.css +1 -0
  18. package/dist/worker/console/static/index.html +2 -2
  19. package/dist/worker/console/static-src/operator-chat/refs.js +24 -0
  20. package/dist/worker/console/static-src/operator-chat/resource-auto-invocation.js +91 -0
  21. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +690 -0
  22. package/dist/worker/console/static-src/operator-chat/turn-submission.js +158 -0
  23. package/dist/worker/console/static-src/operator-chat/useChatStream.js +535 -86
  24. package/dist/workflows/dag/init-hybrid.js +2 -0
  25. package/docs/operations/local-development-environment.md +4 -2
  26. package/docs/templates/branch-merge-report.md +9 -0
  27. package/package.json +3 -2
  28. package/dist/worker/console/static/assets/index-BQkhJpV8.css +0 -1
  29. package/dist/worker/console/static/assets/index-BpuHmlSP.js +0 -29
@@ -8,6 +8,7 @@ import path from "node:path";
8
8
  import { getTaskPaths } from "../../task/runtime.js";
9
9
  import { SEMANTIC_INTAKE_ARTIFACT_REL, } from "../../task/source-prepare/semantic-intake.js";
10
10
  import { extractRequirementFactsFromMarkdown } from "../../task/source-prepare/parse-intent.js";
11
+ import { filterPlaceholderPaths, isNonPlaceholderPath, } from "../../task/source-prepare/placeholder-paths.js";
11
12
  import { emptyDraft } from "./interview/grill-me.js";
12
13
  import { normalizeConsoleWorkflowKind } from "./workflow-kinds.js";
13
14
  function asStringList(value) {
@@ -105,13 +106,13 @@ export function parseEngineeringBoundaryFromParams(p) {
105
106
  if (Array.isArray(value)) {
106
107
  return value
107
108
  .map((item) => (typeof item === "string" ? item.trim() : ""))
108
- .filter(Boolean);
109
+ .filter(isNonPlaceholderPath);
109
110
  }
110
111
  if (typeof value === "string") {
111
112
  return value
112
113
  .split(/[\n,;,;]+/)
113
114
  .map((s) => s.trim())
114
- .filter(Boolean);
115
+ .filter(isNonPlaceholderPath);
115
116
  }
116
117
  return [];
117
118
  };
@@ -176,10 +177,10 @@ export function parseEngineeringBoundaryFromParams(p) {
176
177
  };
177
178
  }
178
179
  export function appendEngineeringCliArgs(args, boundary) {
179
- for (const pathGlob of boundary.allowedPaths ?? []) {
180
+ for (const pathGlob of filterPlaceholderPaths(boundary.allowedPaths)) {
180
181
  args.push("--allowed-path", pathGlob);
181
182
  }
182
- for (const pathGlob of boundary.forbiddenPaths ?? []) {
183
+ for (const pathGlob of filterPlaceholderPaths(boundary.forbiddenPaths)) {
183
184
  args.push("--forbidden-path", pathGlob);
184
185
  }
185
186
  for (const cmd of boundary.verifyCommands ?? []) {
@@ -187,8 +188,10 @@ export function appendEngineeringCliArgs(args, boundary) {
187
188
  }
188
189
  }
189
190
  export function applyEngineeringBoundaryToDraft(draft, boundary) {
190
- if (!(boundary.allowedPaths?.length) &&
191
- !(boundary.forbiddenPaths?.length) &&
191
+ const allowedPaths = filterPlaceholderPaths(boundary.allowedPaths);
192
+ const forbiddenPaths = filterPlaceholderPaths(boundary.forbiddenPaths);
193
+ if (allowedPaths.length === 0 &&
194
+ forbiddenPaths.length === 0 &&
192
195
  !(boundary.verifyCommands?.length)) {
193
196
  return draft;
194
197
  }
@@ -196,11 +199,11 @@ export function applyEngineeringBoundaryToDraft(draft, boundary) {
196
199
  ...draft,
197
200
  constraints: {
198
201
  invariants: draft.constraints?.invariants ?? [],
199
- allowedPaths: boundary.allowedPaths?.length
200
- ? boundary.allowedPaths
202
+ allowedPaths: allowedPaths.length > 0
203
+ ? allowedPaths
201
204
  : (draft.constraints?.allowedPaths ?? []),
202
- forbiddenPaths: boundary.forbiddenPaths?.length
203
- ? boundary.forbiddenPaths
205
+ forbiddenPaths: forbiddenPaths.length > 0
206
+ ? forbiddenPaths
204
207
  : (draft.constraints?.forbiddenPaths ?? []),
205
208
  },
206
209
  verification: {
@@ -253,15 +256,53 @@ export async function buildDraftFromTaskIntake(input) {
253
256
  const title = artifact?.draft?.title?.trim() ||
254
257
  artifact?.semantic?.title?.trim() ||
255
258
  input.title;
259
+ // Preserve semantic engineering boundary (paths/verify/taskKind) so the
260
+ // Console draft does not fall back to interview defaults and overwrite
261
+ // TX1 precise values on contractApply --from-draft.
262
+ const semDraftConstraints = artifact?.draft?.constraints;
263
+ const semDraftVerification = artifact?.draft?.verification;
264
+ const semTaskKind = artifact?.draft?.taskKind?.trim();
265
+ const mergedAllowed = filterPlaceholderPaths(semDraftConstraints?.allowedPaths);
266
+ const mergedForbidden = filterPlaceholderPaths(semDraftConstraints?.forbiddenPaths);
267
+ const mergedVerify = Array.isArray(semDraftVerification?.commands)
268
+ ? semDraftVerification.commands
269
+ .filter((cmd) => typeof cmd?.command === "string" && cmd.command.trim().length > 0)
270
+ .map((cmd) => ({
271
+ label: typeof cmd.label === "string" && cmd.label.trim()
272
+ ? cmd.label.trim()
273
+ : "verify",
274
+ command: cmd.command.trim(),
275
+ ...(typeof cmd.timeoutMs === "number"
276
+ ? { timeoutMs: cmd.timeoutMs }
277
+ : {}),
278
+ }))
279
+ : [];
256
280
  draft = {
257
281
  ...draft,
258
282
  title,
283
+ ...(semTaskKind
284
+ ? { taskKind: normalizeConsoleWorkflowKind(semTaskKind, taskKind) }
285
+ : {}),
259
286
  requirement: {
260
287
  objective: semanticReq.objective.trim(),
261
288
  scope: asStringList(semanticReq.scope),
262
289
  nonGoals: asStringList(semanticReq.nonGoals),
263
290
  acceptanceCriteria: asAcceptance(semanticReq.acceptanceCriteria),
264
291
  },
292
+ ...(mergedAllowed.length > 0 ||
293
+ mergedForbidden.length > 0 ||
294
+ Array.isArray(semDraftConstraints?.invariants)
295
+ ? {
296
+ constraints: {
297
+ invariants: asStringList(semDraftConstraints?.invariants),
298
+ allowedPaths: mergedAllowed,
299
+ forbiddenPaths: mergedForbidden,
300
+ },
301
+ }
302
+ : {}),
303
+ ...(mergedVerify.length > 0
304
+ ? { verification: { commands: mergedVerify } }
305
+ : {}),
265
306
  openQuestions: asStringList(artifact?.draft?.openQuestions ?? artifact?.semantic?.openQuestions) || undefined,
266
307
  assumptions: asStringList(artifact?.draft?.assumptions ?? artifact?.semantic?.assumptions) || undefined,
267
308
  references: artifact?.draft?.references,
@@ -14,6 +14,7 @@ import { InterviewSessionStore } from "./interview/session.js";
14
14
  import { isLoopbackHost } from "./loopback.js";
15
15
  import { ChatSessionStore } from "./chat/session-store.js";
16
16
  import { createChatEventStore, createChatOperationLinker, } from "./chat/chat-event-store.js";
17
+ import { createChatTurnExecutionRegistry } from "./chat/turn-execution-registry.js";
17
18
  import { ConsolePiRuntime } from "./chat/pi-runtime.js";
18
19
  import { handleChatRequest } from "./chat/routes.js";
19
20
  import { createOperationEventStore, } from "./operation-sse.js";
@@ -147,6 +148,7 @@ export async function createConsoleServer(options) {
147
148
  // than silently consume a different process' event namespace.
148
149
  const chatEventEpoch = randomBytes(12).toString("hex");
149
150
  const chatEvents = createChatEventStore({ appData, epoch: chatEventEpoch });
151
+ const chatTurnExecutions = createChatTurnExecutionRegistry();
150
152
  const chatOperationLinker = createChatOperationLinker({
151
153
  chatEvents,
152
154
  operations,
@@ -155,6 +157,7 @@ export async function createConsoleServer(options) {
155
157
  const chatRuntime = new ConsolePiRuntime({
156
158
  cwd: repoRoot,
157
159
  sessionDir: appData.chatSessions,
160
+ resourcePreferencesPath: appData.resourcePreferences,
158
161
  actionContext,
159
162
  });
160
163
  // chatRouteDeps is a plain object literal — it cannot throw. The previous
@@ -165,6 +168,7 @@ export async function createConsoleServer(options) {
165
168
  runtime: chatRuntime,
166
169
  store: chatStore,
167
170
  events: chatEvents,
171
+ turnExecutions: chatTurnExecutions,
168
172
  operationLinker: chatOperationLinker,
169
173
  appData,
170
174
  bootToken,