@tea-agent/loop-agent 0.39.0-next.20 → 0.39.0-next.22
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 +4 -0
- package/dist/application/dag/generate-task-dag.js +9 -0
- package/dist/build-stamp.json +2 -2
- package/dist/shared/operator/capabilities.js +3 -3
- package/dist/worker/console/chat/deferred-turn.js +91 -0
- package/dist/worker/console/chat/routes.js +458 -47
- package/dist/worker/console/chat/semantic-activity.js +13 -13
- package/dist/worker/console/chat/session-store.js +146 -2
- package/dist/worker/console/recovery-cta.js +4 -4
- package/dist/worker/console/recovery-error-copy.js +4 -4
- package/dist/worker/console/server.js +6 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-BmOEx0gA.js → abnfDiagram-N423BO3Z-C4bmo3iY.js} +1 -1
- package/dist/worker/console/static/assets/{arc-BGiVVe8b.js → arc-SAD7McOS.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-nDdu4rgJ.js → architectureDiagram-T3A2C74G-DAVLUdK1.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Bb5u0BWf.js → blockDiagram-VBNYF7ZC-CPPdv4vj.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BlhC0j94.js → c4Diagram-5PPSVZJV-D1GRGZax.js} +1 -1
- package/dist/worker/console/static/assets/channel-R6oQIDkw.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-Ai8_qQXI.js → chunk-2GRJ4B5K-D_Bq2ZqK.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B9gyCjqX.js → chunk-2Q5K7J3B-CPLVtamK.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-Bzbj3zGH.js → chunk-5RXB4S5H-DnaZWcL3.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BT415PvT.js → chunk-5VM5RSS4-BRTmFgnq.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-D_A5_5QL.js → chunk-6Q2QTUOP-BRlfYZoH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-srJkaP3f.js → chunk-GF5L2VYU-CjNybD4u.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-UYGvEP4l.js → chunk-JWPE2WC7-D3e-74fG.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-B8luBrrz.js → chunk-KBJHAD2P-Br3ir6f2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DN7wXZSq.js → chunk-RYQCIY6F-1NgVuRbh.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DXKyMuKS.js → chunk-XXDRQBXY-BTYuvuWN.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BPXlmPWI.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BPXlmPWI.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-dqvoynXj.js → cose-bilkent-JH36ORCC-BC6Bgosf.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2--PcyL34A.js → cynefin-VYW2F7L2-DV-HypfL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DvWs_hTY.js → cynefinDiagram-MW4NZA55-DhTaddO-.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DxeIxbyO.js → dagre-VZM6K2ZE-BnEcOmiI.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DPCG61Of.js → diagram-7IWD3JNH-xphGRVKp.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CmuU50-U.js → diagram-B4RE2ZJO-CrdD1mRG.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-B61XLD_v.js → diagram-LBJQPF4R-D4YdLsaF.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BB7HTRRY.js → diagram-Q27KOJAE-LCKyGZ5U.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-DvkboAIp.js → diagram-UB23O5K3-BeiTe7t0.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BdJ_y1fL.js → ebnfDiagram-BXEA7PRR-BO2cq8GS.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-9bUBZTRi.js → erDiagram-JOGREHBK-CmWww3Nt.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-Dw4L4RBa.js → flowDiagram-UKHOOZJN-C2kkUYg5.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Jr82N_QP.js → ganttDiagram-PKOTCBZU-DY_JZ2iQ.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DAz9wFLr.js → gitGraphDiagram-DS77QQ5N-BizhCSw9.js} +1 -1
- package/dist/worker/console/static/assets/index-BXN89VPX.js +325 -0
- package/dist/worker/console/static/assets/index-CuH5CNFu.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-CBB5Np7y.js → infoDiagram-6WML65LV-Dlo2eK_d.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-D8IOp94y.js → ishikawaDiagram-WSZJBQD7-3EIlIIuZ.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Dgd3AHGG.js → journeyDiagram-NVQOT4AX-DiMDe5Yh.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BmYOxLE9.js → kanban-definition-27J2QSJJ-sN553oIN.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DfYTEF6J.js → linear-D9Py31Ld.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BjuFPRqa.js → mermaid.core-D7Occzk_.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CLyUViGd.js → mindmap-definition-FAOFIHXS-DjDRboiR.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BvX2Di4-.js → pegDiagram-VL7TDLO6-Cgc4qlzp.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BFj0_OLv.js → pieDiagram-7S7Q4E2Y-DxZj8pKd.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-BIUrD_hx.js → quadrantDiagram-CIZ2JOQS-CJ50MngR.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-CHBB48fj.js → railroadDiagram-AXF67PYL-BY-OD8Tr.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-sJrYw2Sf.js → requirementDiagram-LRYGKXZP-CQFButfK.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-BzHH6fPR.js → sankeyDiagram-W5VNT64P-BB_QUK_b.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-7QCnelCt.js → sequenceDiagram-SI44F4Z6-CqhXZjyx.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-sDYSxn72.js → sizeCapture-X5ZJPWSS-2l1U4rgJ.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-XpiUdwzm.js → stateDiagram-OKZ733FA-BX1FbrhJ.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DJKi0Qel.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DvqgNPzD.js → swimlanes-SLNWSIFB-DOSnT7hb.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-YYe7EEm5.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-2TyOYNx0.js → timeline-definition-Z64GVDOM-DVJQA7AN.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B-nM6wM2.js → vennDiagram-T6HMQDX7-74uxl9gx.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-B86wPdbr.js → wardleyDiagram-T6FBY63Y-DsBxlcg_.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Dr1C4AQz.js → xychartDiagram-ELKLHX3M-snuW9Mjw.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/useOperatorActions.js +1 -1
- package/dist/worker/console/static-src/app/useRecoveryActions.js +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +38 -1
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +8 -1
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +42 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +3 -0
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +204 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +23 -1
- package/dist/workflows/dag/convergence/controller.js +141 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +6 -3
- package/dist/workflows/dag/init-hybrid.js +40 -0
- package/dist/workflows/dag/prompt.js +45 -0
- package/dist/workflows/dag/rerun-feedback.js +212 -0
- package/dist/workflows/dag/rerun-plan.js +93 -27
- package/dist/workflows/dag/rerun-run.js +3 -0
- package/dist/workflows/dag/rerun-task.js +61 -2
- package/dist/workflows/dag/retry-policy.js +18 -0
- package/dist/workflows/dag/types.js +51 -0
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-Tl-FkUqr.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BaehtRk4.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BaehtRk4.js +0 -1
- package/dist/worker/console/static/assets/index-B7Y-0g3J.css +0 -1
- package/dist/worker/console/static/assets/index-DkCrqaYg.js +0 -325
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-eEhq2A8Y.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-la8AC7fo.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
|
|
29
29
|
### 改进
|
|
30
30
|
|
|
31
|
+
- Operator Chat 的乐观停止现在把“视觉已停止”和 Turn ownership 分开:Abort 获得可靠终态前明确显示“正在停止”,此时可为原会话保存一条服务端持久化的“停止后发送”消息;后一次覆盖前一次,切换会话、刷新页面或 Console 重启不会丢失,旧 Turn 结束后复用正常 Turn 准入路径自动发送,并以固定 `clientRequestId` 防止重复执行。
|
|
32
|
+
- Operator Chat 修复快速终止时“停止后发送”与普通发送之间的准入空洞:发送路径改读实时 ownership;若 deferred 请求恰好撞上旧 Turn 终态,会先按服务端状态对账,再使用同一 `clientRequestId` 自动转为普通发送,不再要求用户刷新重试或丢失本次提交。
|
|
33
|
+
- `dag rerun-task` 现在会把父 run 最后一轮仍未解决的 `verify-pi` / review 反馈、证据引用和修订轮次带入新完整 DAG;planner、implementer 与 verifier/reviewer 必须修复或举证说明不再适用,不能仅因文件已存在就返回 `already-satisfied`。Console 同步区分「自动修订」「从失败节点恢复」「带反馈重新执行任务」。
|
|
34
|
+
- DAG 恢复与治理收敛收窄为两条最小路径:标准治理 `request-revision` 仅在 `maxFixLoops > 0` 时同 run 回到 `implement-pi`;writer 遇到 `unavailable` / `network` / `rate-limit` / `timeout` 时,`dag rerun --from-node` 重跑 writer 本身及安全下游,不再把 parent `ERROR` 改写成 `FINISHED`,任意自定义 shell 也不能仅凭 `verifyEvidence` 获得续跑资格。
|
|
31
35
|
- `frontend-plan-pi` 改为 runtime skeleton + editable RFC 7386 patch:`schemaVersion`、source binding、risk、writer target files 与生产 Mock 安全位由 DAG 冻结且不可被 plan/revision 覆盖;节点 validator 将补丁编译为 canonical 完整契约后再交给 review/prewrite,并在 `contracts/candidates/<nodeId>/` 保存每次 raw/extracted/normalized/validation 证据。任务提示与三类结构化重试(invalid-output / provider length 截断 / output-too-large)同步收敛为单一 patch + 唯一 `openspec-citations`;无法在声明文件中解析的可选 verification symbol 会被确定性移除并留下 normalization action,避免格式冲突、完整契约重复输出和说明性 symbol 延迟到 trace 才失败。
|
|
32
36
|
- Operator Chat 恢复工具对齐真实能力:系统提示改用 `dagReport` / `dagRerunPlan` / `dagRerun` / `standaloneTaskRerun` / `workerTaskRetry` 真名,不再写 `operator_*` 或把 `dagResume` 当成模型可执行项;`dagDoctor` / `dagStatus` / `workerPoolDoctor` 改为 typed `runId`/`taskId`,不再让模型猜 CLI `args[]`。ADR 0013 自定义 base prompt 上限由 1900 统一调整为 2500(2026-08-18,废止 0.8×2498 比例),预算用于写清节点续跑 / 整单重生 / Worker 重排队分流,以及多轮迭代恢复纪律(先一句话总结上一轮错误、修根因不修症状、禁止原样重交、同错两轮后停下报告)。
|
|
33
37
|
- Operator Chat 模型工具面收敛:`advanced` 分类的命令(workflow/loop/benchmark/knowledge-graph 等 8 个只读低频入口)不再进入模型工具白名单,模型注意力集中到高频工具;保留的 27 个 model-callable 官方 CLI 动作全部换上「做什么 + 何时用」语义描述,不再是无信息的 `Official CLI action coverage for ...` 模板;dispatcher 对官方尾部动作的识别从描述前缀匹配改为结构化 `OFFICIAL_TAIL_ACTION_IDS` 集合判断。审查收口:`knowledgeCurate` 纠正为 `mutation`/`advanced`(条件写盘,移出模型面,防经 read 通道传 `--output` 写盘);`promoteRun`/`closeoutTask` 描述去掉 dispatch 不保证的生命周期断言,如实标注为 task-advance 别名并提示先核 run/任务状态。工具清单渲染修复:promptSnippet 去掉重复工具名前缀(SDK 渲染自带 `- name:`,原实现名字出现两遍);`inspect`/`status`/`spineCheck`/`sourceInstructions` 四条占位描述换成语义描述;task-advance 家族(`newTask`/`dagRunTask`)标注与标准流 `taskAdvance` 的关系,避免模型在 5 个相似入口间选错。可调用性修复:`observeLink` 补上 4 个可选参数 schema(dagRunId/taskId/featureId/workerRunId,原空 schema + additionalProperties:false 导致模型传参必被拒、工具名存实亡);Pi 工具参数 schema 现在携带注册表里的参数描述(Type.String/Boolean/Number/Array 注入 `description`,原实现丢弃参数描述、模型只能看到参数名)。
|
|
@@ -279,6 +279,7 @@ export async function generateTaskDagUseCase(input) {
|
|
|
279
279
|
const candidateResult = await initHybridDagFromTask(repoRoot, parsed.taskId, {
|
|
280
280
|
outputPath: parsed.outputPath,
|
|
281
281
|
template: "standard-dag",
|
|
282
|
+
rerunFeedback: parsed.rerunFeedback,
|
|
282
283
|
});
|
|
283
284
|
const candidateValidateSummary = await validateDagUseCase(buildValidateInput(repoRoot, candidateResult.outputPath, parsed));
|
|
284
285
|
const profileRouting = await resolveProfileRouting(repoRoot, parsed, candidateValidateSummary.governanceProfile ?? {
|
|
@@ -324,8 +325,16 @@ export async function generateTaskDagUseCase(input) {
|
|
|
324
325
|
: await initHybridDagFromTask(repoRoot, parsed.taskId, {
|
|
325
326
|
outputPath: parsed.outputPath,
|
|
326
327
|
template: profileRouting.selectedTemplate,
|
|
328
|
+
rerunFeedback: parsed.rerunFeedback,
|
|
327
329
|
});
|
|
328
330
|
const outputPath = initResult.outputPath;
|
|
331
|
+
if (parsed.expectedRerunFeedbackDigest) {
|
|
332
|
+
const generatedSpec = parseDagSpec(JSON.parse(await readFile(outputPath, "utf8")));
|
|
333
|
+
if (generatedSpec.rerunFeedback?.digest !==
|
|
334
|
+
parsed.expectedRerunFeedbackDigest) {
|
|
335
|
+
throw new Error(`rerun feedback drift: expected ${parsed.expectedRerunFeedbackDigest}, got ${generatedSpec.rerunFeedback?.digest ?? "missing"}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
329
338
|
const validateSummary = profileRouting.selectedTemplate === candidateResult.template
|
|
330
339
|
? candidateValidateSummary
|
|
331
340
|
: await validateDagUseCase(buildValidateInput(repoRoot, outputPath, parsed));
|
package/dist/build-stamp.json
CHANGED
|
@@ -1163,7 +1163,7 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1163
1163
|
resultSchemaVersion: 1,
|
|
1164
1164
|
envelopeSchemaVersion: 1,
|
|
1165
1165
|
requiredErrorCodes: ["INVALID_INPUT", "NOT_FOUND"],
|
|
1166
|
-
description: "Read-only check
|
|
1166
|
+
description: "Read-only check for failed-node recovery; it does not execute. Call after dagReport with primaryFailure.nodeId. eligible=true returns the exact planHash required by dagRerun. eligible=false covers writer/decision/fingerprint, unsafe shell, Worker ownership, or workspace/controller drift: use workerTaskRetry for Worker/Task Pool failures, or standaloneTaskRerun after any required contract adopt for standalone runs. Do not force dagRerun or invent a new task.",
|
|
1167
1167
|
inputParams: [
|
|
1168
1168
|
{
|
|
1169
1169
|
name: "runId",
|
|
@@ -1193,7 +1193,7 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1193
1193
|
"BINDING_DRIFT",
|
|
1194
1194
|
"INVALID_INPUT",
|
|
1195
1195
|
],
|
|
1196
|
-
description: "Continue the same DAG from
|
|
1196
|
+
description: "Continue the same DAG from the effective failed node by creating a continuation run. Requires a fresh eligible dagRerunPlan and its exact planHash. Prefer this for provider, network, rate-limit, timeout, and other safe downstream failures. Not a full task regenerate: use standaloneTaskRerun for that. Server rejects stale planHash, binding, or fingerprint drift.",
|
|
1197
1197
|
inputParams: [
|
|
1198
1198
|
{
|
|
1199
1199
|
name: "runId",
|
|
@@ -1559,7 +1559,7 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1559
1559
|
"INVALID_INPUT",
|
|
1560
1560
|
"HUMAN_CONFIRMATION_REQUIRED",
|
|
1561
1561
|
],
|
|
1562
|
-
description: "Regenerate the whole standalone DAG from the CURRENT contract, then validate and execute a new run
|
|
1562
|
+
description: "Regenerate the whole standalone DAG from the CURRENT contract, then validate and execute a new run with parent lineage and the latest unresolved verify/review feedback when available. This is NOT continue-from-failed-node (use dagRerun for that). Server rejects the call when dagRerunPlan is eligible, primaryRecovery.humanRequired=true, or run facts do not recommend rerun-task. Feedback is recovery context, not a contract rewrite; adopt required contract changes before calling or the new DAG repeats the same failure.",
|
|
1563
1563
|
inputParams: [
|
|
1564
1564
|
{
|
|
1565
1565
|
name: "runId",
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
const IMAGE_MIME_TYPES = new Set([
|
|
3
|
+
"image/png",
|
|
4
|
+
"image/jpeg",
|
|
5
|
+
"image/gif",
|
|
6
|
+
"image/webp",
|
|
7
|
+
]);
|
|
8
|
+
export function hashDeferredTurnPayload(input) {
|
|
9
|
+
return createHash("sha256")
|
|
10
|
+
.update(JSON.stringify({
|
|
11
|
+
text: input.text,
|
|
12
|
+
images: input.images.map(({ type, mimeType, data }) => ({
|
|
13
|
+
type,
|
|
14
|
+
mimeType,
|
|
15
|
+
data,
|
|
16
|
+
})),
|
|
17
|
+
}))
|
|
18
|
+
.digest("hex");
|
|
19
|
+
}
|
|
20
|
+
export function parseDeferredTurn(value) {
|
|
21
|
+
if (!value || typeof value !== "object")
|
|
22
|
+
return undefined;
|
|
23
|
+
const item = value;
|
|
24
|
+
if (item.schemaVersion !== 1 ||
|
|
25
|
+
!Number.isSafeInteger(item.revision) ||
|
|
26
|
+
(item.revision ?? 0) < 1 ||
|
|
27
|
+
typeof item.clientRequestId !== "string" ||
|
|
28
|
+
!item.clientRequestId.trim() ||
|
|
29
|
+
typeof item.payloadHash !== "string" ||
|
|
30
|
+
!/^[a-f0-9]{64}$/.test(item.payloadHash) ||
|
|
31
|
+
typeof item.blockedByTurnId !== "string" ||
|
|
32
|
+
!item.blockedByTurnId.trim() ||
|
|
33
|
+
typeof item.text !== "string" ||
|
|
34
|
+
!Array.isArray(item.images) ||
|
|
35
|
+
!["queued", "dispatching", "accepted", "failed"].includes(item.state) ||
|
|
36
|
+
typeof item.createdAt !== "string" ||
|
|
37
|
+
typeof item.updatedAt !== "string") {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const images = [];
|
|
41
|
+
for (const image of item.images) {
|
|
42
|
+
if (!image || typeof image !== "object")
|
|
43
|
+
return undefined;
|
|
44
|
+
const candidate = image;
|
|
45
|
+
if (typeof candidate.name !== "string" ||
|
|
46
|
+
candidate.type !== "image" ||
|
|
47
|
+
typeof candidate.mimeType !== "string" ||
|
|
48
|
+
!IMAGE_MIME_TYPES.has(candidate.mimeType) ||
|
|
49
|
+
typeof candidate.data !== "string") {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
images.push(candidate);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
schemaVersion: 1,
|
|
56
|
+
revision: item.revision,
|
|
57
|
+
clientRequestId: item.clientRequestId.trim(),
|
|
58
|
+
payloadHash: item.payloadHash,
|
|
59
|
+
blockedByTurnId: item.blockedByTurnId.trim(),
|
|
60
|
+
text: item.text,
|
|
61
|
+
images,
|
|
62
|
+
state: item.state,
|
|
63
|
+
createdAt: item.createdAt,
|
|
64
|
+
updatedAt: item.updatedAt,
|
|
65
|
+
...(typeof item.acceptedTurnId === "string" && item.acceptedTurnId
|
|
66
|
+
? { acceptedTurnId: item.acceptedTurnId }
|
|
67
|
+
: {}),
|
|
68
|
+
...(item.lastError &&
|
|
69
|
+
typeof item.lastError.code === "string" &&
|
|
70
|
+
typeof item.lastError.message === "string"
|
|
71
|
+
? { lastError: { code: item.lastError.code, message: item.lastError.message } }
|
|
72
|
+
: {}),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function projectDeferredTurnSummary(deferredTurn) {
|
|
76
|
+
if (!deferredTurn)
|
|
77
|
+
return null;
|
|
78
|
+
return {
|
|
79
|
+
revision: deferredTurn.revision,
|
|
80
|
+
clientRequestId: deferredTurn.clientRequestId,
|
|
81
|
+
blockedByTurnId: deferredTurn.blockedByTurnId,
|
|
82
|
+
state: deferredTurn.state,
|
|
83
|
+
updatedAt: deferredTurn.updatedAt,
|
|
84
|
+
textPreview: deferredTurn.text.replace(/\s+/g, " ").trim().slice(0, 120),
|
|
85
|
+
imageCount: deferredTurn.images.length,
|
|
86
|
+
...(deferredTurn.acceptedTurnId
|
|
87
|
+
? { acceptedTurnId: deferredTurn.acceptedTurnId }
|
|
88
|
+
: {}),
|
|
89
|
+
...(deferredTurn.lastError ? { lastError: deferredTurn.lastError } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|