@kafca/agentdock 0.1.44 → 0.1.46
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/README.md +76 -11
- package/bin/agentdock.mjs +5 -5
- package/dist/renderer/assets/{Badge-Qk9qHovH.js → Badge-BIesaDYG.js} +1 -1
- package/dist/renderer/assets/Chat-CpataoDh.js +2 -0
- package/dist/renderer/assets/{ChatMarkdown-BKdW8OON.js → ChatMarkdown-_Mdmltgv.js} +1 -1
- package/dist/renderer/assets/Config-Pe5-zKZk.js +21 -0
- package/dist/renderer/assets/CronList-BnaOSPT8.js +1 -0
- package/dist/renderer/assets/Dashboard-D05l8GKE.js +26 -0
- package/dist/renderer/assets/{EmptyState-kD9yAwtw.js → EmptyState-BDBavDll.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-BAMCLrjz.js → KnowledgeDetail-DvR798l_.js} +2 -2
- package/dist/renderer/assets/KnowledgeHome-r2ZuvU8-.js +11 -0
- package/dist/renderer/assets/Logs-BaljtmAV.js +1 -0
- package/dist/renderer/assets/{Modal-DwY4lecS.js → Modal-CXhD_OWR.js} +1 -1
- package/dist/renderer/assets/MonitorList-D7tyipbx.js +1 -0
- package/dist/renderer/assets/{Page-CnB9ePsb.js → Page-KUuFYgjg.js} +1 -1
- package/dist/renderer/assets/ProjectDetail-Ddq94-yu.js +11 -0
- package/dist/renderer/assets/ProjectList-CbdHd5Ev.js +1 -0
- package/dist/renderer/assets/{Select-zfoksLGB.js → Select-Djc8BXMC.js} +1 -1
- package/dist/renderer/assets/SessionChat-DOy0iKQR.js +1 -0
- package/dist/renderer/assets/SessionList-DHgl1s1D.js +1 -0
- package/dist/renderer/assets/ThreadChat-I7dYibDc.js +23 -0
- package/dist/renderer/assets/Workspace-DTocqY-F.js +19 -0
- package/dist/renderer/assets/{arrow-left-CNEAuElg.js → arrow-left-CXyya3hP.js} +1 -1
- package/dist/renderer/assets/{book-open-BNJMhNI-.js → book-open-9n4Kxc7E.js} +1 -1
- package/dist/renderer/assets/bot-C9HBk5XH.js +6 -0
- package/dist/renderer/assets/{check-BnclClRU.js → check-CutSg9a5.js} +1 -1
- package/dist/renderer/assets/{chevron-down-Bh53e0O-.js → chevron-down-DrydR4i3.js} +1 -1
- package/dist/renderer/assets/{circle-ClZTWCWO.js → circle-BEjtahw6.js} +1 -1
- package/dist/renderer/assets/desktop-DATgk_ka.js +1 -0
- package/dist/renderer/assets/{desktop-C6q6wBae.js → desktop-JQkhNOF4.js} +5 -5
- package/dist/renderer/assets/en-CmAr_0e6.js +1 -0
- package/dist/renderer/assets/es-Cs9x52ca.js +1 -0
- package/dist/renderer/assets/{funnel-_5hsz0xI.js → funnel-BhqZpS4f.js} +1 -1
- package/dist/renderer/assets/{heart-u4Q1aOqj.js → heart-Dp8Vs-7_.js} +1 -1
- package/dist/renderer/assets/{index-BNFx4uYv.js → index-BKpv0P0s.js} +2 -2
- package/dist/renderer/assets/index-CO4fGqmv.css +11 -0
- package/dist/renderer/assets/{index-B36eowj-.js → index-cI3pWBnN.js} +36 -36
- package/dist/renderer/assets/ja-DtvtBRTW.js +1 -0
- package/dist/renderer/assets/{pencil-DLh9QNmT.js → pencil-ywcJzeOo.js} +1 -1
- package/dist/renderer/assets/{play-BDTk9Scm.js → play-AtN492Cx.js} +1 -1
- package/dist/renderer/assets/{plus-BSc8POsz.js → plus-BEj14BBV.js} +1 -1
- package/dist/renderer/assets/projects-Clar8lgb.js +1 -0
- package/dist/renderer/assets/save-D6ov4CNv.js +11 -0
- package/dist/renderer/assets/{search-CniPk7Ey.js → search-C3bvw7AR.js} +1 -1
- package/dist/renderer/assets/{server-GsXyQAZm.js → server-C1Uyedyx.js} +1 -1
- package/dist/renderer/assets/{session-utils-BDxzgTBC.js → session-utils-DpRwJ6Nh.js} +1 -1
- package/dist/renderer/assets/{sessions-CLcKA1Tt.js → sessions-BWmAppwK.js} +1 -1
- package/dist/renderer/assets/{shield-check-4i0E3hmf.js → shield-check-CVx1mEs2.js} +1 -1
- package/dist/renderer/assets/{trash-2-DhtOCsO5.js → trash-2-o-heXOgs.js} +1 -1
- package/dist/renderer/assets/user-dPOzUqIc.js +6 -0
- package/dist/renderer/assets/{wifi-off-BHPzPY_B.js → wifi-off-Fz5c3_x_.js} +1 -1
- package/dist/renderer/assets/zh-CcJ9vBZj.js +1 -0
- package/dist/renderer/assets/zh-TW-elI72AC1.js +1 -0
- package/dist/renderer/index.html +2 -2
- package/dist-electron/electron/main.js +26 -1
- package/dist-electron/packages/core-sdk/src/index.js +28 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +111 -62
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +80 -7
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +78 -5
- package/dist-electron/services/local-ai-core/src/acp/store/external-store.js +98 -0
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +33 -0
- package/dist-electron/services/local-ai-core/src/acp/store/model-provider-store.js +88 -0
- package/dist-electron/services/local-ai-core/src/acp/store/schema.js +43 -0
- package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +2 -119
- package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +148 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/inbound.js +55 -1
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +65 -10
- package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +4 -2
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +139 -29
- package/dist-electron/services/local-ai-core/src/execution/agent-execution-backend.js +56 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +18 -57
- package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +255 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/catalog.js +78 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +3 -1
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +64 -9
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -2
- package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +152 -0
- package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +175 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +330 -3
- package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +11 -2
- package/dist-electron/services/local-ai-core/src/runtime/provider-config-migration.js +32 -0
- package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +76 -8
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +62 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +708 -4
- package/dist-electron/services/local-ai-core/src/runtime/standalone.js +13 -3
- package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +113 -0
- package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +273 -0
- package/dist-electron/services/local-ai-core/src/sandbox/sandbox-manager.js +215 -0
- package/dist-electron/services/local-ai-core/src/sandbox/sandbox-stdio-proxy.js +188 -0
- package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +3 -0
- package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +32 -0
- package/dist-electron/services/local-ai-core/src/thread/thread-slash-command-dispatcher.js +71 -0
- package/dist-electron/shared/desktop.js +85 -1
- package/dist-electron/tests/contracts/architecture-docs.test.js +83 -0
- package/dist-electron/tests/electron/plugin-kernel.test.js +225 -18
- package/dist-electron/tests/electron/runtime-detection-service.test.js +57 -5
- package/dist-electron/tests/electron/sandbox-config.test.js +541 -0
- package/dist-electron/tests/electron/workspace-task-store.test.js +257 -0
- package/dist-electron/tests/integration/lark-gateway.test.js +139 -0
- package/dist-electron/tests/integration/local-core-refactor.test.js +183 -20
- package/dist-electron/tests/integration/local-core-routes.test.js +34 -0
- package/package.json +2 -3
- package/dist/renderer/assets/Chat-BK-fm0Xr.js +0 -2
- package/dist/renderer/assets/Config-B93CQGvY.js +0 -16
- package/dist/renderer/assets/CronList-Z3TvSRKP.js +0 -1
- package/dist/renderer/assets/Dashboard-Ch3QkWwf.js +0 -26
- package/dist/renderer/assets/KnowledgeHome-ChvjOfrc.js +0 -11
- package/dist/renderer/assets/Logs-Cv0nth3j.js +0 -1
- package/dist/renderer/assets/MonitorList-JEvMoWUm.js +0 -1
- package/dist/renderer/assets/ProjectDetail-DJa3sMmU.js +0 -11
- package/dist/renderer/assets/ProjectList-D6CXumR_.js +0 -1
- package/dist/renderer/assets/SessionChat-DUTh4WoM.js +0 -1
- package/dist/renderer/assets/SessionList-D9o-lUst.js +0 -1
- package/dist/renderer/assets/ThreadChat-BYXlT-Kc.js +0 -23
- package/dist/renderer/assets/Workspace-BrhSwRQ-.js +0 -14
- package/dist/renderer/assets/desktop-C5vBT0yM.js +0 -1
- package/dist/renderer/assets/en-D2SkCrhG.js +0 -1
- package/dist/renderer/assets/es-C8UBPhxM.js +0 -1
- package/dist/renderer/assets/index-CaQZSRbg.css +0 -11
- package/dist/renderer/assets/ja-ChF4vbBL.js +0 -1
- package/dist/renderer/assets/plug-BG0JHW6B.js +0 -6
- package/dist/renderer/assets/projects-DwfZwxDW.js +0 -1
- package/dist/renderer/assets/save-D5AO_G6a.js +0 -6
- package/dist/renderer/assets/user-BtC_pVXV.js +0 -11
- package/dist/renderer/assets/zh-DIcdHycM.js +0 -1
- package/dist/renderer/assets/zh-TW-BtRwreY_.js +0 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocalCoreErrorReporter = exports.LocalCoreError = void 0;
|
|
4
|
+
exports.toLocalCoreErrorInfo = toLocalCoreErrorInfo;
|
|
5
|
+
exports.formatUserError = formatUserError;
|
|
6
|
+
exports.formatLogError = formatLogError;
|
|
7
|
+
exports.errorInfoToHttpBody = errorInfoToHttpBody;
|
|
8
|
+
const DEFAULTS = {
|
|
9
|
+
runtime_not_found: {
|
|
10
|
+
severity: 'error',
|
|
11
|
+
retryable: false,
|
|
12
|
+
userMessage: 'Agent runtime is not installed or is not available on PATH.',
|
|
13
|
+
suggestedAction: 'Install the runtime or update the service PATH, then retry.',
|
|
14
|
+
},
|
|
15
|
+
runtime_start_failed: {
|
|
16
|
+
severity: 'error',
|
|
17
|
+
retryable: true,
|
|
18
|
+
userMessage: 'Agent runtime failed to start.',
|
|
19
|
+
suggestedAction: 'Check the runtime installation and logs, then retry.',
|
|
20
|
+
},
|
|
21
|
+
runtime_protocol_timeout: {
|
|
22
|
+
severity: 'error',
|
|
23
|
+
retryable: true,
|
|
24
|
+
userMessage: 'Agent runtime timed out.',
|
|
25
|
+
suggestedAction: 'Retry the request. If it repeats, restart the runtime.',
|
|
26
|
+
},
|
|
27
|
+
runtime_protocol_error: {
|
|
28
|
+
severity: 'error',
|
|
29
|
+
retryable: true,
|
|
30
|
+
userMessage: 'Agent runtime returned an invalid protocol response.',
|
|
31
|
+
suggestedAction: 'Retry the request or switch to another agent.',
|
|
32
|
+
},
|
|
33
|
+
runtime_exited: {
|
|
34
|
+
severity: 'error',
|
|
35
|
+
retryable: true,
|
|
36
|
+
userMessage: 'Agent runtime exited before finishing the task.',
|
|
37
|
+
suggestedAction: 'Retry the request. If it repeats, check the runtime logs.',
|
|
38
|
+
},
|
|
39
|
+
channel_session_expired: {
|
|
40
|
+
severity: 'error',
|
|
41
|
+
retryable: false,
|
|
42
|
+
userMessage: 'Channel login has expired.',
|
|
43
|
+
suggestedAction: 'Reconnect the channel and retry.',
|
|
44
|
+
},
|
|
45
|
+
channel_auth_failed: {
|
|
46
|
+
severity: 'error',
|
|
47
|
+
retryable: false,
|
|
48
|
+
userMessage: 'Channel authentication failed.',
|
|
49
|
+
suggestedAction: 'Check the channel credentials and reconnect.',
|
|
50
|
+
},
|
|
51
|
+
channel_rate_limited: {
|
|
52
|
+
severity: 'warning',
|
|
53
|
+
retryable: true,
|
|
54
|
+
userMessage: 'Channel is rate limited.',
|
|
55
|
+
suggestedAction: 'Wait a moment and retry.',
|
|
56
|
+
},
|
|
57
|
+
channel_delivery_failed: {
|
|
58
|
+
severity: 'error',
|
|
59
|
+
retryable: true,
|
|
60
|
+
userMessage: 'Channel message delivery failed.',
|
|
61
|
+
suggestedAction: 'Retry the message or check the channel status.',
|
|
62
|
+
},
|
|
63
|
+
channel_download_failed: {
|
|
64
|
+
severity: 'warning',
|
|
65
|
+
retryable: true,
|
|
66
|
+
userMessage: 'Channel attachment download failed.',
|
|
67
|
+
suggestedAction: 'Retry or upload the attachment again.',
|
|
68
|
+
},
|
|
69
|
+
config_invalid: {
|
|
70
|
+
severity: 'error',
|
|
71
|
+
retryable: false,
|
|
72
|
+
userMessage: 'Configuration is invalid.',
|
|
73
|
+
suggestedAction: 'Fix the configuration and retry.',
|
|
74
|
+
},
|
|
75
|
+
permission_waiting: {
|
|
76
|
+
severity: 'info',
|
|
77
|
+
retryable: true,
|
|
78
|
+
userMessage: 'Agent is waiting for permission.',
|
|
79
|
+
suggestedAction: 'Choose a permission option to continue.',
|
|
80
|
+
},
|
|
81
|
+
provider_auth_failed: {
|
|
82
|
+
severity: 'error',
|
|
83
|
+
retryable: false,
|
|
84
|
+
userMessage: 'Model provider authentication failed.',
|
|
85
|
+
suggestedAction: 'Update provider credentials and retry.',
|
|
86
|
+
},
|
|
87
|
+
scheduler_delivery_failed: {
|
|
88
|
+
severity: 'error',
|
|
89
|
+
retryable: true,
|
|
90
|
+
userMessage: 'Scheduled delivery failed.',
|
|
91
|
+
suggestedAction: 'Check the target channel and retry the scheduled job.',
|
|
92
|
+
},
|
|
93
|
+
sandbox_unavailable: {
|
|
94
|
+
severity: 'error',
|
|
95
|
+
retryable: true,
|
|
96
|
+
userMessage: 'Sandbox service is unavailable.',
|
|
97
|
+
suggestedAction: 'Start OpenSandbox with docker compose and retry.',
|
|
98
|
+
},
|
|
99
|
+
sandbox_unauthorized: {
|
|
100
|
+
severity: 'error',
|
|
101
|
+
retryable: false,
|
|
102
|
+
userMessage: 'Sandbox service rejected authentication.',
|
|
103
|
+
suggestedAction: 'Check OPEN_SANDBOX_API_KEY and retry.',
|
|
104
|
+
},
|
|
105
|
+
sandbox_request_failed: {
|
|
106
|
+
severity: 'error',
|
|
107
|
+
retryable: true,
|
|
108
|
+
userMessage: 'Sandbox service request failed.',
|
|
109
|
+
suggestedAction: 'Check OpenSandbox logs and retry.',
|
|
110
|
+
},
|
|
111
|
+
sandbox_start_failed: {
|
|
112
|
+
severity: 'error',
|
|
113
|
+
retryable: true,
|
|
114
|
+
userMessage: 'Sandbox failed to start.',
|
|
115
|
+
suggestedAction: 'Check image availability, mounts, and OpenSandbox logs.',
|
|
116
|
+
},
|
|
117
|
+
sandbox_start_timeout: {
|
|
118
|
+
severity: 'error',
|
|
119
|
+
retryable: true,
|
|
120
|
+
userMessage: 'Sandbox startup timed out.',
|
|
121
|
+
suggestedAction: 'Check Docker image startup time and OpenSandbox health.',
|
|
122
|
+
},
|
|
123
|
+
sandbox_endpoint_missing: {
|
|
124
|
+
severity: 'error',
|
|
125
|
+
retryable: true,
|
|
126
|
+
userMessage: 'Sandbox ACP endpoint is unavailable.',
|
|
127
|
+
suggestedAction: 'Check that the sandbox image exposes the configured ACP port.',
|
|
128
|
+
},
|
|
129
|
+
internal_error: {
|
|
130
|
+
severity: 'error',
|
|
131
|
+
retryable: true,
|
|
132
|
+
userMessage: 'AgentDock hit an internal error.',
|
|
133
|
+
suggestedAction: 'Retry the request. If it repeats, check the logs.',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
class LocalCoreError extends Error {
|
|
137
|
+
info;
|
|
138
|
+
constructor(code, message, input = {}) {
|
|
139
|
+
const defaults = DEFAULTS[code];
|
|
140
|
+
super(message || defaults.userMessage);
|
|
141
|
+
this.name = 'LocalCoreError';
|
|
142
|
+
this.info = {
|
|
143
|
+
code,
|
|
144
|
+
message: message || defaults.userMessage,
|
|
145
|
+
userMessage: input.userMessage || defaults.userMessage,
|
|
146
|
+
severity: input.severity || defaults.severity,
|
|
147
|
+
retryable: input.retryable ?? defaults.retryable,
|
|
148
|
+
suggestedAction: input.suggestedAction ?? defaults.suggestedAction,
|
|
149
|
+
details: input.details,
|
|
150
|
+
cause: input.cause,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.LocalCoreError = LocalCoreError;
|
|
155
|
+
function toLocalCoreErrorInfo(error, fallbackCode = 'internal_error', details = {}) {
|
|
156
|
+
if (error instanceof LocalCoreError) {
|
|
157
|
+
return mergeDetails(error.info, details);
|
|
158
|
+
}
|
|
159
|
+
const maybeInfo = error?.info;
|
|
160
|
+
if (maybeInfo?.code && maybeInfo.message) {
|
|
161
|
+
return mergeDetails(maybeInfo, details);
|
|
162
|
+
}
|
|
163
|
+
const message = error instanceof Error ? error.message : String(error || '');
|
|
164
|
+
const classifiedCode = classifyErrorMessage(message, fallbackCode);
|
|
165
|
+
return new LocalCoreError(classifiedCode, message || DEFAULTS[classifiedCode].userMessage, {
|
|
166
|
+
details: Object.keys(details).length ? details : undefined,
|
|
167
|
+
}).info;
|
|
168
|
+
}
|
|
169
|
+
function formatUserError(info) {
|
|
170
|
+
return [info.userMessage, info.suggestedAction].filter(Boolean).join(' ');
|
|
171
|
+
}
|
|
172
|
+
function formatLogError(info) {
|
|
173
|
+
const suffix = info.cause ? ` cause=${info.cause}` : '';
|
|
174
|
+
return `${info.code}: ${info.message}${suffix}`;
|
|
175
|
+
}
|
|
176
|
+
function errorInfoToHttpBody(info) {
|
|
177
|
+
return {
|
|
178
|
+
ok: false,
|
|
179
|
+
error: info.message,
|
|
180
|
+
code: info.code,
|
|
181
|
+
errorInfo: info,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
class LocalCoreErrorReporter {
|
|
185
|
+
log;
|
|
186
|
+
windowMs;
|
|
187
|
+
summaries = new Map();
|
|
188
|
+
lastLoggedAt = new Map();
|
|
189
|
+
constructor(log, windowMs = 5 * 60 * 1000) {
|
|
190
|
+
this.log = log;
|
|
191
|
+
this.windowMs = windowMs;
|
|
192
|
+
}
|
|
193
|
+
report(scope, error, context = {}, fallbackCode = 'internal_error') {
|
|
194
|
+
const info = toLocalCoreErrorInfo(error, fallbackCode, context);
|
|
195
|
+
const now = new Date();
|
|
196
|
+
const key = [
|
|
197
|
+
scope,
|
|
198
|
+
info.code,
|
|
199
|
+
context.workspaceId,
|
|
200
|
+
context.instanceId,
|
|
201
|
+
context.runtimeId,
|
|
202
|
+
context.threadId,
|
|
203
|
+
].filter(Boolean).join(':');
|
|
204
|
+
const existing = this.summaries.get(key);
|
|
205
|
+
const summary = existing
|
|
206
|
+
? { ...existing, count: existing.count + 1, lastSeenAt: now.toISOString(), errorInfo: info, context }
|
|
207
|
+
: { key, count: 1, firstSeenAt: now.toISOString(), lastSeenAt: now.toISOString(), errorInfo: info, context };
|
|
208
|
+
this.summaries.set(key, summary);
|
|
209
|
+
const lastLoggedAt = this.lastLoggedAt.get(key) || 0;
|
|
210
|
+
if (!lastLoggedAt || now.getTime() - lastLoggedAt >= this.windowMs) {
|
|
211
|
+
this.lastLoggedAt.set(key, now.getTime());
|
|
212
|
+
this.log(`[${scope}] ${formatLogError(info)}${summary.count > 1 ? ` count=${summary.count}` : ''}`);
|
|
213
|
+
}
|
|
214
|
+
return info;
|
|
215
|
+
}
|
|
216
|
+
list() {
|
|
217
|
+
return [...this.summaries.values()]
|
|
218
|
+
.sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.LocalCoreErrorReporter = LocalCoreErrorReporter;
|
|
222
|
+
function classifyErrorMessage(message, fallbackCode) {
|
|
223
|
+
const normalized = message.toLowerCase();
|
|
224
|
+
if (normalized.includes('enoent') || normalized.includes('command not found') || normalized.includes('not found on path')) {
|
|
225
|
+
return 'runtime_not_found';
|
|
226
|
+
}
|
|
227
|
+
if (normalized.includes('timed out waiting for acp') || normalized.includes('timeout')) {
|
|
228
|
+
return 'runtime_protocol_timeout';
|
|
229
|
+
}
|
|
230
|
+
if (normalized.includes('exited with code') || normalized.includes('sigterm')) {
|
|
231
|
+
return 'runtime_exited';
|
|
232
|
+
}
|
|
233
|
+
if (normalized.includes('session timeout') || normalized.includes('login expired') || normalized.includes('errcode=-14')) {
|
|
234
|
+
return 'channel_session_expired';
|
|
235
|
+
}
|
|
236
|
+
if (normalized.includes('rate limit') || normalized.includes('too many requests')) {
|
|
237
|
+
return 'channel_rate_limited';
|
|
238
|
+
}
|
|
239
|
+
if (normalized.includes('unauthorized') || normalized.includes('forbidden') || normalized.includes('auth')) {
|
|
240
|
+
return 'channel_auth_failed';
|
|
241
|
+
}
|
|
242
|
+
return fallbackCode;
|
|
243
|
+
}
|
|
244
|
+
function mergeDetails(info, details) {
|
|
245
|
+
if (!Object.keys(details).length) {
|
|
246
|
+
return info;
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
...info,
|
|
250
|
+
details: {
|
|
251
|
+
...(info.details || {}),
|
|
252
|
+
...details,
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBuiltinNoopKnowledgePlugin = exports.createBuiltinCronSchedulerPlugin = void 0;
|
|
4
|
+
exports.createKernelBuiltinPlugins = createKernelBuiltinPlugins;
|
|
5
|
+
exports.createRuntimeAgentPlugins = createRuntimeAgentPlugins;
|
|
6
|
+
exports.createRuntimeChannelPlugins = createRuntimeChannelPlugins;
|
|
7
|
+
exports.createRuntimeKnowledgePlugin = createRuntimeKnowledgePlugin;
|
|
8
|
+
exports.createRuntimeSchedulerPlugins = createRuntimeSchedulerPlugins;
|
|
9
|
+
exports.createRuntimeMonitorPlugins = createRuntimeMonitorPlugins;
|
|
10
|
+
const index_js_1 = require("../../agents/index.js");
|
|
11
|
+
const monitor_stock_plugin_js_1 = require("./monitor-stock-plugin.js");
|
|
12
|
+
const channel_lark_plugin_js_1 = require("./channel-lark-plugin.js");
|
|
13
|
+
const channel_weixin_plugin_js_1 = require("./channel-weixin-plugin.js");
|
|
14
|
+
const knowledge_ai_vector_plugin_js_1 = require("./knowledge-ai-vector-plugin.js");
|
|
15
|
+
const knowledge_noop_plugin_js_1 = require("./knowledge-noop-plugin.js");
|
|
16
|
+
Object.defineProperty(exports, "createBuiltinNoopKnowledgePlugin", { enumerable: true, get: function () { return knowledge_noop_plugin_js_1.createBuiltinNoopKnowledgePlugin; } });
|
|
17
|
+
const scheduler_cron_plugin_js_1 = require("./scheduler-cron-plugin.js");
|
|
18
|
+
Object.defineProperty(exports, "createBuiltinCronSchedulerPlugin", { enumerable: true, get: function () { return scheduler_cron_plugin_js_1.createBuiltinCronSchedulerPlugin; } });
|
|
19
|
+
const scheduler_lark_plugin_js_1 = require("./scheduler-lark-plugin.js");
|
|
20
|
+
const scheduler_local_plugin_js_1 = require("./scheduler-local-plugin.js");
|
|
21
|
+
const scheduler_weixin_plugin_js_1 = require("./scheduler-weixin-plugin.js");
|
|
22
|
+
function createKernelBuiltinPlugins() {
|
|
23
|
+
return [
|
|
24
|
+
...(0, index_js_1.getStaticAgentRuntimeDefinitions)().map((definition) => (0, index_js_1.createBuiltinStaticAgentCapabilityPlugin)(definition.agentType, definition.displayName)),
|
|
25
|
+
(0, index_js_1.createBuiltinLocalCoreAcpAgentPlugin)(),
|
|
26
|
+
(0, scheduler_cron_plugin_js_1.createBuiltinCronSchedulerPlugin)(),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
function createRuntimeAgentPlugins(localCoreAgentPlugin) {
|
|
30
|
+
return [
|
|
31
|
+
localCoreAgentPlugin,
|
|
32
|
+
(0, index_js_1.createBuiltinPiAgentPlugin)(),
|
|
33
|
+
(0, index_js_1.createBuiltinOpencodeAgentPlugin)(),
|
|
34
|
+
(0, index_js_1.createBuiltinCodexAgentPlugin)(),
|
|
35
|
+
(0, index_js_1.createBuiltinClaudeCodeAgentPlugin)(),
|
|
36
|
+
(0, index_js_1.createBuiltinHermesAgentPlugin)(),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
function createRuntimeChannelPlugins(options) {
|
|
40
|
+
return {
|
|
41
|
+
lark: (0, channel_lark_plugin_js_1.createBuiltinLarkChannelPlugin)(options),
|
|
42
|
+
weixin: (0, channel_weixin_plugin_js_1.createBuiltinWeixinChannelPlugin)(options),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function createRuntimeKnowledgePlugin(options) {
|
|
46
|
+
return options.enableKnowledge === false
|
|
47
|
+
? (0, knowledge_noop_plugin_js_1.createBuiltinNoopKnowledgePlugin)()
|
|
48
|
+
: (0, knowledge_ai_vector_plugin_js_1.createBuiltinAiVectorKnowledgePlugin)({
|
|
49
|
+
userDataPath: options.userDataPath,
|
|
50
|
+
getConfig: options.getConfig,
|
|
51
|
+
setConfig: options.setConfig,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function createRuntimeSchedulerPlugins(options) {
|
|
55
|
+
return [
|
|
56
|
+
(0, scheduler_local_plugin_js_1.createBuiltinLocalSchedulerPlugin)({
|
|
57
|
+
store: options.store,
|
|
58
|
+
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
59
|
+
}),
|
|
60
|
+
(0, scheduler_lark_plugin_js_1.createBuiltinLarkSchedulerPlugin)({
|
|
61
|
+
store: options.store,
|
|
62
|
+
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
63
|
+
getChannelRuntime: options.getLarkChannelRuntime,
|
|
64
|
+
log: options.log,
|
|
65
|
+
}),
|
|
66
|
+
(0, scheduler_weixin_plugin_js_1.createBuiltinWeixinSchedulerPlugin)({
|
|
67
|
+
store: options.store,
|
|
68
|
+
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
69
|
+
getChannelRuntime: options.getWeixinChannelRuntime,
|
|
70
|
+
log: options.log,
|
|
71
|
+
}),
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
function createRuntimeMonitorPlugins() {
|
|
75
|
+
return [
|
|
76
|
+
(0, monitor_stock_plugin_js_1.createBuiltinStockMonitorPlugin)(),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
@@ -7,6 +7,7 @@ const node_path_1 = require("node:path");
|
|
|
7
7
|
const desktop_js_1 = require("../../../../shared/desktop.js");
|
|
8
8
|
const index_js_1 = require("../agents/index.js");
|
|
9
9
|
const launch_utils_js_1 = require("../agents/shared/launch-utils.js");
|
|
10
|
+
const agent_execution_backend_js_1 = require("../execution/agent-execution-backend.js");
|
|
10
11
|
function normalizePlatformTypes(project) {
|
|
11
12
|
return Array.isArray(project?.platforms)
|
|
12
13
|
? project.platforms.map((platform) => (0, desktop_js_1.normalizeDesktopPlatformType)(platform?.type)).filter(Boolean)
|
|
@@ -61,7 +62,7 @@ function toLocalCoreProjectConfig(configState, project) {
|
|
|
61
62
|
throw new Error(`Workspace "${project.name}" requires [projects.agent.options].command for Local AI Core ACP execution.`);
|
|
62
63
|
}
|
|
63
64
|
const defaultArgs = launchDefaults.args || [];
|
|
64
|
-
|
|
65
|
+
const launchConfig = {
|
|
65
66
|
workspaceId: project.name,
|
|
66
67
|
agentType,
|
|
67
68
|
workDir,
|
|
@@ -74,4 +75,5 @@ function toLocalCoreProjectConfig(configState, project) {
|
|
|
74
75
|
},
|
|
75
76
|
model,
|
|
76
77
|
};
|
|
78
|
+
return (0, agent_execution_backend_js_1.prepareAgentExecutionLaunch)({ configState, project, launchConfig });
|
|
77
79
|
}
|
|
@@ -223,6 +223,21 @@ class WorkspaceRouter {
|
|
|
223
223
|
await this.getWorkspaceRoute(workspaceId);
|
|
224
224
|
return this.localCoreAcp.interruptRun(runId);
|
|
225
225
|
}
|
|
226
|
+
async setThreadMode(threadId, mode) {
|
|
227
|
+
const { workspaceId } = (0, workspace_thread_id_js_1.decodeThreadId)(threadId);
|
|
228
|
+
await this.getWorkspaceRoute(workspaceId);
|
|
229
|
+
return this.localCoreAcp.setThreadMode(threadId, mode);
|
|
230
|
+
}
|
|
231
|
+
closeThreadSession(threadId) {
|
|
232
|
+
this.localCoreAcp.closeThreadSession(threadId);
|
|
233
|
+
}
|
|
234
|
+
async getWorkspaceDefaultAgentType(workspaceId) {
|
|
235
|
+
const route = await this.getWorkspaceRoute(workspaceId);
|
|
236
|
+
return route.agentType;
|
|
237
|
+
}
|
|
238
|
+
getAgentTypes() {
|
|
239
|
+
return this.options.getCapabilities().snapshot.agents.map((agent) => agent.agentType);
|
|
240
|
+
}
|
|
226
241
|
getCapabilities() {
|
|
227
242
|
return this.options.getCapabilities();
|
|
228
243
|
}
|
|
@@ -432,10 +447,13 @@ class WorkspaceRouter {
|
|
|
432
447
|
const defaultRoute = await this.getWorkspaceRoute(workspaceId);
|
|
433
448
|
const row = this.store.getThreadRow(threadId);
|
|
434
449
|
const threadAgentType = String(row?.agent_type || '').trim().toLowerCase();
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
450
|
+
const route = !threadAgentType || threadAgentType === defaultRoute.agentType
|
|
451
|
+
? defaultRoute
|
|
452
|
+
: await this.getWorkspaceRoute(workspaceId, threadAgentType);
|
|
453
|
+
const externalThread = this.store.getExternalThreadByThreadId(threadId);
|
|
454
|
+
return externalThread
|
|
455
|
+
? withThreadWorkspacePath(route, externalThread.workspacePath)
|
|
456
|
+
: route;
|
|
439
457
|
}
|
|
440
458
|
async getWorkspaceRoute(workspaceId, agentTypeOverride = '') {
|
|
441
459
|
const configState = await this.options.readConfigState();
|
|
@@ -477,11 +495,12 @@ class WorkspaceRouter {
|
|
|
477
495
|
}
|
|
478
496
|
}
|
|
479
497
|
resolveProjectRoute(configState, project) {
|
|
498
|
+
const routeProject = this.withResolvedProjectProvider(project);
|
|
480
499
|
for (const runtime of this.options.getAgentRuntimes?.() || []) {
|
|
481
|
-
if (!runtime.matchesProject(
|
|
500
|
+
if (!runtime.matchesProject(routeProject)) {
|
|
482
501
|
continue;
|
|
483
502
|
}
|
|
484
|
-
const route = runtime.createRoute(configState,
|
|
503
|
+
const route = runtime.createRoute(configState, routeProject);
|
|
485
504
|
if (route) {
|
|
486
505
|
return {
|
|
487
506
|
...route,
|
|
@@ -489,14 +508,14 @@ class WorkspaceRouter {
|
|
|
489
508
|
};
|
|
490
509
|
}
|
|
491
510
|
}
|
|
492
|
-
if ((0, workspace_route_config_js_1.isLocalCoreNativeAcpProject)(
|
|
493
|
-
const agentType = String(
|
|
511
|
+
if ((0, workspace_route_config_js_1.isLocalCoreNativeAcpProject)(routeProject)) {
|
|
512
|
+
const agentType = String(routeProject.agent?.type || '').trim().toLowerCase() || 'localcore-acp';
|
|
494
513
|
return {
|
|
495
514
|
kind: 'localcore-acp',
|
|
496
515
|
agentType,
|
|
497
516
|
transport: 'localcore-acp',
|
|
498
517
|
config: {
|
|
499
|
-
...(0, workspace_route_config_js_1.toLocalCoreProjectConfig)(configState,
|
|
518
|
+
...(0, workspace_route_config_js_1.toLocalCoreProjectConfig)(configState, routeProject),
|
|
500
519
|
agentType,
|
|
501
520
|
},
|
|
502
521
|
supportsStreamingProbe: true,
|
|
@@ -510,6 +529,23 @@ class WorkspaceRouter {
|
|
|
510
529
|
}
|
|
511
530
|
return null;
|
|
512
531
|
}
|
|
532
|
+
withResolvedProjectProvider(project) {
|
|
533
|
+
const providerId = String(project.agent?.options?.provider_id || '').trim();
|
|
534
|
+
if (!providerId) {
|
|
535
|
+
return project;
|
|
536
|
+
}
|
|
537
|
+
const provider = this.store.getModelProvider(providerId);
|
|
538
|
+
if (!provider) {
|
|
539
|
+
throw new Error(`Workspace "${project.name}" references missing provider "${providerId}".`);
|
|
540
|
+
}
|
|
541
|
+
return {
|
|
542
|
+
...project,
|
|
543
|
+
agent: {
|
|
544
|
+
...project.agent,
|
|
545
|
+
providers: [provider],
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
}
|
|
513
549
|
}
|
|
514
550
|
exports.WorkspaceRouter = WorkspaceRouter;
|
|
515
551
|
function createWorkspaceRouter(options) {
|
|
@@ -540,6 +576,25 @@ function withAgentTypeOverride(project, agentType) {
|
|
|
540
576
|
},
|
|
541
577
|
};
|
|
542
578
|
}
|
|
579
|
+
function withThreadWorkspacePath(route, workspacePath) {
|
|
580
|
+
const workDir = String(workspacePath || '').trim();
|
|
581
|
+
if (!workDir) {
|
|
582
|
+
return route;
|
|
583
|
+
}
|
|
584
|
+
return {
|
|
585
|
+
...route,
|
|
586
|
+
config: {
|
|
587
|
+
...route.config,
|
|
588
|
+
workDir,
|
|
589
|
+
sandbox: route.config.sandbox
|
|
590
|
+
? {
|
|
591
|
+
...route.config.sandbox,
|
|
592
|
+
workspaceHostPath: workDir,
|
|
593
|
+
}
|
|
594
|
+
: route.config.sandbox,
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
}
|
|
543
598
|
function isLocalSlashCommand(content) {
|
|
544
599
|
const text = typeof content === 'string' ? content : String(content.displayText || '');
|
|
545
600
|
const normalized = text.trim().toLowerCase();
|
|
@@ -11,8 +11,11 @@ function detectInstalledAgentRuntimes(options = {}) {
|
|
|
11
11
|
const env = options.env || process.env;
|
|
12
12
|
const configuredCommands = collectConfiguredAgentCommands(options.config);
|
|
13
13
|
const detectedAt = (options.now || new Date()).toISOString();
|
|
14
|
-
const versionTimeoutMs = options.versionTimeoutMs ??
|
|
15
|
-
|
|
14
|
+
const versionTimeoutMs = options.versionTimeoutMs ?? 1500;
|
|
15
|
+
const agentTypes = options.runtimeId
|
|
16
|
+
? desktop_js_1.DESKTOP_AGENT_TYPE_OPTIONS.filter((agentType) => agentType === options.runtimeId)
|
|
17
|
+
: desktop_js_1.DESKTOP_AGENT_TYPE_OPTIONS;
|
|
18
|
+
return agentTypes.map((agentType) => {
|
|
16
19
|
const definition = (0, index_js_1.resolveAgentRuntimeDefinition)(agentType);
|
|
17
20
|
const detection = definition?.detection;
|
|
18
21
|
if (detection?.builtin || agentType === desktop_js_1.LOCALCORE_ACP_AGENT_TYPE) {
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CURRENT_DESKTOP_CONFIG_VERSION = void 0;
|
|
4
|
+
exports.migrateDesktopConnectConfig = migrateDesktopConnectConfig;
|
|
5
|
+
exports.normalizeDesktopProviderForStorage = normalizeDesktopProviderForStorage;
|
|
6
|
+
const index_js_1 = require("../../../../packages/contracts/src/index.js");
|
|
7
|
+
exports.CURRENT_DESKTOP_CONFIG_VERSION = 2;
|
|
8
|
+
function migrateDesktopConnectConfig(input) {
|
|
9
|
+
const config = cloneConfig(input);
|
|
10
|
+
const warnings = [];
|
|
11
|
+
let changed = false;
|
|
12
|
+
if (config.config_version !== exports.CURRENT_DESKTOP_CONFIG_VERSION) {
|
|
13
|
+
config.config_version = exports.CURRENT_DESKTOP_CONFIG_VERSION;
|
|
14
|
+
changed = true;
|
|
15
|
+
}
|
|
16
|
+
const deploymentProfile = String(config.deployment_profile || '').trim();
|
|
17
|
+
for (const project of Array.isArray(config.projects) ? config.projects : []) {
|
|
18
|
+
const options = ensureProjectOptions(project);
|
|
19
|
+
if ('tenant_id' in options && !options.user_id) {
|
|
20
|
+
options.user_id = String(options.tenant_id || '').trim() || 'local';
|
|
21
|
+
delete options.tenant_id;
|
|
22
|
+
changed = true;
|
|
23
|
+
warnings.push(`Project "${project.name}" migrated agent.options.tenant_id to user_id.`);
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(project.agent?.providers)) {
|
|
26
|
+
for (const provider of project.agent.providers) {
|
|
27
|
+
if (normalizeDeepSeekProvider(provider)) {
|
|
28
|
+
changed = true;
|
|
29
|
+
warnings.push(`Project "${project.name}" normalized a DeepSeek provider name.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const sandbox = normalizeSandboxOptions(options.sandbox);
|
|
34
|
+
if (sandbox.changed) {
|
|
35
|
+
options.sandbox = sandbox.value;
|
|
36
|
+
changed = true;
|
|
37
|
+
}
|
|
38
|
+
if (options.sandbox?.enabled) {
|
|
39
|
+
const providerMigration = migrateProjectSandboxProvider(config, options.sandbox, deploymentProfile);
|
|
40
|
+
if (providerMigration.changed) {
|
|
41
|
+
changed = true;
|
|
42
|
+
}
|
|
43
|
+
const imageMigration = migrateProjectSandboxRuntimeImage(config, project, options.sandbox);
|
|
44
|
+
if (imageMigration.changed) {
|
|
45
|
+
changed = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { config, changed, warnings };
|
|
50
|
+
}
|
|
51
|
+
function ensureProjectOptions(project) {
|
|
52
|
+
project.agent ||= { type: 'pi', options: {}, providers: [] };
|
|
53
|
+
project.agent.options ||= {};
|
|
54
|
+
return project.agent.options;
|
|
55
|
+
}
|
|
56
|
+
function normalizeDeepSeekProvider(provider) {
|
|
57
|
+
const name = String(provider.name || '').trim().toLowerCase();
|
|
58
|
+
const baseUrl = String(provider.base_url || '').trim().toLowerCase();
|
|
59
|
+
if (name === 'deepseek' || (!name.startsWith('deepseek-') && !baseUrl.includes('deepseek.com'))) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
provider.name = 'deepseek';
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
function normalizeDesktopProviderForStorage(provider) {
|
|
66
|
+
const next = JSON.parse(JSON.stringify(provider || {}));
|
|
67
|
+
normalizeDeepSeekProvider(next);
|
|
68
|
+
return next;
|
|
69
|
+
}
|
|
70
|
+
function normalizeSandboxOptions(input) {
|
|
71
|
+
if (!input || typeof input !== 'object') {
|
|
72
|
+
return { value: input, changed: false };
|
|
73
|
+
}
|
|
74
|
+
const sandbox = { ...input };
|
|
75
|
+
let changed = false;
|
|
76
|
+
if (sandbox.enabled) {
|
|
77
|
+
if (!sandbox.provider_id) {
|
|
78
|
+
sandbox.provider_id = index_js_1.DEFAULT_SANDBOX_PROVIDER_ID;
|
|
79
|
+
changed = true;
|
|
80
|
+
}
|
|
81
|
+
if (!sandbox.state_scope) {
|
|
82
|
+
sandbox.state_scope = 'project';
|
|
83
|
+
changed = true;
|
|
84
|
+
}
|
|
85
|
+
if (!sandbox.sandbox_lifecycle) {
|
|
86
|
+
sandbox.sandbox_lifecycle = 'per_thread';
|
|
87
|
+
changed = true;
|
|
88
|
+
}
|
|
89
|
+
if (!sandbox.idle_seconds) {
|
|
90
|
+
sandbox.idle_seconds = 900;
|
|
91
|
+
changed = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { value: sandbox, changed };
|
|
95
|
+
}
|
|
96
|
+
function migrateProjectSandboxProvider(config, sandbox, deploymentProfile) {
|
|
97
|
+
const providerId = String(sandbox.provider_id || index_js_1.DEFAULT_SANDBOX_PROVIDER_ID).trim() || index_js_1.DEFAULT_SANDBOX_PROVIDER_ID;
|
|
98
|
+
config.sandbox_providers = Array.isArray(config.sandbox_providers) ? config.sandbox_providers : [];
|
|
99
|
+
const existing = config.sandbox_providers.find((provider) => provider.id === providerId);
|
|
100
|
+
if (existing) {
|
|
101
|
+
return { changed: false };
|
|
102
|
+
}
|
|
103
|
+
const defaultProvider = (0, index_js_1.defaultSandboxProviderForProfile)(deploymentProfile);
|
|
104
|
+
config.sandbox_providers.push({
|
|
105
|
+
...defaultProvider,
|
|
106
|
+
id: providerId,
|
|
107
|
+
type: sandbox.provider || defaultProvider.type,
|
|
108
|
+
server_url: sandbox.server_url || defaultProvider.server_url,
|
|
109
|
+
api_key_env: sandbox.api_key_env || defaultProvider.api_key_env,
|
|
110
|
+
});
|
|
111
|
+
return { changed: true };
|
|
112
|
+
}
|
|
113
|
+
function migrateProjectSandboxRuntimeImage(config, project, sandbox) {
|
|
114
|
+
const agentType = String(project.agent?.type || 'pi').trim().toLowerCase() || 'pi';
|
|
115
|
+
const fallback = (0, index_js_1.defaultSandboxRuntimeImage)(agentType);
|
|
116
|
+
const imageId = String(sandbox.runtime_image_id || fallback.id).trim() || fallback.id;
|
|
117
|
+
const assignedRuntimeImage = sandbox.runtime_image_id === imageId;
|
|
118
|
+
sandbox.runtime_image_id = imageId;
|
|
119
|
+
config.sandbox_runtime_images = Array.isArray(config.sandbox_runtime_images) ? config.sandbox_runtime_images : [];
|
|
120
|
+
const existing = config.sandbox_runtime_images.find((image) => image.id === imageId);
|
|
121
|
+
if (existing) {
|
|
122
|
+
let changed = !assignedRuntimeImage;
|
|
123
|
+
if (!existing.transport && isBuiltInHttpSandboxRuntimeImage(existing.id, existing.image, fallback.image)) {
|
|
124
|
+
existing.transport = fallback.transport;
|
|
125
|
+
changed = true;
|
|
126
|
+
}
|
|
127
|
+
if (!existing.entrypoint) {
|
|
128
|
+
existing.entrypoint = fallback.entrypoint;
|
|
129
|
+
changed = true;
|
|
130
|
+
}
|
|
131
|
+
return { changed };
|
|
132
|
+
}
|
|
133
|
+
config.sandbox_runtime_images.push({
|
|
134
|
+
...fallback,
|
|
135
|
+
id: imageId,
|
|
136
|
+
image: sandbox.image || fallback.image,
|
|
137
|
+
transport: fallback.transport,
|
|
138
|
+
acp_port: sandbox.acp_port || fallback.acp_port,
|
|
139
|
+
entrypoint: sandbox.entrypoint || fallback.entrypoint,
|
|
140
|
+
runtime_command: fallback.runtime_command,
|
|
141
|
+
runtime_args: fallback.runtime_args,
|
|
142
|
+
workspace_mount_path: sandbox.workspace_mount_path || fallback.workspace_mount_path,
|
|
143
|
+
state_mount_path: sandbox.state_mount_path || fallback.state_mount_path,
|
|
144
|
+
});
|
|
145
|
+
return { changed: true };
|
|
146
|
+
}
|
|
147
|
+
function isBuiltInHttpSandboxRuntimeImage(id, image, fallbackImage) {
|
|
148
|
+
return id === index_js_1.DEFAULT_SANDBOX_RUNTIME_IMAGE_ID && String(image || fallbackImage).trim() === fallbackImage;
|
|
149
|
+
}
|
|
150
|
+
function cloneConfig(input) {
|
|
151
|
+
return JSON.parse(JSON.stringify(input || {}));
|
|
152
|
+
}
|