@bolloon/bolloon-agent 0.6.0 → 0.6.1
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/dist/agents/execution-entry.js +10 -0
- package/dist/agents/goal-flywheel/wiring/seams.js +5 -1
- package/dist/agents/pi-sdk-tools.js +18 -8
- package/dist/agents/pi-sdk.js +472 -1263
- package/dist/agents/runner-resolver.js +2 -1
- package/dist/agents/tool-capability/index.js +51 -0
- package/dist/agents/workflow-pivot-loop.js +31 -10
- package/dist/agents/write-verify.js +60 -0
- package/dist/bollharness-integration/integration.js +8 -0
- package/dist/bollharness-integration/skill-adapter.js +32 -3
- package/dist/electron-build/agents/goal-flywheel/wiring/seams.js +5 -1
- package/dist/electron-build/agents/goal-flywheel/wiring/seams.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk-tools.js +21 -11
- package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk.js +473 -1262
- package/dist/electron-build/agents/pi-sdk.js.map +1 -1
- package/dist/electron-build/agents/runner-resolver.js +2 -1
- package/dist/electron-build/agents/runner-resolver.js.map +1 -1
- package/dist/electron-build/agents/tool-capability/index.js +90 -0
- package/dist/electron-build/agents/tool-capability/index.js.map +1 -0
- package/dist/electron-build/agents/workflow-pivot-loop.js +31 -10
- package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
- package/dist/electron-build/agents/write-verify.js +99 -0
- package/dist/electron-build/agents/write-verify.js.map +1 -0
- package/dist/electron-build/bollharness-integration/integration.js +8 -0
- package/dist/electron-build/bollharness-integration/integration.js.map +1 -1
- package/dist/electron-build/bollharness-integration/skill-adapter.js +32 -3
- package/dist/electron-build/bollharness-integration/skill-adapter.js.map +1 -1
- package/dist/electron-build/kernel/channel-actor.js +25 -0
- package/dist/electron-build/kernel/channel-actor.js.map +1 -1
- package/dist/electron-build/kernel/control.js +102 -0
- package/dist/electron-build/kernel/control.js.map +1 -0
- package/dist/electron-build/kernel/model-runtime.js +508 -0
- package/dist/electron-build/kernel/model-runtime.js.map +1 -0
- package/dist/electron-build/kernel/run-lifecycle.js +146 -0
- package/dist/electron-build/kernel/run-lifecycle.js.map +1 -0
- package/dist/electron-build/kernel/transport.js +119 -0
- package/dist/electron-build/kernel/transport.js.map +1 -0
- package/dist/electron-build/llm/native-adapter.js +122 -0
- package/dist/electron-build/llm/native-adapter.js.map +1 -0
- package/dist/index.js +19 -0
- package/dist/ios/bolloon-web.json +3 -3
- package/dist/ios/client.js +13 -7
- package/dist/ios/mobile-core.js +7762 -6289
- package/dist/ios/mobile.js +64 -0
- package/dist/ios/routes-mobile-tasks.js +2 -1
- package/dist/ios/routes-tasks.js +16 -1
- package/dist/ios/routes-x402-info.js +28 -1
- package/dist/ios/server-storage.js +26 -5
- package/dist/ios/server.js +840 -862
- package/dist/ios/sw.js +1 -1
- package/dist/ios/ui/message-renderer.js +473 -29
- package/dist/ios/ui/step-timeline.js +13 -12
- package/dist/kernel/channel-actor.js +24 -0
- package/dist/kernel/gate-scan.js +318 -4
- package/dist/kernel/model-runtime.js +22 -0
- package/dist/kernel/plan-channel-actor.js +12 -5
- package/dist/kernel/plan-communication.js +163 -0
- package/dist/kernel/plan-constraint.js +2 -15
- package/dist/kernel/plan-deletion.js +1 -1
- package/dist/kernel/plan-harness.js +78 -0
- package/dist/kernel/plan.js +1 -5
- package/dist/kernel/roster.js +13 -11
- package/dist/kernel/run-lifecycle.js +138 -0
- package/dist/kernel/transport.js +111 -0
- package/dist/llm/native-adapter.js +117 -0
- package/dist/web/bolloon-web.json +3 -3
- package/dist/web/client.js +9 -5
- package/dist/web/routes-tasks.js +12 -1
- package/dist/web/server.js +802 -866
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* run-lifecycle.ts — K10 ①: **运行生命周期写口** (与 `control.ts` 分开: 语义不同)
|
|
4
|
+
*
|
|
5
|
+
* `control.ts` = **命令式控制面**: 「谁命令我停 / 继续 / 恢复」—— web · cli · supervisor 发起, 带 origin 审计。
|
|
6
|
+
* 本文件 = **回合事实写口**: 「我这一轮发生了什么」—— start-run · record-step · finish-run · save-checkpoint。
|
|
7
|
+
*
|
|
8
|
+
* 为什么必须分开 (K10 ① 的下一刀定形时复核过):
|
|
9
|
+
* 混进同一个 `kind` 空间之后, K10 ②③④ 那些批次就无法区分「这条写入是外部命令还是回合事实」,
|
|
10
|
+
* 两者的**失败语义也不同** —— 控制面被拒要给 409 (调用方改主意), 而事实写不进是**响亮失败**
|
|
11
|
+
* (run-store 是 strict 的: 写不进 = 这次运行在事实层面不存在, 不许静默继续)。
|
|
12
|
+
*
|
|
13
|
+
* 形状照抄 `control.ts` (同一个仓库里只该有一种端口写法):
|
|
14
|
+
* 端口注入 · **未注入即拒** (不静默降级) · 一律**返回结果对象不抛** · 端口用 `{ok:false}` 表达拒绝要被归一化 · 审计流水可读。
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.RUN_LIFECYCLE_NEEDS_RUN_ID = exports.RUN_LIFECYCLE_OPS = void 0;
|
|
18
|
+
exports.runLifecycleAudit = runLifecycleAudit;
|
|
19
|
+
exports.resetRunLifecycleAudit = resetRunLifecycleAudit;
|
|
20
|
+
exports.submitRunLifecycle = submitRunLifecycle;
|
|
21
|
+
exports.assertLifecycleOk = assertLifecycleOk;
|
|
22
|
+
exports.RUN_LIFECYCLE_OPS = [
|
|
23
|
+
'start-run',
|
|
24
|
+
'record-step',
|
|
25
|
+
'finish-run',
|
|
26
|
+
'save-checkpoint',
|
|
27
|
+
];
|
|
28
|
+
/** 哪些操作必须有 runId (start-run 例外: 它的 runId 是**结果**, 不是入参) */
|
|
29
|
+
exports.RUN_LIFECYCLE_NEEDS_RUN_ID = {
|
|
30
|
+
'start-run': false,
|
|
31
|
+
'record-step': true,
|
|
32
|
+
'finish-run': true,
|
|
33
|
+
'save-checkpoint': true,
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* 端口**不抛异常但明确拒绝** (`{ ok: false, reason }`) 的归一化 —— 与 `control.ts` 同口径。
|
|
37
|
+
* 为什么必须有: store 类原语用返回值表达拒绝 (例如状态迁移不合法), 只看"有没有抛"会把**被拒当成成功**。
|
|
38
|
+
*/
|
|
39
|
+
function portRefusal(res) {
|
|
40
|
+
if (res && typeof res === 'object' && 'ok' in res) {
|
|
41
|
+
const r = res;
|
|
42
|
+
if (r.ok === false)
|
|
43
|
+
return `端口拒绝: ${String(r.reason ?? '(未给原因)')}`;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const audit = [];
|
|
48
|
+
const AUDIT_MAX = 200;
|
|
49
|
+
/** 审计流水 (最近 N 条; 测试与运维可读) */
|
|
50
|
+
function runLifecycleAudit() {
|
|
51
|
+
return audit;
|
|
52
|
+
}
|
|
53
|
+
function resetRunLifecycleAudit() {
|
|
54
|
+
audit.length = 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 提交一条生命周期写入。**唯一入口** —— 校验 (op 合法 / origin 非空 / 需要的定位字段齐) → 派发到 port → 记审计。
|
|
58
|
+
* 一律**返回结果对象**, 不抛 (调用方不该用 try/catch 表达"没落盘"); 要不要把 `ok=false` 变成异常由
|
|
59
|
+
* `assertLifecycleOk` 决定 —— 生命周期写入**一律**要 (见该函数注释)。
|
|
60
|
+
*/
|
|
61
|
+
async function submitRunLifecycle(req, ports) {
|
|
62
|
+
const op = req?.op;
|
|
63
|
+
const finish = (ok, detail, port, result) => {
|
|
64
|
+
audit.push({
|
|
65
|
+
at: Date.now(),
|
|
66
|
+
op,
|
|
67
|
+
origin: req?.origin ?? '(anonymous)',
|
|
68
|
+
target: String(req?.runId ?? '(new)'),
|
|
69
|
+
ok,
|
|
70
|
+
detail,
|
|
71
|
+
});
|
|
72
|
+
if (audit.length > AUDIT_MAX)
|
|
73
|
+
audit.splice(0, audit.length - AUDIT_MAX);
|
|
74
|
+
return { ok, op, via: 'kernel-run-lifecycle', detail, port, result };
|
|
75
|
+
};
|
|
76
|
+
if (!exports.RUN_LIFECYCLE_OPS.includes(op))
|
|
77
|
+
return finish(false, `未知写入类型: ${String(req?.op)}`);
|
|
78
|
+
if (!req.origin)
|
|
79
|
+
return finish(false, '缺少 origin (审计要求: 不许匿名写入)');
|
|
80
|
+
if (exports.RUN_LIFECYCLE_NEEDS_RUN_ID[op] && !req.runId)
|
|
81
|
+
return finish(false, `${op} 缺少 runId`);
|
|
82
|
+
const payload = req.payload ?? {};
|
|
83
|
+
if (op === 'start-run') {
|
|
84
|
+
if (typeof ports.startRun !== 'function')
|
|
85
|
+
return finish(false, 'port 未注入: startRun');
|
|
86
|
+
try {
|
|
87
|
+
const res = await ports.startRun(payload);
|
|
88
|
+
const refusal = portRefusal(res);
|
|
89
|
+
return refusal ? finish(false, refusal, 'startRun', res) : finish(true, undefined, 'startRun', res);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return finish(false, `startRun 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (op === 'record-step') {
|
|
96
|
+
if (typeof ports.recordStep !== 'function')
|
|
97
|
+
return finish(false, 'port 未注入: recordStep');
|
|
98
|
+
try {
|
|
99
|
+
const res = await ports.recordStep(req.runId, payload);
|
|
100
|
+
const refusal = portRefusal(res);
|
|
101
|
+
return refusal ? finish(false, refusal, 'recordStep', res) : finish(true, undefined, 'recordStep', res);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return finish(false, `recordStep 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (op === 'finish-run') {
|
|
108
|
+
if (typeof ports.finishRun !== 'function')
|
|
109
|
+
return finish(false, 'port 未注入: finishRun');
|
|
110
|
+
try {
|
|
111
|
+
const res = await ports.finishRun(req.runId, payload);
|
|
112
|
+
const refusal = portRefusal(res);
|
|
113
|
+
return refusal ? finish(false, refusal, 'finishRun', res) : finish(true, undefined, 'finishRun', res);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
return finish(false, `finishRun 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (op === 'save-checkpoint') {
|
|
120
|
+
if (typeof ports.saveCheckpoint !== 'function')
|
|
121
|
+
return finish(false, 'port 未注入: saveCheckpoint');
|
|
122
|
+
try {
|
|
123
|
+
const res = await ports.saveCheckpoint(req.runId, payload);
|
|
124
|
+
const refusal = portRefusal(res);
|
|
125
|
+
return refusal ? finish(false, refusal, 'saveCheckpoint', res) : finish(true, undefined, 'saveCheckpoint', res);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
return finish(false, `saveCheckpoint 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return finish(false, `未处理的写入类型: ${String(op)}`);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 生命周期写入**必须**落盘 —— 拿不到 `ok` 就抛。
|
|
135
|
+
*
|
|
136
|
+
* 依据: `run-store` 的持久化是 **strict** (写不进 = 这次运行在事实层面不存在),
|
|
137
|
+
* 所以「写失败但继续跑」= 制造"agent 跑了但没记录"的老毛病。要降级只有一种合法姿势:
|
|
138
|
+
* 由调用方显式换持久化等级 (环境开关), 不许在这里静默吞。
|
|
139
|
+
*/
|
|
140
|
+
function assertLifecycleOk(out) {
|
|
141
|
+
if (!out.ok) {
|
|
142
|
+
throw new Error(`[kernel-run-lifecycle] ${out.op} 未落盘: ${out.detail ?? '未知原因'}`
|
|
143
|
+
+ ' (run-store 是 strict: 写不进 = 这次运行在事实层面不存在, 不许静默继续)');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=run-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-lifecycle.js","sourceRoot":"","sources":["../../../src/kernel/run-lifecycle.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;AAIU,QAAA,iBAAiB,GAA8B;IAC1D,WAAW;IACX,aAAa;IACb,YAAY;IACZ,iBAAiB;CAClB,CAAC;AAEF,2DAA2D;AAC9C,QAAA,0BAA0B,GAA8C;IACnF,WAAW,EAAE,KAAK;IAClB,aAAa,EAAE,IAAI;IACnB,YAAY,EAAE,IAAI;IAClB,iBAAiB,EAAE,IAAI;CACxB,CAAC;AA8BF;;;GAGG;AACH,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,IAAI,IAAK,GAA+B,EAAE,CAAC;QAC/E,MAAM,CAAC,GAAG,GAAyC,CAAC;QACpD,IAAI,CAAC,CAAC,EAAE,KAAK,KAAK;YAAE,OAAO,SAAS,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,EAAE,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAWD,MAAM,KAAK,GAAiB,EAAE,CAAC;AAC/B,MAAM,SAAS,GAAG,GAAG,CAAC;AAEtB,6BAA6B;AAC7B;IACE,OAAO,KAAK,CAAC;AACf,CAAC;AAED;IACE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACI,KAAK,6BACV,GAAwB,EACxB,KAAwB;IAExB,MAAM,EAAE,GAAG,GAAG,EAAE,EAAoB,CAAC;IACrC,MAAM,MAAM,GAAG,CAAC,EAAW,EAAE,MAAe,EAAE,IAAa,EAAE,MAAgB,EAAuB,EAAE;QACpG,KAAK,CAAC,IAAI,CAAC;YACT,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,EAAE;YACF,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,aAAa;YACpC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,OAAO,CAAC;YACrC,EAAE;YACF,MAAM;SACP,CAAC,CAAC;QACH,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS;YAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;QACxE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,sBAAsB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACvE,CAAC,CAAC;IAEF,IAAI,CAAC,QAAA,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,EAAE,WAAW,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IACxF,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;IAClE,IAAI,QAAA,0BAA0B,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IAEzF,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAElC,IAAI,EAAE,KAAK,WAAW,EAAE,CAAC;QACvB,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU;YAAE,OAAO,MAAM,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;QACrF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACjC,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACtG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,MAAM,CAAC,KAAK,EAAE,gBAAgB,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,IAAI,EAAE,KAAK,aAAa,EAAE,CAAC;QACzB,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;QACzF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAe,EAAE,OAAO,CAAC,CAAC;YACjE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACjC,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QAC1G,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,MAAM,CAAC,KAAK,EAAE,kBAAkB,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED,IAAI,EAAE,KAAK,YAAY,EAAE,CAAC;QACxB,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,UAAU;YAAE,OAAO,MAAM,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QACvF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,KAAe,EAAE,OAAO,CAAC,CAAC;YAChE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACjC,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QACxG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,MAAM,CAAC,KAAK,EAAE,iBAAiB,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED,IAAI,EAAE,KAAK,iBAAiB,EAAE,CAAC;QAC7B,IAAI,OAAO,KAAK,CAAC,cAAc,KAAK,UAAU;YAAE,OAAO,MAAM,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;QACjG,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,KAAe,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACjC,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC;QAClH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,MAAM,CAAC,KAAK,EAAE,sBAAsB,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,EAAE,aAAa,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;GAMG;AACH,2BAAkC,GAAwB;IACxD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,0BAA0B,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,MAAM,IAAI,MAAM,EAAE;cAC3D,mDAAmD,CACxD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* transport.ts — K10 ④: **通信入口端口** (与 `control.ts` / `run-lifecycle.ts` 同一套端口写法)
|
|
4
|
+
*
|
|
5
|
+
* 目标形态 (设计页): `transport → router → channel mailbox` —— 也就是说:
|
|
6
|
+
* **上层只对"通信端口"说话, 不直接对某条传输 (hyperswarm / iroh / p2pNetwork) 说话**。
|
|
7
|
+
* Pi 现在自己持有 3 个薄包装 (`getPeers` / `sendMessage` / `broadcast` → `p2pNetwork`),
|
|
8
|
+
* 那正是"Pi 内部通信发送逻辑"还没迁完的形状 (K10 ④)。
|
|
9
|
+
*
|
|
10
|
+
* 为什么用端口而不是直接调传输:
|
|
11
|
+
* - 传输是可替换的 (hyperswarm / iroh / 以后的东西) ⇒ 上层不该 import 具体实现;
|
|
12
|
+
* - 发送是**有副作用**的动作 ⇒ 要能审计 (谁发的 / 发给谁 / 成没成), 且**未注入即拒** (不静默丢弃消息);
|
|
13
|
+
* - 与 `control.ts` / `run-lifecycle.ts` 保持同一种形状, 免得仓里出现第三种端口写法。
|
|
14
|
+
*
|
|
15
|
+
* 注: 本模块只做"入口收口", **不搬传输实现** (传输仍在 `src/network/**`); 判据见 `src/test/k10-transport-port.test.ts`。
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TRANSPORT_NEEDS_TARGET = exports.TRANSPORT_OPS = void 0;
|
|
19
|
+
exports.transportPeersSync = transportPeersSync;
|
|
20
|
+
exports.transportAudit = transportAudit;
|
|
21
|
+
exports.resetTransportAudit = resetTransportAudit;
|
|
22
|
+
exports.submitTransport = submitTransport;
|
|
23
|
+
exports.TRANSPORT_OPS = ['send', 'broadcast', 'peers'];
|
|
24
|
+
/** 哪些操作必须有目标 (send 要 peerId; broadcast / peers 不需要) */
|
|
25
|
+
exports.TRANSPORT_NEEDS_TARGET = {
|
|
26
|
+
send: true,
|
|
27
|
+
broadcast: false,
|
|
28
|
+
peers: false,
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* 同步读对端 (K10 ④ 后半) —— 与 `submitTransport` 分开是因为**签名**而不是因为语义:
|
|
32
|
+
* 传输层是异步的, 但上层有同步调用点 (sync 签名不能凭空变 async)。
|
|
33
|
+
* 返回 `null` = 端口未注入 (调用方必须自己决定降级, 不许假装"没有对端" —— 那是两回事)。
|
|
34
|
+
*/
|
|
35
|
+
function transportPeersSync(ports) {
|
|
36
|
+
if (typeof ports?.peersSync !== 'function')
|
|
37
|
+
return null;
|
|
38
|
+
return ports.peersSync();
|
|
39
|
+
}
|
|
40
|
+
/** 端口用 `{ok:false}` 表达拒绝的归一化 (与另外两个端口同口径) */
|
|
41
|
+
function portRefusal(res) {
|
|
42
|
+
if (res && typeof res === 'object' && 'ok' in res) {
|
|
43
|
+
const r = res;
|
|
44
|
+
if (r.ok === false)
|
|
45
|
+
return `端口拒绝: ${String(r.reason ?? '(未给原因)')}`;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const audit = [];
|
|
50
|
+
const AUDIT_MAX = 200;
|
|
51
|
+
/** 审计流水 (最近 N 条; 测试与运维可读) */
|
|
52
|
+
function transportAudit() {
|
|
53
|
+
return audit;
|
|
54
|
+
}
|
|
55
|
+
function resetTransportAudit() {
|
|
56
|
+
audit.length = 0;
|
|
57
|
+
}
|
|
58
|
+
/** 提交一次通信动作。**唯一入口** —— 校验 → 派发到 port → 记审计; 一律返回结果对象, 不抛。 */
|
|
59
|
+
async function submitTransport(req, ports) {
|
|
60
|
+
const op = req?.op;
|
|
61
|
+
const finish = (ok, detail, port, result) => {
|
|
62
|
+
audit.push({
|
|
63
|
+
at: Date.now(),
|
|
64
|
+
op,
|
|
65
|
+
origin: req?.origin ?? '(anonymous)',
|
|
66
|
+
target: String(req?.peerId ?? '(all)'),
|
|
67
|
+
ok,
|
|
68
|
+
detail,
|
|
69
|
+
});
|
|
70
|
+
if (audit.length > AUDIT_MAX)
|
|
71
|
+
audit.splice(0, audit.length - AUDIT_MAX);
|
|
72
|
+
return { ok, op, via: 'kernel-transport', detail, port, result };
|
|
73
|
+
};
|
|
74
|
+
if (!exports.TRANSPORT_OPS.includes(op))
|
|
75
|
+
return finish(false, `未知通信动作: ${String(req?.op)}`);
|
|
76
|
+
if (!req.origin)
|
|
77
|
+
return finish(false, '缺少 origin (审计要求: 不许匿名发送)');
|
|
78
|
+
if (exports.TRANSPORT_NEEDS_TARGET[op] && !req.peerId)
|
|
79
|
+
return finish(false, `${op} 缺少 peerId`);
|
|
80
|
+
const kind = req.kind ?? 'message';
|
|
81
|
+
const payload = req.payload ?? '';
|
|
82
|
+
if (op === 'send') {
|
|
83
|
+
if (typeof ports.send !== 'function')
|
|
84
|
+
return finish(false, 'port 未注入: send');
|
|
85
|
+
try {
|
|
86
|
+
const res = await ports.send(req.peerId, kind, payload);
|
|
87
|
+
const refusal = portRefusal(res);
|
|
88
|
+
return refusal ? finish(false, refusal, 'send', res) : finish(true, undefined, 'send', res);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return finish(false, `send 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (op === 'broadcast') {
|
|
95
|
+
if (typeof ports.broadcast !== 'function')
|
|
96
|
+
return finish(false, 'port 未注入: broadcast');
|
|
97
|
+
try {
|
|
98
|
+
const res = await ports.broadcast(kind, payload);
|
|
99
|
+
const refusal = portRefusal(res);
|
|
100
|
+
return refusal ? finish(false, refusal, 'broadcast', res) : finish(true, undefined, 'broadcast', res);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
return finish(false, `broadcast 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (op === 'peers') {
|
|
107
|
+
if (typeof ports.peers !== 'function')
|
|
108
|
+
return finish(false, 'port 未注入: peers');
|
|
109
|
+
try {
|
|
110
|
+
const res = await ports.peers();
|
|
111
|
+
return finish(true, undefined, 'peers', res);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return finish(false, `peers 失败: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return finish(false, `未处理的通信动作: ${String(op)}`);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/kernel/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createNativeAdapter = createNativeAdapter;
|
|
4
|
+
exports.nativeAdapterFromEnv = nativeAdapterFromEnv;
|
|
5
|
+
const tool_name_js_1 = require("./tool-name.js");
|
|
6
|
+
/** 可被 abort 打断的 sleep (退避用) */
|
|
7
|
+
function sleep(ms, signal) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
const t = setTimeout(() => { signal?.removeEventListener?.('abort', onAbort); resolve(); }, ms);
|
|
10
|
+
const onAbort = () => { clearTimeout(t); reject(new Error('aborted during backoff')); };
|
|
11
|
+
if (signal?.aborted)
|
|
12
|
+
onAbort();
|
|
13
|
+
else
|
|
14
|
+
signal?.addEventListener?.('abort', onAbort, { once: true });
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function createNativeAdapter(cfg) {
|
|
18
|
+
const timeoutMs = cfg.timeoutMs ?? 120_000;
|
|
19
|
+
const maxRetries = cfg.maxRetries ?? 3;
|
|
20
|
+
const url = `${String(cfg.baseUrl || '').replace(/\/+$/, '')}/chat/completions`;
|
|
21
|
+
let calls = 0; // 观测: 真发出去几次 (重试也算)
|
|
22
|
+
let retries = 0;
|
|
23
|
+
const adapter = {
|
|
24
|
+
providerId: cfg.providerId ?? 'native',
|
|
25
|
+
stats: () => ({ calls, retries }),
|
|
26
|
+
async chat(context, systemPrompt, signal, tools, purpose) {
|
|
27
|
+
const messages = [
|
|
28
|
+
{ role: 'system', content: String(systemPrompt ?? '') },
|
|
29
|
+
{ role: 'user', content: String(context ?? '') },
|
|
30
|
+
];
|
|
31
|
+
let attempt = 0;
|
|
32
|
+
let lastErr;
|
|
33
|
+
while (attempt <= maxRetries) {
|
|
34
|
+
const ac = new AbortController();
|
|
35
|
+
const onAbort = () => ac.abort();
|
|
36
|
+
if (signal?.aborted)
|
|
37
|
+
ac.abort();
|
|
38
|
+
else
|
|
39
|
+
signal?.addEventListener?.('abort', onAbort, { once: true });
|
|
40
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
41
|
+
try {
|
|
42
|
+
calls += 1;
|
|
43
|
+
// ⚠️ 出程必须**净化工具名** —— 端点只接受 `^[a-zA-Z0-9_-]{1,64}$` (实测: 原样转发 183 个工具
|
|
44
|
+
// 里第 124 个不合规 ⇒ HTTP 400, 整轮空回复)。净化会把映射登记进**全局路由表**,
|
|
45
|
+
// 回程由 pivot 的 `resolveApiToolName` 还原 ⇒ 上下层协议不变 (这正是"适配器边界"的一部分)。
|
|
46
|
+
const wireTools = Array.isArray(tools) && tools.length > 0 ? (0, tool_name_js_1.sanitizeToolsForApi)(tools) : undefined;
|
|
47
|
+
const res = await fetch(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: { 'content-type': 'application/json', authorization: `Bearer ${cfg.apiKey}` },
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
model: cfg.model,
|
|
52
|
+
messages,
|
|
53
|
+
...(wireTools ? { tools: wireTools } : {}),
|
|
54
|
+
stream: false,
|
|
55
|
+
}),
|
|
56
|
+
signal: ac.signal,
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const text = await res.text().catch(() => '');
|
|
60
|
+
const retryable = res.status === 429 || res.status >= 500;
|
|
61
|
+
if (retryable && attempt < maxRetries) {
|
|
62
|
+
lastErr = new Error(`native-adapter HTTP ${res.status}: ${text.slice(0, 160)}`);
|
|
63
|
+
attempt += 1;
|
|
64
|
+
retries += 1;
|
|
65
|
+
await sleep(1000 * 2 ** (attempt - 1), signal);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// 非 429 的 4xx ⇒ **不重试** (重试无意义)。这里必须打标记: 否则下面的 catch
|
|
69
|
+
// 会把它当"网络错"再退避重试 —— 踩过 (用例⑤: 一个 400 被发了 4 次)。
|
|
70
|
+
const fatal = new Error(`native-adapter HTTP ${res.status}: ${text.slice(0, 200)}`);
|
|
71
|
+
fatal.noRetry = true;
|
|
72
|
+
throw fatal;
|
|
73
|
+
}
|
|
74
|
+
const data = await res.json();
|
|
75
|
+
const msg = data?.choices?.[0]?.message ?? {};
|
|
76
|
+
const toolCalls = Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 ? msg.tool_calls : undefined;
|
|
77
|
+
return {
|
|
78
|
+
reply: String(msg.content ?? ''),
|
|
79
|
+
tokens: data?.usage?.total_tokens,
|
|
80
|
+
toolCalls,
|
|
81
|
+
messages: messages.concat([{ role: 'assistant', content: String(msg.content ?? '') }]),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
// 调用方主动 abort ⇒ 原样抛出 (别当网络错去重试)
|
|
86
|
+
if (signal?.aborted)
|
|
87
|
+
throw e;
|
|
88
|
+
if (e?.noRetry)
|
|
89
|
+
throw e; // 非 429 的 4xx 等: 不重试
|
|
90
|
+
lastErr = e;
|
|
91
|
+
if (attempt >= maxRetries)
|
|
92
|
+
throw e;
|
|
93
|
+
attempt += 1;
|
|
94
|
+
retries += 1;
|
|
95
|
+
await sleep(1000 * 2 ** (attempt - 1), signal);
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
signal?.removeEventListener?.('abort', onAbort);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
throw lastErr ?? new Error('native-adapter: 不可达');
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
return adapter;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 从环境装配一个 native 适配器 (供 `BOLLOON_NATIVE_ADAPTER=1` 开关使用)。
|
|
109
|
+
* 缺 key ⇒ 返回 null (调用方回落到原适配器, 不假装可用)。
|
|
110
|
+
*/
|
|
111
|
+
function nativeAdapterFromEnv(env = process.env) {
|
|
112
|
+
const apiKey = env.BOLLOON_NATIVE_API_KEY || env.DEEPSEEK_API_KEY || '';
|
|
113
|
+
if (!apiKey)
|
|
114
|
+
return null;
|
|
115
|
+
return createNativeAdapter({
|
|
116
|
+
baseUrl: env.BOLLOON_NATIVE_BASE_URL || 'https://api.deepseek.com/v1',
|
|
117
|
+
apiKey,
|
|
118
|
+
model: env.BOLLOON_NATIVE_MODEL || 'deepseek-chat',
|
|
119
|
+
providerId: 'native-openai-compatible',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=native-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-adapter.js","sourceRoot":"","sources":["../../../src/llm/native-adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4745,6 +4745,25 @@ goalFlag) {
|
|
|
4745
4745
|
case 'harness-skill': {
|
|
4746
4746
|
if (!harness) {
|
|
4747
4747
|
harness = createBollharnessIntegration();
|
|
4748
|
+
// 2026-10-02 (K7): **生产活路径必须过门** —— 这条路径原先直调 registry (skill 旁路)。
|
|
4749
|
+
// 门 = PiAgentSession 的 Harness 判定 (`createSkillGuard()`, 只给判定; 执行仍在 adapter 的唯一执行点)。
|
|
4750
|
+
// **fail-closed**: 门建不起来 ⇒ 注入 deny-all (拒绝执行), 绝不留"没门"状态 ——
|
|
4751
|
+
// "门坏了静默等于没门"比没门更危险 (与 pivot loop / adapter 同一条纪律)。
|
|
4752
|
+
try {
|
|
4753
|
+
const gateSession = await createAgentSession({ cwd: process.cwd(), peerId: 'harness-skill' });
|
|
4754
|
+
if (typeof gateSession.createSkillGuard !== 'function') {
|
|
4755
|
+
throw new Error('该 session 实现未提供 createSkillGuard');
|
|
4756
|
+
}
|
|
4757
|
+
harness.setSkillGuard(gateSession.createSkillGuard());
|
|
4758
|
+
}
|
|
4759
|
+
catch (guardErr) {
|
|
4760
|
+
console.warn(`[K7] skill 门未能建立 ⇒ fail-closed (拒绝执行): ${String(guardErr?.message || guardErr)}`);
|
|
4761
|
+
harness.setSkillGuard(async () => ({
|
|
4762
|
+
allow: false,
|
|
4763
|
+
rejectedBy: 'harness-unavailable',
|
|
4764
|
+
reason: `skill 门未能建立: ${String(guardErr?.message || guardErr).slice(0, 120)}`,
|
|
4765
|
+
}));
|
|
4766
|
+
}
|
|
4748
4767
|
}
|
|
4749
4768
|
const [skillName, action] = args;
|
|
4750
4769
|
if (!skillName) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "bolloon-mobile-web/1",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"channel": "stable",
|
|
5
5
|
"build": "stable",
|
|
6
|
-
"commit": "
|
|
7
|
-
"builtAt": "2026-
|
|
6
|
+
"commit": "6e2afcdd8723004df91715d48cf7bf7d291ab7af",
|
|
7
|
+
"builtAt": "2026-10-04T08:00:57.589Z",
|
|
8
8
|
"layer": "web",
|
|
9
9
|
"note": "web 资源层构建戳 (手机端 OTA 的身份第 ③ 级回退; 装机后以 OTA state.json 为准)"
|
|
10
10
|
}
|
package/dist/ios/client.js
CHANGED
|
@@ -383,7 +383,7 @@
|
|
|
383
383
|
function parseToolCall(content, ctx) {
|
|
384
384
|
if (!content) return null;
|
|
385
385
|
const strippedContent = content.replace(/<think[\s\S]*?<\/think/g, "");
|
|
386
|
-
try {
|
|
386
|
+
if (PARSE_DIAG_ON) try {
|
|
387
387
|
const result = /* @__PURE__ */ (function _diagProbe() {
|
|
388
388
|
return null;
|
|
389
389
|
})();
|
|
@@ -571,11 +571,13 @@
|
|
|
571
571
|
}
|
|
572
572
|
return null;
|
|
573
573
|
}
|
|
574
|
-
var SHELL_KEYWORDS;
|
|
574
|
+
var SHELL_KEYWORDS, _parseEnv, PARSE_DIAG_ON;
|
|
575
575
|
var init_parse_tool_call = __esm({
|
|
576
576
|
"src/agents/parse-tool-call.ts"() {
|
|
577
577
|
"use strict";
|
|
578
578
|
SHELL_KEYWORDS = ["git", "npx", "npm", "tsx", "tsc", "vitest", "node", "mkdir", "touch", "ls", "echo", "cat", "head", "tail", "wc", "pwd", "date"];
|
|
579
|
+
_parseEnv = typeof process !== "undefined" ? process.env : void 0;
|
|
580
|
+
PARSE_DIAG_ON = !!_parseEnv && (_parseEnv.BOLLOON_PARSE_DIAG === "1" || _parseEnv.BOLLOON_VERBOSE === "1");
|
|
579
581
|
}
|
|
580
582
|
});
|
|
581
583
|
|
|
@@ -2885,6 +2887,11 @@ ${data.error || "channel not found"}`, "error");
|
|
|
2885
2887
|
}
|
|
2886
2888
|
var lastUsedJudgmentIds = [];
|
|
2887
2889
|
var currentPreviewBubble = null;
|
|
2890
|
+
function retirePreviewBubbles(container) {
|
|
2891
|
+
if (!container) return;
|
|
2892
|
+
container.querySelectorAll(".message-ai.preview").forEach((el) => el.remove());
|
|
2893
|
+
currentPreviewBubble = null;
|
|
2894
|
+
}
|
|
2888
2895
|
var selfImproveCardSeq = 0;
|
|
2889
2896
|
function getMessagesContainerForCurrent2() {
|
|
2890
2897
|
if (currentChannelId && messagesContainers.get(currentChannelId)) {
|
|
@@ -3144,9 +3151,7 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3144
3151
|
addMessage2(data.content, "user", true, container);
|
|
3145
3152
|
}
|
|
3146
3153
|
} else if (data.type === "ai") {
|
|
3147
|
-
|
|
3148
|
-
allPreviews.forEach((el) => el.remove());
|
|
3149
|
-
currentPreviewBubble = null;
|
|
3154
|
+
retirePreviewBubbles(container);
|
|
3150
3155
|
if (!MR_hasStreamingText()) {
|
|
3151
3156
|
addMessage2(data.content || "", "ai", true, container, lastUsedJudgmentIds || []);
|
|
3152
3157
|
} else {
|
|
@@ -3156,8 +3161,7 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3156
3161
|
sendRokidText(data.content || "", { source: "ai" });
|
|
3157
3162
|
} else if (data.type === "reply-preview") {
|
|
3158
3163
|
const previewContent = data.content || "";
|
|
3159
|
-
|
|
3160
|
-
oldPreviews.forEach((el) => el.remove());
|
|
3164
|
+
retirePreviewBubbles(container);
|
|
3161
3165
|
addMessage2(previewContent, "ai", false, container, []);
|
|
3162
3166
|
const newPreview = container.querySelector(".message-ai:not(.preview):last-of-type") || container.lastElementChild;
|
|
3163
3167
|
if (newPreview) {
|
|
@@ -3179,6 +3183,7 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3179
3183
|
handleStepEvent2(data);
|
|
3180
3184
|
} else if (data.type === "done") {
|
|
3181
3185
|
finalizeTimelineAsMessage2();
|
|
3186
|
+
retirePreviewBubbles(container);
|
|
3182
3187
|
hideLoopStatusBar2();
|
|
3183
3188
|
setSendMode("idle");
|
|
3184
3189
|
} else if (data.type === "renamed") {
|
|
@@ -3192,6 +3197,7 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3192
3197
|
}
|
|
3193
3198
|
} else if (data.type === "error") {
|
|
3194
3199
|
const errContent = String(data.content || "\u672A\u77E5\u9519\u8BEF");
|
|
3200
|
+
retirePreviewBubbles(container);
|
|
3195
3201
|
addMessage2(`\u26A0\uFE0F ${errContent}`, "ai", false, container);
|
|
3196
3202
|
if (typeof showSimpleToast === "function") {
|
|
3197
3203
|
showSimpleToast("\u26A0\uFE0F " + errContent.slice(0, 200));
|