@harness-mix/cli 0.1.7 → 0.1.9
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/NOTICE +12 -0
- package/README.md +51 -43
- package/docs/harness-management.md +1 -1
- package/docs/native-acp.md +7 -2
- package/docs/task-handoff-design.md +65 -0
- package/licenses/codex-styler-Apache-2.0.txt +193 -0
- package/licenses/heige-codex-skin-studio-MIT.txt +22 -0
- package/output/native-build/desktop-controller.mjs +2 -1
- package/output/native-build/renderer-extension.js +651 -9
- package/package.json +188 -188
- package/scripts/acp-capabilities-probe.cjs +1 -0
- package/scripts/build-native.cjs +1 -1
- package/scripts/codex-adapter-test.cjs +44 -0
- package/scripts/collaboration-recovery-test.cjs +3 -0
- package/scripts/e2e-codex.cjs +3 -1
- package/scripts/e2e-native-acp.cjs +1 -1
- package/scripts/error-kind-test.cjs +107 -0
- package/scripts/handoff-checkpoint-test.cjs +38 -0
- package/scripts/integrations-test.cjs +5 -2
- package/scripts/kiro-cursor-adapters-test.cjs +18 -0
- package/scripts/native-acp-depth-test.cjs +1 -1
- package/scripts/native-protocol-test.cjs +60 -4
- package/scripts/native-ui-smoke.cjs +92 -2
- package/scripts/switch-harness-test.cjs +79 -12
- package/scripts/tool-concurrency-regression-test.cjs +8 -6
- package/src/assets/icons/cline-color.svg +1 -0
- package/src/assets/skins/codex-styler/ASSET_LICENSES.md +36 -0
- package/src/assets/skins/codex-styler/NOTICE +11 -0
- package/src/assets/skins/codex-styler/themes/gilded-grandeur/hero.webp +0 -0
- package/src/assets/skins/codex-styler/themes/merry-big-top/hero.webp +0 -0
- package/src/assets/skins/codex-styler/themes/nocturne-studio/hero.webp +0 -0
- package/src/assets/skins/codex-styler/themes/quiet-garden/hero.webp +0 -0
- package/src/assets/skins/heige/ASSET_PROVENANCE.md +56 -0
- package/src/assets/skins/heige/NOTICE.md +13 -0
- package/src/assets/skins/heige/themes/dalao-dianyan/hero.webp +0 -0
- package/src/assets/skins/heige/themes/dalao-dianyan/theme.json +14 -0
- package/src/assets/skins/heige/themes/deepspace-dawn/hero.webp +0 -0
- package/src/assets/skins/heige/themes/deepspace-dawn/theme.json +14 -0
- package/src/assets/skins/heige/themes/deepspace-star/hero.webp +0 -0
- package/src/assets/skins/heige/themes/deepspace-star/theme.json +14 -0
- package/src/assets/skins/heige/themes/dragonball-nimbus/hero.webp +0 -0
- package/src/assets/skins/heige/themes/dragonball-nimbus/theme.json +16 -0
- package/src/assets/skins/heige/themes/dragonball-super-saiyan/hero.webp +0 -0
- package/src/assets/skins/heige/themes/dragonball-super-saiyan/theme.json +16 -0
- package/src/assets/skins/heige/themes/genshin-dawn/hero.webp +0 -0
- package/src/assets/skins/heige/themes/genshin-dawn/theme.json +14 -0
- package/src/assets/skins/heige/themes/genshin-night/hero.webp +0 -0
- package/src/assets/skins/heige/themes/genshin-night/theme.json +14 -0
- package/src/assets/skins/heige/themes/miku-488137/hero.webp +0 -0
- package/src/assets/skins/heige/themes/miku-488137/logo.webp +0 -0
- package/src/assets/skins/heige/themes/miku-488137/polaroid.webp +0 -0
- package/src/assets/skins/heige/themes/miku-488137/theme.json +16 -0
- package/src/assets/skins/heige/themes/naruto-hokage/hero.webp +0 -0
- package/src/assets/skins/heige/themes/naruto-hokage/theme.json +14 -0
- package/src/assets/skins/heige/themes/naruto-sasuke/hero.webp +0 -0
- package/src/assets/skins/heige/themes/naruto-sasuke/theme.json +14 -0
- package/src/assets/skins/heige/themes/wuthering-echo/hero.webp +0 -0
- package/src/assets/skins/heige/themes/wuthering-echo/theme.json +14 -0
- package/src/assets/skins/heige/themes/wuthering-tide/hero.webp +0 -0
- package/src/assets/skins/heige/themes/wuthering-tide/theme.json +14 -0
- package/src/main/adapters/cline.js +22 -0
- package/src/main/adapters/codex.js +78 -8
- package/src/main/adapters/index.js +2 -1
- package/src/main/adapters/native-acp-command.js +1 -0
- package/src/main/harness-adapter/error-kind.js +82 -0
- package/src/main/harness-adapter/event-normalizer.js +7 -1
- package/src/main/host/core-session.js +1 -1
- package/src/main/host/handoff-access.js +23 -4
- package/src/main/host/handoff-checkpoints.js +9 -2
- package/src/main/host/handoff-tools.js +3 -0
- package/src/main/host/handoff.js +11 -2
- package/src/main/host/runtime.js +272 -163
- package/src/main/host/session-history.js +54 -15
- package/src/main/native/icons.js +3 -2
- package/src/main/native/pets.js +234 -0
- package/src/main/native/protocol.js +197 -56
- package/src/main/protocol-core/projector.js +44 -41
- package/src/native-ui/desktop-control/dist/production-controller.d.ts.map +1 -1
- package/src/native-ui/desktop-control/dist/production-controller.js +1 -0
- package/src/native-ui/desktop-control/dist/production-controller.js.map +1 -1
- package/src/native-ui/desktop-control/dist/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/desktop-control/src/production-controller.ts +1 -0
- package/src/native-ui/desktop-control/test/production-controller.test.ts +1 -0
- package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts +4 -2
- package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-agent-icon.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-agent-picker.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-harness-mentions.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-settings-lifecycle.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-sidebar-agent-icons.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/connections-page.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/icons.d.ts +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/icons.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/localization.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/shell.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/skin-market.d.ts +4 -0
- package/src/native-ui/renderer-extension/dist/types/settings/skin-market.d.ts.map +1 -0
- package/src/native-ui/renderer-extension/dist/types/settings/skin-runtime.d.ts +31 -0
- package/src/native-ui/renderer-extension/dist/types/settings/skin-runtime.d.ts.map +1 -0
- package/src/native-ui/renderer-extension/dist/types/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/renderer-extension/dist/types/versioned-renderer-adapter.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/package.json +1 -1
- package/src/native-ui/renderer-extension/src/agent-selection-state.ts +16 -0
- package/src/native-ui/renderer-extension/src/assets.d.ts +5 -0
- package/src/native-ui/renderer-extension/src/renderer-agent-icon.ts +5 -4
- package/src/native-ui/renderer-extension/src/renderer-agent-picker.ts +1 -0
- package/src/native-ui/renderer-extension/src/renderer-binding-probe.ts +9 -6
- package/src/native-ui/renderer-extension/src/renderer-harness-handoff.ts +2 -2
- package/src/native-ui/renderer-extension/src/renderer-harness-mentions.ts +2 -0
- package/src/native-ui/renderer-extension/src/renderer-settings-lifecycle.ts +2 -0
- package/src/native-ui/renderer-extension/src/renderer-sidebar-agent-icons.ts +1 -0
- package/src/native-ui/renderer-extension/src/settings/connections-page.ts +2 -0
- package/src/native-ui/renderer-extension/src/settings/icons.ts +6 -0
- package/src/native-ui/renderer-extension/src/settings/localization.ts +4 -2
- package/src/native-ui/renderer-extension/src/settings/pages.ts +5 -2
- package/src/native-ui/renderer-extension/src/settings/shell.ts +3 -2
- package/src/native-ui/renderer-extension/src/settings/skin-market.css +213 -0
- package/src/native-ui/renderer-extension/src/settings/skin-market.ts +174 -0
- package/src/native-ui/renderer-extension/src/settings/skin-runtime.ts +399 -0
- package/src/native-ui/renderer-extension/src/versioned-renderer-adapter.ts +2 -1
- package/src/native-ui/renderer-extension/test/settings/localization.test.ts +11 -1
- package/src/native-ui/renderer-extension/test/settings/shell.test.ts +3 -0
- package/src/native-ui/renderer-extension/test/settings/skin-runtime.test.ts +136 -0
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.d.ts +7 -0
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.d.ts.map +1 -1
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.js +3 -0
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.js.map +1 -1
- package/src/native-ui/shared-contracts/dist/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/shared-contracts/src/thread-harness-switch.ts +3 -0
|
@@ -28,6 +28,7 @@ const PACKAGE_JSON_PATH = path.join(REPO_ROOT, 'package.json');
|
|
|
28
28
|
|
|
29
29
|
const ALIASES = { workbuddy: 'codebuddy', 'claude-code': 'claude', 'deepseek-harness': 'dsh', 'codex-harness': 'codex' };
|
|
30
30
|
const externalId = id => ({ workbuddy: 'codebuddy', claude: 'claude-code', dsh: 'deepseek-harness', codex: 'codex-harness' }[id] || id);
|
|
31
|
+
const { errorActions } = require('../harness-adapter/error-kind');
|
|
31
32
|
const modelRef = model => ({ id: Buffer.from(JSON.stringify({ id: model.id, provider: model.provider })).toString('base64url') });
|
|
32
33
|
const routeModel = harnessId => ['pi', 'claude-code', 'deepseek-harness', 'antigravity', 'omp', 'opencode', 'grok'].includes(harnessId)
|
|
33
34
|
? `codexhost/${harnessId}-native`
|
|
@@ -47,6 +48,7 @@ const HARNESS_INSTALL_COMMANDS = {
|
|
|
47
48
|
antigravity: { win32: 'npm install -g @google/antigravity-cli', default: 'npm install -g @google/antigravity-cli' },
|
|
48
49
|
openclaw: { win32: 'npm install -g openclaw', default: 'npm install -g openclaw' },
|
|
49
50
|
hermes: { win32: 'pip install hermes-agent', default: 'pip3 install hermes-agent' },
|
|
51
|
+
cline: { win32: 'npm install -g cline', default: 'npm install -g cline' },
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
const HARNESS_AUTH_INFO = {
|
|
@@ -66,6 +68,7 @@ const HARNESS_AUTH_INFO = {
|
|
|
66
68
|
hermes: { name: 'Hermes', plan: 'Nous Hermes', label: 'Hermes Agent 配置', loginCommand: null, configHint: '~/.hermes/ 配置文件或各模型 API Key' },
|
|
67
69
|
zcode: { name: 'ZCode', plan: 'ZCode AI', label: 'ZCode 账号与配置', loginCommand: null, configHint: 'ZCode 客户端或配置文件' },
|
|
68
70
|
trae: { name: 'Trae', plan: 'Trae AI', label: 'Trae 账号与配置', loginCommand: null, configHint: 'Trae 客户端登录状态' },
|
|
71
|
+
cline: { name: 'Cline', plan: 'Cline Providers', label: 'Cline CLI 认证', loginCommand: 'cline auth', configHint: '命令行 cline auth 或 ~/.cline/data 配置' },
|
|
69
72
|
};
|
|
70
73
|
|
|
71
74
|
const MODEL_REF_ID = /^[A-Za-z0-9._~-]{1,512}$/;
|
|
@@ -150,6 +153,52 @@ function unifiedDiff(change, kindType) {
|
|
|
150
153
|
return [`diff --git a/${file} b/${file}`, ...(/^---\s/m.test(body) ? [] : headers), body].filter(Boolean).join('\n');
|
|
151
154
|
}
|
|
152
155
|
|
|
156
|
+
// 各 harness 终端工具的命名集合;命中即把该工具调用投影为原生 commandExecution,
|
|
157
|
+
// 让 Desktop 显示「正在运行/运行了命令」而不是笼统的「已使用 Harness Mix 集成」。
|
|
158
|
+
const SHELL_TOOL_TITLE = /bash|shell|terminal|console|exec|powershell|pwsh|\bcmd\b|command|命令|终端/i;
|
|
159
|
+
|
|
160
|
+
function shellCommandText(item) {
|
|
161
|
+
if (!SHELL_TOOL_TITLE.test(String(item.title || ''))) return null;
|
|
162
|
+
const input = item.input;
|
|
163
|
+
if (typeof input !== 'string' || !input.trim()) return String(item.title || 'command');
|
|
164
|
+
try {
|
|
165
|
+
const parsed = JSON.parse(input);
|
|
166
|
+
if (parsed && typeof parsed === 'object') {
|
|
167
|
+
const cmd = parsed.command ?? parsed.cmd ?? parsed.script ?? parsed.input;
|
|
168
|
+
if (typeof cmd === 'string' && cmd.trim()) return cmd;
|
|
169
|
+
}
|
|
170
|
+
} catch {}
|
|
171
|
+
return input;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 官方 app-server 由 Rust 把命令解析成 commandActions;这里只对无引号/管道/重定向的
|
|
175
|
+
// 简单单命令做保守分类(读取/搜索/列目录),其余一律 unknown,不臆造命令行为。
|
|
176
|
+
function classifyCommandAction(command) {
|
|
177
|
+
if (/["'`|;&<>()[\]{}$]/.test(command)) return { type: 'unknown', command };
|
|
178
|
+
const tokens = command.trim().split(/\s+/).filter(Boolean);
|
|
179
|
+
const exe = (tokens[0] || '').toLowerCase().replace(/^.*[\\/]/, '').replace(/\.exe$/, '');
|
|
180
|
+
const args = tokens.slice(1).filter(t => !t.startsWith('-'));
|
|
181
|
+
if (['cat', 'head', 'tail', 'type', 'get-content', 'more'].includes(exe) && args.length === 1)
|
|
182
|
+
return { type: 'read', command, name: args[0].split(/[\\/]/).pop(), path: args[0] };
|
|
183
|
+
if (['rg', 'grep', 'egrep', 'fgrep', 'findstr'].includes(exe) && args.length >= 1)
|
|
184
|
+
return { type: 'search', command, query: args[0] };
|
|
185
|
+
if (['ls', 'dir', 'tree'].includes(exe))
|
|
186
|
+
return { type: 'listFiles', command, ...(args[0] ? { path: args[0] } : {}) };
|
|
187
|
+
return { type: 'unknown', command };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Desktop 权限菜单/回合参数中的权限字段(thread/settings/update 与 turn/start 用 sandboxPolicy,
|
|
191
|
+
// thread/start 用 sandbox),统一存为 turnPermissions { approvalPolicy, approvalsReviewer, sandboxPolicy, permissions }
|
|
192
|
+
function pickTurnPermissions(params = {}) {
|
|
193
|
+
const picked = {};
|
|
194
|
+
if (typeof params.approvalPolicy === 'string') picked.approvalPolicy = params.approvalPolicy;
|
|
195
|
+
if (typeof params.approvalsReviewer === 'string') picked.approvalsReviewer = params.approvalsReviewer;
|
|
196
|
+
const sandbox = params.sandboxPolicy ?? params.sandbox;
|
|
197
|
+
if (sandbox && typeof sandbox === 'object') picked.sandboxPolicy = sandbox;
|
|
198
|
+
if (typeof params.permissions === 'string') picked.permissions = params.permissions;
|
|
199
|
+
return Object.keys(picked).length ? picked : null;
|
|
200
|
+
}
|
|
201
|
+
|
|
153
202
|
function projectItem(item) {
|
|
154
203
|
const base = { id: item.id };
|
|
155
204
|
if (item.type === 'user_message') return { ...base, type: 'userMessage', content: [
|
|
@@ -175,23 +224,33 @@ function projectItem(item) {
|
|
|
175
224
|
agentsStates: job.child_thread_id ? { [job.child_thread_id]: { status,
|
|
176
225
|
message: job.attention?.message || job.attention?.title || job.result || job.error || null } } : {} };
|
|
177
226
|
}
|
|
178
|
-
if (item.type === 'tool_call')
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
227
|
+
if (item.type === 'tool_call') {
|
|
228
|
+
const status = terminal(item.status) ? (item.state === 'error' ? 'failed' : 'completed') : 'inProgress';
|
|
229
|
+
const command = shellCommandText(item);
|
|
230
|
+
if (command != null) {
|
|
231
|
+
// 退出码未知不臆造(exitCode: null);durationMs 来自 Core 真实时间戳
|
|
232
|
+
return { ...base, type: 'commandExecution', command, cwd: null, status,
|
|
233
|
+
commandActions: [classifyCommandAction(command)],
|
|
234
|
+
aggregatedOutput: item.output ? String(item.output) : null,
|
|
235
|
+
exitCode: null, durationMs: terminal(item.status) ? Math.max(0, (item.updatedAt ?? 0) - (item.createdAt ?? 0)) : null, processId: null };
|
|
236
|
+
}
|
|
237
|
+
return { ...base, type: 'dynamicToolCall', namespace: 'harness-mix', tool: item.title || 'tool',
|
|
238
|
+
arguments: item.input || {}, contentItems: item.output ? [{ type: 'inputText', text: String(item.output) }] : null,
|
|
239
|
+
status, success: terminal(item.status) ? item.state !== 'error' : null };
|
|
240
|
+
}
|
|
182
241
|
if (item.type === 'file_change') return { ...base, type: 'fileChange', status: terminal(item.status) ? 'completed' : 'inProgress',
|
|
183
242
|
changes: (item.changes || [item]).map(change => {
|
|
184
243
|
const kind = change.changeType === 'deleted' ? { type: 'delete' } : change.changeType === 'added' ? { type: 'add' } : { type: 'update', move_path: null };
|
|
185
244
|
return { path: change.path || change.file || '', kind, diff: unifiedDiff(change, kind.type) };
|
|
186
245
|
}) };
|
|
187
|
-
if (item.type === 'context_compaction' || item.type === 'contextCompaction') return { ...base, type: 'contextCompaction' };
|
|
188
|
-
if (item.type === 'verification_report') {
|
|
189
|
-
const report = item.report ?? {};
|
|
190
|
-
const failed = report.status === 'failed';
|
|
191
|
-
return { ...base, type: 'mcpToolCall', server: 'harness-mix', tool: 'verification_gate',
|
|
192
|
-
arguments: { mode: report.mode ?? 'off' }, result: { content: [{ type: 'text', text: JSON.stringify(report) }], structuredContent: report },
|
|
193
|
-
status: failed ? 'failed' : 'completed', error: failed ? { message: 'Verification gate failed' } : null, durationMs: Math.max(0, (report.completedAt ?? 0) - (report.startedAt ?? 0)) };
|
|
194
|
-
}
|
|
246
|
+
if (item.type === 'context_compaction' || item.type === 'contextCompaction') return { ...base, type: 'contextCompaction' };
|
|
247
|
+
if (item.type === 'verification_report') {
|
|
248
|
+
const report = item.report ?? {};
|
|
249
|
+
const failed = report.status === 'failed';
|
|
250
|
+
return { ...base, type: 'mcpToolCall', server: 'harness-mix', tool: 'verification_gate',
|
|
251
|
+
arguments: { mode: report.mode ?? 'off' }, result: { content: [{ type: 'text', text: JSON.stringify(report) }], structuredContent: report },
|
|
252
|
+
status: failed ? 'failed' : 'completed', error: failed ? { message: 'Verification gate failed' } : null, durationMs: Math.max(0, (report.completedAt ?? 0) - (report.startedAt ?? 0)) };
|
|
253
|
+
}
|
|
195
254
|
return null;
|
|
196
255
|
}
|
|
197
256
|
|
|
@@ -206,10 +265,14 @@ class NativeProtocol {
|
|
|
206
265
|
emit,
|
|
207
266
|
});
|
|
208
267
|
this.approvals = new Map();
|
|
268
|
+
this.pets = require('./pets').createPetMarket();
|
|
209
269
|
this.published = new Map();
|
|
210
270
|
this.steering = new Map(); // threadId -> in-flight steer promise
|
|
211
271
|
this.steerReceipts = new Map(); // `${threadId}\0${clientUserMessageId}` -> bounded delivery receipt
|
|
212
272
|
this.queues = new Map(); // threadId -> Array<{ id, input, clientUserMessageId, createdAt }>
|
|
273
|
+
this.queueNotifications = new Map(); // response-first queue notifications, coalesced per thread
|
|
274
|
+
this.queueStarts = new Set(); // queued submission ids currently being accepted by a native harness
|
|
275
|
+
this.closed = false;
|
|
213
276
|
this.unsubscribe = runtime.core.subscribe(({ event, projected }) => this.onCore(event, projected));
|
|
214
277
|
// Host 侧新建的线程(协作子任务等)也要通知 Desktop 侧栏,与 thread/start 同一契约
|
|
215
278
|
this.unsubscribeRuntime = runtime.subscribe(event => {
|
|
@@ -223,21 +286,41 @@ class NativeProtocol {
|
|
|
223
286
|
if (!this.queues.has(threadId)) this.queues.set(threadId, []);
|
|
224
287
|
return this.queues.get(threadId);
|
|
225
288
|
}
|
|
226
|
-
emitQueueChanged(threadId) {
|
|
227
|
-
|
|
289
|
+
emitQueueChanged(threadId) {
|
|
290
|
+
// Desktop mutates its local queue cache after the request promise resolves. Emitting
|
|
291
|
+
// synchronously lets its refresh replace that cache first; an edit then holds the old
|
|
292
|
+
// message id and fails with "queued follow-up no longer exists". Match app-server
|
|
293
|
+
// ordering: return the mutation response first, then notify this and other windows.
|
|
294
|
+
if (this.closed || this.queueNotifications.has(threadId)) return;
|
|
295
|
+
const timer = setTimeout(() => {
|
|
296
|
+
this.queueNotifications.delete(threadId);
|
|
297
|
+
this.emit({ method: 'thread/queue/changed', params: { threadId } });
|
|
298
|
+
}, 0);
|
|
299
|
+
timer.unref?.();
|
|
300
|
+
this.queueNotifications.set(threadId, timer);
|
|
301
|
+
}
|
|
302
|
+
thread(id) {
|
|
303
|
+
if (!id) return undefined;
|
|
304
|
+
return this.runtime.threads.some(t => t.id === id) ? this.runtime.getThread(id) : undefined;
|
|
228
305
|
}
|
|
229
|
-
thread(id) {
|
|
230
|
-
if (!id) return undefined;
|
|
231
|
-
return this.runtime.threads.some(t => t.id === id) ? this.runtime.getThread(id) : undefined;
|
|
232
|
-
}
|
|
233
306
|
owns(id) { return Boolean(this.thread(id)); }
|
|
234
|
-
turn(turn) {
|
|
235
|
-
|
|
307
|
+
turn(turn) {
|
|
308
|
+
// 官方 Turn 合约的时间字段:startedAt/completedAt(epoch 秒,Desktop 恢复线程时经
|
|
309
|
+
// kBt(x*1e3) 还原)与 durationMs(turn/completed 处理器直接采用)。缺失时 Desktop
|
|
310
|
+
// 无法合成 worked-for 计时项,完成回合只回退显示“已使用 Harness Mix 集成”。
|
|
311
|
+
const startedAt = turn.startedAt ?? turn.createdAt ?? null;
|
|
312
|
+
const completedAt = turn.completedAt ?? null;
|
|
313
|
+
return { id: turn.id, status: turnStatus(turn.status), error: turn.error ? { message: String(turn.error), codexErrorInfo: turn.codexErrorInfo ?? null, additionalDetails: null } : null,
|
|
314
|
+
startedAt: startedAt != null ? Math.floor(startedAt / 1000) : null,
|
|
315
|
+
completedAt: completedAt != null ? Math.floor(completedAt / 1000) : null,
|
|
316
|
+
durationMs: startedAt != null && completedAt != null ? Math.max(0, completedAt - startedAt) : null,
|
|
317
|
+
items: this.runtime.core.getItemsForTurn(turn.id).map(projectItem).filter(Boolean) };
|
|
318
|
+
}
|
|
236
319
|
projectThread(thread, includeTurns = true) {
|
|
237
320
|
// Projection shape mirrors the upstream codexhost external-thread contract: every
|
|
238
321
|
// field the Desktop sidebar/composer reads must be present with the same defaults.
|
|
239
322
|
const updatedAt = Math.floor((thread.updatedAt || thread.createdAt) / 1000);
|
|
240
|
-
return { id: thread.id, preview: thread.messages?.find(m => m.role === 'user')?.text || thread.preview || thread.title,
|
|
323
|
+
return { id: thread.id, preview: thread.messages?.find(m => m.role === 'user')?.text || thread.preview || thread.title,
|
|
241
324
|
ephemeral: thread.ephemeral === true, modelProvider: 'codexhost', model: routeModel(externalId(thread.harnessId)), reasoningEffort: null,
|
|
242
325
|
section: thread.section ?? null, sectionEnteredAt: thread.sectionEnteredAt ?? null, projectId: thread.projectId ?? null,
|
|
243
326
|
createdAt: Math.floor(thread.createdAt / 1000),
|
|
@@ -249,7 +332,14 @@ class NativeProtocol {
|
|
|
249
332
|
sessionId: thread.id, forkedFromId: thread.forkedFrom ?? null, parentThreadId: thread.parentThreadId ?? null,
|
|
250
333
|
// 跨 Harness 原地切换血缘:链上每条是某 Harness 曾用的原生会话引用(切回可 resume)
|
|
251
334
|
harnessChain: (thread.harnessChain ?? []).map(e => ({ harnessId: externalId(e.harnessId), at: e.at })),
|
|
252
|
-
pendingHarnessSwitch: thread.pendingHandoff ? {
|
|
335
|
+
pendingHarnessSwitch: thread.pendingHandoff ? {
|
|
336
|
+
checkpointId: thread.pendingHandoff.checkpointId,
|
|
337
|
+
fromHarnessId: externalId(thread.pendingHandoff.fromHarnessId),
|
|
338
|
+
toHarnessId: externalId(thread.pendingHandoff.toHarnessId || thread.harnessId),
|
|
339
|
+
phase: thread.pendingHandoff.phase || 'ready',
|
|
340
|
+
intent: thread.pendingHandoff.intent || 'continue',
|
|
341
|
+
note: thread.pendingHandoff.note ?? null,
|
|
342
|
+
} : null,
|
|
253
343
|
canAcceptDirectInput: true, historyMode: 'legacy', isPinned: false, extra: null,
|
|
254
344
|
isolation: thread.isolation ?? 'shared',
|
|
255
345
|
workspace: thread.workspace ? { mode: thread.workspace.mode, branch: thread.workspace.branch, root: thread.workspace.root } : null,
|
|
@@ -350,7 +440,24 @@ class NativeProtocol {
|
|
|
350
440
|
if (method === 'codexhost/harness/session-import/list') return this.runtime.history.list(params);
|
|
351
441
|
if (method === 'codexhost/harness/session-import/import') return this.runtime.history.import(params);
|
|
352
442
|
if (method === 'codexhost/collaboration/agents') return [...this.runtime.adapters.values()].map(a => ({ id: externalId(a.manifest.id), name: a.manifest.name, available: !!this.runtime.status[a.manifest.id]?.available, lead: a.manifest.capabilities?.collaborationTools === true }));
|
|
443
|
+
// 桌宠市场:官方预载(Codex 安装包 asar 提取)与 ~/.codex/pets 安装管理
|
|
444
|
+
if (method === 'codexhost/pets/catalog') return this.pets.catalog();
|
|
445
|
+
if (method === 'codexhost/pets/preview') return this.pets.preview(params);
|
|
446
|
+
if (method === 'codexhost/pets/install') return this.pets.install(params);
|
|
447
|
+
if (method === 'codexhost/pets/uninstall') return this.pets.uninstall(params);
|
|
353
448
|
const thread = this.thread(params.threadId);
|
|
449
|
+
// 失败回合分类查询:Renderer 据此在输入框下方渲染只真正帮得上忙的动作按钮
|
|
450
|
+
if (method === 'codexhost/harness/turn-error') {
|
|
451
|
+
if (!thread) throw new Error('Unknown thread');
|
|
452
|
+
const kind = thread.errorKind ?? null;
|
|
453
|
+
const meta = HARNESS_AUTH_INFO[externalId(thread.harnessId)] || HARNESS_AUTH_INFO[thread.harnessId];
|
|
454
|
+
return {
|
|
455
|
+
threadId: thread.id,
|
|
456
|
+
error: thread.error ?? null,
|
|
457
|
+
errorKind: kind,
|
|
458
|
+
actions: kind ? errorActions(kind, { canLogin: Boolean(meta?.loginCommand) }) : [],
|
|
459
|
+
};
|
|
460
|
+
}
|
|
354
461
|
if (method === 'harness-mix/runtime/inspect') return {
|
|
355
462
|
owner: 'harness-mix',
|
|
356
463
|
runtime: 'src/main/host/runtime.js',
|
|
@@ -575,9 +682,9 @@ class NativeProtocol {
|
|
|
575
682
|
}
|
|
576
683
|
return { accounts };
|
|
577
684
|
}
|
|
578
|
-
if (method === 'codexhost/harness/plugins/list') return { plugins: this.runtime.snapshot().adapters.map(a => ({ id: externalId(a.id), name: a.id === 'codex' ? 'Codex(协作)' : a.name, version: '0.1.0', icon: `data:image/svg+xml;base64,${Buffer.from(getHarnessSvg(a.id)).toString('base64')}` })) };
|
|
579
|
-
if (method === 'codexhost/storage/inspect') return this.runtime.inspectStorage();
|
|
580
|
-
if (method === 'codexhost/storage/optimize') return this.runtime.optimizeStorage();
|
|
685
|
+
if (method === 'codexhost/harness/plugins/list') return { plugins: this.runtime.snapshot().adapters.map(a => ({ id: externalId(a.id), name: a.id === 'codex' ? 'Codex(协作)' : a.name, version: '0.1.0', icon: `data:image/svg+xml;base64,${Buffer.from(getHarnessSvg(a.id)).toString('base64')}` })) };
|
|
686
|
+
if (method === 'codexhost/storage/inspect') return this.runtime.inspectStorage();
|
|
687
|
+
if (method === 'codexhost/storage/optimize') return this.runtime.optimizeStorage();
|
|
581
688
|
if (method === 'codexhost/harness/inspect') return this.inspect(params.harnessId);
|
|
582
689
|
if (method === 'codexhost/harness/install') {
|
|
583
690
|
const local = ALIASES[params.harnessId] || params.harnessId;
|
|
@@ -648,6 +755,7 @@ class NativeProtocol {
|
|
|
648
755
|
model: selectedModel, thinking: effectiveRoute.thinkingOptionId, permissionMode: effectiveRoute.permissionModeId,
|
|
649
756
|
...(accountContext || {}),
|
|
650
757
|
...(isWorktree ? { worktree: true } : {}),
|
|
758
|
+
...(pickTurnPermissions(params) ? { turnPermissions: pickTurnPermissions(params) } : {}),
|
|
651
759
|
} });
|
|
652
760
|
if (created.error) throw new Error(created.error);
|
|
653
761
|
const result = { thread: this.projectThread(created), model: params.model, modelProvider: 'harness-mix', cwd: created.cwd,
|
|
@@ -658,10 +766,10 @@ class NativeProtocol {
|
|
|
658
766
|
if (method === 'codexhost/thread/workspace/review') return this.runtime.reviewThreadWorkspace(params.threadId);
|
|
659
767
|
if (method === 'codexhost/thread/workspace/apply') return this.runtime.applyThreadWorkspace(params.threadId, params.digest);
|
|
660
768
|
if (method === 'codexhost/thread/workspace/discard') return this.runtime.discardThreadWorkspace(params.threadId);
|
|
661
|
-
if (method === 'codexhost/thread/workspace/push') return this.runtime.pushThreadWorkspace(params.threadId, params);
|
|
662
|
-
if (method === 'codexhost/thread/verification/get') return this.runtime.verificationState(params.threadId);
|
|
663
|
-
if (method === 'codexhost/thread/verification/configure') return this.runtime.configureVerification(params.threadId, params.policy);
|
|
664
|
-
if (method === 'codexhost/thread/verification/run') return this.runtime.runVerification(params.threadId);
|
|
769
|
+
if (method === 'codexhost/thread/workspace/push') return this.runtime.pushThreadWorkspace(params.threadId, params);
|
|
770
|
+
if (method === 'codexhost/thread/verification/get') return this.runtime.verificationState(params.threadId);
|
|
771
|
+
if (method === 'codexhost/thread/verification/configure') return this.runtime.configureVerification(params.threadId, params.policy);
|
|
772
|
+
if (method === 'codexhost/thread/verification/run') return this.runtime.runVerification(params.threadId);
|
|
665
773
|
if (!thread) {
|
|
666
774
|
if (method.startsWith('codexhost/')) throw new Error(`Harness Mix does not implement ${method}`);
|
|
667
775
|
return undefined;
|
|
@@ -729,22 +837,16 @@ class NativeProtocol {
|
|
|
729
837
|
? queue.findIndex(item => item.id === params.queuedSubmissionId)
|
|
730
838
|
: 0;
|
|
731
839
|
if (idx === -1 || !queue[idx]) throw new Error('Queued submission not found');
|
|
732
|
-
|
|
733
|
-
this.emitQueueChanged(thread.id);
|
|
734
|
-
const { text, attachments } = await prepareInput(submission.input, thread.cwd);
|
|
735
|
-
if (attachments.length && !this.runtime.getCapabilities(thread.harnessId).conversation.attachments) {
|
|
736
|
-
throw new Error('当前 Harness 不支持图片附件');
|
|
737
|
-
}
|
|
738
|
-
if (this.runtime.execution.isRunning(thread.id)) {
|
|
739
|
-
// 正在执行中:打断当前回合并立即执行该排队消息
|
|
740
|
-
const turnId = await this.steerExclusive(thread, thread.currentTurn?.id, text, attachments);
|
|
741
|
-
const started = this.runtime.core.getTurn(turnId) || thread.currentTurn;
|
|
742
|
-
return { turn: this.turn(started) };
|
|
743
|
-
}
|
|
744
|
-
const turn = await this.startNativeTurn(thread, text, attachments);
|
|
745
|
-
return { turn: this.turn(turn) };
|
|
840
|
+
return { turn: this.turn(await this.startQueuedSubmission(thread, queue[idx])) };
|
|
746
841
|
}
|
|
747
842
|
if (method === 'thread/metadata/update') return { thread: this.projectThread(await this.runtime.updateThreadMetadata(thread.id, params.gitInfo)) };
|
|
843
|
+
// Desktop 权限菜单(请求批准/帮我批准/完全访问)推送的线程级设置:原样存储并持久化,
|
|
844
|
+
// 后续回合经 codex 适配器转发到原生 app-server,让显示选择与实际生效一致
|
|
845
|
+
if (method === 'thread/settings/update') {
|
|
846
|
+
const picked = pickTurnPermissions(params);
|
|
847
|
+
if (picked) await this.runtime.setOptions(thread.id, { turnPermissions: { ...(thread.options?.turnPermissions ?? {}), ...picked } });
|
|
848
|
+
return {};
|
|
849
|
+
}
|
|
748
850
|
if (method === 'thread/section/move') {
|
|
749
851
|
if (params.sectionId !== null && (typeof params.sectionId !== 'string' || !params.sectionId)) throw new Error('Invalid sectionId');
|
|
750
852
|
let section = null;
|
|
@@ -761,10 +863,17 @@ class NativeProtocol {
|
|
|
761
863
|
await this.runtime.setThreadSection(thread.id, section, params.beforeThreadId);
|
|
762
864
|
return {};
|
|
763
865
|
}
|
|
764
|
-
if (method === 'thread/resume')
|
|
866
|
+
if (method === 'thread/resume') {
|
|
867
|
+
// 回显线程实际生效的权限(Desktop 据此渲染 composer 权限指示),而不是硬编码默认值
|
|
868
|
+
const perms = thread.options?.turnPermissions ?? null;
|
|
869
|
+
return { thread: this.projectThread(thread), model: routeModel(externalId(thread.harnessId)), modelProvider: 'harness-mix', cwd: thread.cwd,
|
|
870
|
+
approvalPolicy: perms?.approvalPolicy ?? 'on-request', approvalsReviewer: perms?.approvalsReviewer ?? null,
|
|
871
|
+
sandbox: perms?.sandboxPolicy ?? { type: 'workspaceWrite', writableRoots: [thread.cwd], networkAccess: false, excludeTmpdirEnvVar: false, excludeSlashTmp: false }, reasoningEffort: null };
|
|
872
|
+
}
|
|
765
873
|
if (method === 'turn/start') {
|
|
766
874
|
const { text, attachments } = await prepareInput(params.input, thread.cwd);
|
|
767
|
-
|
|
875
|
+
// Desktop fallback 路径在每个回合都携带完整权限参数;缺失时由适配器回退到线程级设置
|
|
876
|
+
return { turn: this.turn(await this.startNativeTurn(thread, text, attachments, undefined, pickTurnPermissions(params))) };
|
|
768
877
|
}
|
|
769
878
|
// External steering: cancel the active Turn, wait for it to fully settle, then start
|
|
770
879
|
// the new input as a real new Turn. Never guess a stale target, never auto-start on
|
|
@@ -851,12 +960,12 @@ class NativeProtocol {
|
|
|
851
960
|
}
|
|
852
961
|
// 原地切换 Harness:会话历史保留,下条消息携带一次性上下文信封(/switch 指令的 RPC 等价物)
|
|
853
962
|
if (method === 'codexhost/thread/harness/switch') {
|
|
854
|
-
await this.runtime.switchHarness(thread.id, ALIASES[params.harnessId] || params.harnessId, {
|
|
963
|
+
const result = await this.runtime.switchHarness(thread.id, ALIASES[params.harnessId] || params.harnessId, {
|
|
855
964
|
note: typeof params.note === 'string' ? params.note : undefined,
|
|
856
965
|
intent: params.intent,
|
|
857
966
|
includes: params.includes,
|
|
858
967
|
});
|
|
859
|
-
return {
|
|
968
|
+
return { ...result, fromHarnessId: externalId(result.fromHarnessId), toHarnessId: externalId(result.toHarnessId) };
|
|
860
969
|
}
|
|
861
970
|
if (method === 'thread/fork' || method === 'codexhost/thread/fork') {
|
|
862
971
|
if (params.ephemeral || params.threadSource || params.excludeTurns) {
|
|
@@ -889,10 +998,10 @@ class NativeProtocol {
|
|
|
889
998
|
const converted = projectItem(item);
|
|
890
999
|
if (converted) {
|
|
891
1000
|
const previous = this.published.get(item.id);
|
|
892
|
-
if (!previous) notify('item/started', { item: converted });
|
|
1001
|
+
if (!previous) notify('item/started', { item: converted, startedAtMs: item.createdAt ?? Date.now() });
|
|
893
1002
|
if (item.type === 'agent_message' && item.content?.length > (previous?.content?.length || 0)) notify('item/agentMessage/delta', { itemId: item.id, delta: item.content.slice(previous?.content?.length || 0) });
|
|
894
1003
|
if (item.type === 'reasoning' && item.content?.length > (previous?.content?.length || 0)) notify('item/reasoning/summaryTextDelta', { itemId: item.id, summaryIndex: 0, delta: item.content.slice(previous?.content?.length || 0) });
|
|
895
|
-
if (terminal(item.status) && (!terminal(previous?.status) || ['file_change', 'tool_call'].includes(item.type) && JSON.stringify(converted) !== JSON.stringify(projectItem(previous)))) notify('item/completed', { item: converted });
|
|
1004
|
+
if (terminal(item.status) && (!terminal(previous?.status) || ['file_change', 'tool_call'].includes(item.type) && JSON.stringify(converted) !== JSON.stringify(projectItem(previous)))) notify('item/completed', { item: converted, completedAtMs: item.updatedAt ?? item.createdAt ?? Date.now() });
|
|
896
1005
|
this.published.set(item.id, structuredClone(item));
|
|
897
1006
|
if (this.published.size > 200) {
|
|
898
1007
|
const oldest = this.published.keys().next().value;
|
|
@@ -926,11 +1035,8 @@ class NativeProtocol {
|
|
|
926
1035
|
const queue = this.getQueue(threadId);
|
|
927
1036
|
const currentThread = this.thread(threadId);
|
|
928
1037
|
if (queue.length > 0 && currentThread && !this.runtime.execution.isRunning(threadId) && !this.steering.has(threadId) && !this.runtime.sending?.has(threadId)) {
|
|
929
|
-
const [submission] = queue.splice(0, 1);
|
|
930
|
-
this.emitQueueChanged(threadId);
|
|
931
1038
|
try {
|
|
932
|
-
|
|
933
|
-
await this.startNativeTurn(currentThread, text, attachments);
|
|
1039
|
+
await this.startQueuedSubmission(currentThread, queue[0]);
|
|
934
1040
|
} catch (err) {
|
|
935
1041
|
console.error(`Failed to auto-drain queued submission for thread ${threadId}:`, err);
|
|
936
1042
|
}
|
|
@@ -939,13 +1045,41 @@ class NativeProtocol {
|
|
|
939
1045
|
}
|
|
940
1046
|
}
|
|
941
1047
|
}
|
|
942
|
-
async
|
|
1048
|
+
async startQueuedSubmission(thread, submission) {
|
|
1049
|
+
if (this.queueStarts.has(submission.id)) throw new Error('Queued submission is already starting');
|
|
1050
|
+
this.queueStarts.add(submission.id);
|
|
1051
|
+
try {
|
|
1052
|
+
// Keep the item addressable until the native harness has accepted a real Turn. If
|
|
1053
|
+
// input preparation or turn startup fails, Desktop can still edit/retry/delete it.
|
|
1054
|
+
const { text, attachments } = await prepareInput(submission.input, thread.cwd);
|
|
1055
|
+
if (attachments.length && !this.runtime.getCapabilities(thread.harnessId).conversation.attachments) {
|
|
1056
|
+
throw new Error('当前 Harness 不支持图片附件');
|
|
1057
|
+
}
|
|
1058
|
+
let started;
|
|
1059
|
+
if (this.runtime.execution.isRunning(thread.id)) {
|
|
1060
|
+
const turnId = await this.steerExclusive(thread, thread.currentTurn?.id, text, attachments);
|
|
1061
|
+
started = this.runtime.core.getTurn(turnId) || thread.currentTurn;
|
|
1062
|
+
} else {
|
|
1063
|
+
started = await this.startNativeTurn(thread, text, attachments);
|
|
1064
|
+
}
|
|
1065
|
+
const queue = this.getQueue(thread.id);
|
|
1066
|
+
const idx = queue.findIndex(item => item.id === submission.id);
|
|
1067
|
+
if (idx !== -1) {
|
|
1068
|
+
queue.splice(idx, 1);
|
|
1069
|
+
this.emitQueueChanged(thread.id);
|
|
1070
|
+
}
|
|
1071
|
+
return started;
|
|
1072
|
+
} finally {
|
|
1073
|
+
this.queueStarts.delete(submission.id);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
async startNativeTurn(thread, text, attachments, commandId, turnPermissions) {
|
|
943
1077
|
const before = thread.currentTurn?.id;
|
|
944
1078
|
for (let i = 0; i < 100 && this.runtime.sending?.has(thread.id) && !this.runtime.execution.isRunning(thread.id); i++) {
|
|
945
1079
|
await new Promise(resolve => setTimeout(resolve, 20));
|
|
946
1080
|
}
|
|
947
1081
|
let failure;
|
|
948
|
-
const running = (commandId ? this.runtime.executeCommand(thread.id, commandId) : this.runtime.send(thread.id, text, { attachments })).catch(error => { failure = error; });
|
|
1082
|
+
const running = (commandId ? this.runtime.executeCommand(thread.id, commandId) : this.runtime.send(thread.id, text, { attachments, turnPermissions })).catch(error => { failure = error; });
|
|
949
1083
|
for (let attempt = 0; attempt < 600 && thread.currentTurn?.id === before && !failure; attempt++) await new Promise(resolve => setTimeout(resolve, 50));
|
|
950
1084
|
if (failure) throw failure;
|
|
951
1085
|
if (!thread.currentTurn || thread.currentTurn.id === before) throw new Error('Native turn did not start');
|
|
@@ -1008,6 +1142,13 @@ class NativeProtocol {
|
|
|
1008
1142
|
this.approvals.delete(message.id);
|
|
1009
1143
|
return true;
|
|
1010
1144
|
}
|
|
1011
|
-
close() {
|
|
1145
|
+
close() {
|
|
1146
|
+
this.closed = true;
|
|
1147
|
+
this.codexAccounts.close();
|
|
1148
|
+
this.unsubscribe();
|
|
1149
|
+
this.unsubscribeRuntime();
|
|
1150
|
+
for (const timer of this.queueNotifications.values()) clearTimeout(timer);
|
|
1151
|
+
this.queueNotifications.clear();
|
|
1152
|
+
}
|
|
1012
1153
|
}
|
|
1013
1154
|
module.exports = { NativeProtocol, decodeRoute, projectItem, externalId, routeModel };
|
|
@@ -17,23 +17,23 @@ class Projector {
|
|
|
17
17
|
if (existingTurn && existingTurn.threadId !== event.threadId) throw new Error('event belongs to another thread');
|
|
18
18
|
if (existingTurn && TERMINAL_TURN_STATUS.includes(existingTurn.status) && event.type.startsWith('item.')) return {};
|
|
19
19
|
if (existingTurn && typeof event.sequence === 'number') existingTurn.lastSequence = Math.max(existingTurn.lastSequence, event.sequence);
|
|
20
|
-
switch (event.type) {
|
|
21
|
-
case 'thread.rolledBack': {
|
|
22
|
-
const turns = this.turns.turnsForThread(event.threadId);
|
|
23
|
-
const count = event.payload.numTurns;
|
|
24
|
-
if (!Number.isSafeInteger(count) || count < 1 || count > turns.length || turns.some(t => !TERMINAL_TURN_STATUS.includes(t.status))) throw new Error('Invalid rollback boundary');
|
|
25
|
-
const removed = new Set(turns.slice(-count).map(t => t.id));
|
|
26
|
-
for (const id of removed) this.turns.turns.delete(id);
|
|
27
|
-
for (const [id, item] of this.items) if (removed.has(item.turnId)) this.items.delete(id);
|
|
28
|
-
const thread = this.threads.get(event.threadId);
|
|
29
|
-
thread.usage = {};
|
|
30
|
-
for (const turn of turns.slice(0, -count)) {
|
|
31
|
-
turn.nativeTurnRef = { ...turn.nativeTurnRef, sessionId: event.payload.sessionId };
|
|
32
|
-
const map = event.payload.checkpointMap;
|
|
33
|
-
if (map && turn.nativeTurnRef.checkpointId) turn.nativeTurnRef.checkpointId = map[turn.nativeTurnRef.checkpointId];
|
|
34
|
-
}
|
|
35
|
-
return { thread: this.threads.update(event.threadId, { status: 'idle', activeTurnId: null, nativeSessionRef: { sessionId: event.payload.sessionId } }, event.timestamp) };
|
|
36
|
-
}
|
|
20
|
+
switch (event.type) {
|
|
21
|
+
case 'thread.rolledBack': {
|
|
22
|
+
const turns = this.turns.turnsForThread(event.threadId);
|
|
23
|
+
const count = event.payload.numTurns;
|
|
24
|
+
if (!Number.isSafeInteger(count) || count < 1 || count > turns.length || turns.some(t => !TERMINAL_TURN_STATUS.includes(t.status))) throw new Error('Invalid rollback boundary');
|
|
25
|
+
const removed = new Set(turns.slice(-count).map(t => t.id));
|
|
26
|
+
for (const id of removed) this.turns.turns.delete(id);
|
|
27
|
+
for (const [id, item] of this.items) if (removed.has(item.turnId)) this.items.delete(id);
|
|
28
|
+
const thread = this.threads.get(event.threadId);
|
|
29
|
+
thread.usage = {};
|
|
30
|
+
for (const turn of turns.slice(0, -count)) {
|
|
31
|
+
turn.nativeTurnRef = { ...turn.nativeTurnRef, sessionId: event.payload.sessionId };
|
|
32
|
+
const map = event.payload.checkpointMap;
|
|
33
|
+
if (map && turn.nativeTurnRef.checkpointId) turn.nativeTurnRef.checkpointId = map[turn.nativeTurnRef.checkpointId];
|
|
34
|
+
}
|
|
35
|
+
return { thread: this.threads.update(event.threadId, { status: 'idle', activeTurnId: null, nativeSessionRef: { sessionId: event.payload.sessionId } }, event.timestamp) };
|
|
36
|
+
}
|
|
37
37
|
case 'thread.created': {
|
|
38
38
|
const thread = this.threads.create({ id: event.threadId, ...event.payload }, event.timestamp);
|
|
39
39
|
return { thread };
|
|
@@ -83,28 +83,28 @@ class Projector {
|
|
|
83
83
|
item.updatedAt = event.timestamp;
|
|
84
84
|
return { item };
|
|
85
85
|
}
|
|
86
|
-
case 'usage.updated': {
|
|
86
|
+
case 'usage.updated': {
|
|
87
87
|
const item = this.#upsertUsageItem(event);
|
|
88
88
|
const thread = this.threads.update(event.threadId, { usage: event.payload }, event.timestamp);
|
|
89
|
-
return { item, thread };
|
|
90
|
-
}
|
|
91
|
-
case 'verification.updated': {
|
|
92
|
-
const turn = this.turns.get(event.turnId);
|
|
93
|
-
if (!turn) return {};
|
|
94
|
-
const itemId = event.itemId ?? `verification_${turn.id}`;
|
|
95
|
-
let item = this.items.get(itemId);
|
|
96
|
-
if (!item) {
|
|
97
|
-
item = createItem({ id: itemId, threadId: event.threadId, turnId: turn.id,
|
|
98
|
-
type: 'verification_report', status: 'completed', report: structuredClone(event.payload.report) }, event.timestamp);
|
|
99
|
-
this.items.set(item.id, item);
|
|
100
|
-
if (!turn.itemIds.includes(item.id)) turn.itemIds.push(item.id);
|
|
101
|
-
} else {
|
|
102
|
-
item.report = structuredClone(event.payload.report);
|
|
103
|
-
item.status = 'completed';
|
|
104
|
-
item.updatedAt = event.timestamp;
|
|
105
|
-
}
|
|
106
|
-
return { item };
|
|
107
|
-
}
|
|
89
|
+
return { item, thread };
|
|
90
|
+
}
|
|
91
|
+
case 'verification.updated': {
|
|
92
|
+
const turn = this.turns.get(event.turnId);
|
|
93
|
+
if (!turn) return {};
|
|
94
|
+
const itemId = event.itemId ?? `verification_${turn.id}`;
|
|
95
|
+
let item = this.items.get(itemId);
|
|
96
|
+
if (!item) {
|
|
97
|
+
item = createItem({ id: itemId, threadId: event.threadId, turnId: turn.id,
|
|
98
|
+
type: 'verification_report', status: 'completed', report: structuredClone(event.payload.report) }, event.timestamp);
|
|
99
|
+
this.items.set(item.id, item);
|
|
100
|
+
if (!turn.itemIds.includes(item.id)) turn.itemIds.push(item.id);
|
|
101
|
+
} else {
|
|
102
|
+
item.report = structuredClone(event.payload.report);
|
|
103
|
+
item.status = 'completed';
|
|
104
|
+
item.updatedAt = event.timestamp;
|
|
105
|
+
}
|
|
106
|
+
return { item };
|
|
107
|
+
}
|
|
108
108
|
default:
|
|
109
109
|
return {};
|
|
110
110
|
}
|
|
@@ -119,9 +119,9 @@ class Projector {
|
|
|
119
119
|
return this.turns.create({ id: event.turnId ?? `turn_${event.eventId}`, threadId: event.threadId, nativeTurnRef: event.nativeRef }, event.timestamp);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
#settleTurn(event, kind) {
|
|
123
|
-
const turn = this.#ensureTurn(event);
|
|
124
|
-
if (event.nativeRef) turn.nativeTurnRef = { ...turn.nativeTurnRef, ...event.nativeRef };
|
|
122
|
+
#settleTurn(event, kind) {
|
|
123
|
+
const turn = this.#ensureTurn(event);
|
|
124
|
+
if (event.nativeRef) turn.nativeTurnRef = { ...turn.nativeTurnRef, ...event.nativeRef };
|
|
125
125
|
if (typeof event.sequence === 'number') turn.lastSequence = event.sequence;
|
|
126
126
|
// 首次结算生效:Turn 已进入终态后,迟到的重复结算事件为幂等噪声(如 cancel 后
|
|
127
127
|
// 原生流仍送达 agent_settled / result),不改变 Turn 生命周期。
|
|
@@ -133,7 +133,10 @@ class Projector {
|
|
|
133
133
|
} else if (kind === 'cancelled') {
|
|
134
134
|
this.turns.cancel(turn.id, {}, event.timestamp);
|
|
135
135
|
} else {
|
|
136
|
-
this.turns.fail(turn.id, event.payload?.message ?? event.payload?.error, {
|
|
136
|
+
this.turns.fail(turn.id, event.payload?.message ?? event.payload?.error, {
|
|
137
|
+
...(event.payload?.errorKind ? { errorKind: event.payload.errorKind } : {}),
|
|
138
|
+
...(event.payload?.codexErrorInfo ? { codexErrorInfo: event.payload.codexErrorInfo } : {}),
|
|
139
|
+
}, event.timestamp);
|
|
137
140
|
}
|
|
138
141
|
// Turn 结算:所有未终态 Item 一并收尾(语义等同 legacy finishMessage)
|
|
139
142
|
this.#finalizeOpenItems(turn, event.timestamp);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"production-controller.d.ts","sourceRoot":"","sources":["../src/production-controller.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,sCAAsC,EAC5C,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,WAAW,wBAAwB;IACvC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,CAAC,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,EAAE,CAAC;CACZ;AAED,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,OAAO,EAAE;QACf,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACvC,qBAAqB,CACnB,OAAO,EAAE,sCAAsC,GAC9C,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACvC,KAAK,CAAC,SAAS,EAAE,0BAA0B,GAAG,IAAI,CAAC;IACnD,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,GAAG,CAAC,IAAI,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAqBD,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,0BAA0B,GAAG,MAAM,CAejG;AA8BD,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,wBAAwB,CAwE1B;AAmCD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,wBAAwB,EACjC,MAAM,EAAE,WAAW,EACnB,YAAY,GAAE,6BAAmD,GAChE,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"production-controller.d.ts","sourceRoot":"","sources":["../src/production-controller.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,sCAAsC,EAC5C,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,WAAW,wBAAwB;IACvC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,CAAC,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,EAAE,CAAC;CACZ;AAED,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,OAAO,EAAE;QACf,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACvC,qBAAqB,CACnB,OAAO,EAAE,sCAAsC,GAC9C,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACvC,KAAK,CAAC,SAAS,EAAE,0BAA0B,GAAG,IAAI,CAAC;IACnD,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,GAAG,CAAC,IAAI,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAqBD,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,0BAA0B,GAAG,MAAM,CAejG;AA8BD,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,wBAAwB,CAwE1B;AAmCD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,wBAAwB,EACjC,MAAM,EAAE,WAAW,EACnB,YAAY,GAAE,6BAAmD,GAChE,OAAO,CAAC,IAAI,CAAC,CA8Hf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"production-controller.js","sourceRoot":"","sources":["../src/production-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,+BAA+B,GAGhC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gCAAgC,GAEjC,MAAM,mCAAmC,CAAC;AAiC3C,MAAM,6BAA6B,GAAG,MAAM,CAAC;AAC7C,MAAM,sBAAsB,GAC1B,qFAAqF,CAAC;AACxF,MAAM,sCAAsC,GAAG,GAAG,CAAC;AACnD,MAAM,0BAA0B,GAAG,CAAC,CAAC;AACrC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AACvC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AACzC,MAAM,qBAAqB,GAAG,OAAO,CAAC;AACtC,MAAM,qBAAqB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAEzC,SAAS,YAAY,CAAC,KAAa,EAAE,MAAgB;IACnD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG;QAAE,OAAO;IACxD,MAAM,MAAM,GACV,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC/F,OAAO,CAAC,KAAK,CACX,uBAAuB,IAAI,CAAC,GAAG,EAAE,GAAG,qBAAqB,mBAAmB,KAAK,GAAG,MAAM,EAAE,CAC7F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,SAAqC;IACvF,IACE,SAAS,CAAC,aAAa,KAAK,CAAC;QAC7B,SAAS,CAAC,KAAK,KAAK,YAAY;QAChC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;QAChC,SAAS,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,EACnC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,sCAAsC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,mBAAmB,GAAkC;IACzD,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IACtD,OAAO,EAAE,gCAAgC;IACzC,qBAAqB,EAAE,+BAA+B;IACtD,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE;QACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,mCAAmC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC;IACD,KAAK,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACpF,iBAAiB,EAAE,GAAG;CACvB,CAAC;AAEF,SAAS,mBAAmB,CAAC,KAAa;IACxC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,IACE,GAAG,CAAC,QAAQ,KAAK,OAAO;QACxB,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC3D,CAAC,GAAG,CAAC,IAAI;QACT,GAAG,CAAC,QAAQ;QACZ,GAAG,CAAC,QAAQ;QACZ,CAAC,GAAG,CAAC,QAAQ,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAC;QAC7C,GAAG,CAAC,MAAM;QACV,GAAG,CAAC,IAAI,EACR,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,UAA6B;IAE7B,IAAI,QAA4B,CAAC;IACjC,IAAI,YAAgC,CAAC;IACrC,IAAI,YAAwC,CAAC;IAC7C,IAAI,cAAkC,CAAC;IACvC,IAAI,eAAmC,CAAC;IACxC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACpC,IAAI,QAAQ,KAAK,yBAAyB,EAAE,CAAC;YAC3C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;YACxE,QAAQ,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACtC,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC9B,IAAI,YAAY,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACxF,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC3D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACpF,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACrC,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YACnC,IAAI,YAAY,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC7F,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAC7D,CAAC;YACD,YAAY,GAAG,KAAK,CAAC;YACrB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YACrC,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACjE,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;YACD,cAAc,GAAG,IAAI,CAAC;YACtB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,KAAK,oBAAoB,EAAE,CAAC;YACtC,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;YACpF,CAAC;YACD,eAAe,GAAG,KAAK,CAAC;YACxB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACnF,IAAI,YAAY,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC1E,IAAI,YAAY,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC/E,IAAI,cAAc,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnF,IAAI,eAAe,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACrF,OAAO;QACL,mBAAmB,EAAE,QAAQ;QAC7B,YAAY;QACZ,YAAY;QACZ,cAAc;QACd,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CAAC,KAAc;IACrD,IAAI,OAAO,GAAY,KAAK,CAAC;IAC7B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7E,IACE,OAAO,CAAC,QAAQ,CAAC,iCAAiC,CAAC;YACnD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EACzC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/D,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,wBAAwB,CACrC,OAAgE,EAChE,YAA2C;IAE3C,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,0BAA0B,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QAC1E,IAAI,CAAC;YACH,OAAO,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO,KAAK,0BAA0B,IAAI,CAAC,+BAA+B,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtF,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,YAAY,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAiC,EACjC,MAAmB,EACnB,eAA8C,mBAAmB;IAEjE,MAAM,aAAa,GAAG,+GAA+G,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC;IAClL,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACzC,IAAI,OAA8C,CAAC;IACnD,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,eAAe,GAAG,yBAAyB,CAAC;IAChD,MAAM,qBAAqB,GAAG,GAAS,EAAE;QACvC,cAAc,GAAG,GAAG,EAAE,GAAG,eAAe,CAAC;QACzC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,EAAE,qBAAqB,CAAC,CAAC;IACzE,CAAC,CAAC;IACF,MAAM,qBAAqB,GAAG,GAAS,EAAE;QACvC,cAAc,GAAG,CAAC,CAAC;QACnB,eAAe,GAAG,yBAAyB,CAAC;IAC9C,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,KAAK,IAAwC,EAAE;QACnE,YAAY,CAAC,yBAAyB,CAAC,CAAC;QACxC,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC7E,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC/F,YAAY,CAAC,6BAA6B,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAC9C;YACE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;YAChD,cAAc,EAAE,GAAG,sBAAsB,KAAK,aAAa,KAAK,cAAc,EAAE;YAChF,aAAa,EAAE;gBACb,OAAO;gBACP,IAAI;gBACJ,aAAa;gBACb,kBAAkB;gBAClB,KAAK;gBACL,UAAU;gBACV,MAAM;gBACN,UAAU;gBACV,QAAQ;gBACR,aAAa;gBACb,OAAO;gBACP,WAAW;gBACX,UAAU;gBACV,YAAY;gBACZ,eAAe;gBACf,OAAO;gBACP,MAAM;
|
|
1
|
+
{"version":3,"file":"production-controller.js","sourceRoot":"","sources":["../src/production-controller.ts"],"names":[],"mappings":"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"}
|