@xopcai/xopc 0.0.221 → 0.0.223
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-NItGQmvR.js → activity-store--GBciH10.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B8SBTGg3.js → agent-avatar-dicebear-C93T3FLD.js} +1 -1
- package/dist/gateway/static/root/assets/agents-Ba4XF0Im.js +68 -0
- package/dist/gateway/static/root/assets/{api-53ZXsuyr.js → api-HoIz_ija.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BtmPXaqu.js → app-management-settings-panel-Bhl8Xluk.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-t7HoJyNN.js → appearance-settings-CywEN-kG.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BZY09nuJ.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-D8o8CP9Y.js → archive-plugin-CteCVsBP.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CsLXzas8.js → attachment-load-CbNE_EPd.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-D-zgoAKz.js → automations-page-Bcqk6tOx.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-DtI6vsMf.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-B-MjP_22.js → binary-plugins-M_i3WS5M.js} +1 -1
- package/dist/gateway/static/root/assets/block-editor-eg9LEH2o.js +184 -0
- package/dist/gateway/static/root/assets/browser-settings-page-kKwbvzjj.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-Bi6RSSpD.js → browser-workflow-inputs-1UZ0vnIy.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-EEFHUm1i.js → browser-workflows-page-D8ATQqZ5.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CZRcis8B.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-pC2fno7r.js → capability-presets-api-yNqTIuyd.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-CgdRkwnk.js +3 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-B5Szgu_z.js → channel-recipient-api-krezGsKc.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DETCY0Ku.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-DMxB7slL.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DT-OFl4r.js → chat-terminal-dock-DQ5bB4Su.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-D9D92u28.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-MZ_AJqrm.js → cron-expression-CEwPkdhh.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-Bv9hZLuD.js → date-picker-DDAxTir8.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-D-6oO_Vk.js → dependency-picker-CYVoSZwI.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-CiI5caKj.js → desktop-pet-CrNKfW_c.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DhkSOy4K.js → desktop-pet-settings-C06PaB46.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-C4s4Pz8I.js → directory-picker-path-field--D7laeLF.js} +1 -1
- package/dist/gateway/static/root/assets/dist-DaxPZj9e.js +1 -0
- package/dist/gateway/static/root/assets/{dist-DY4Af0fY.js → dist-J_ySZvz0.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DE7J1-6W.js → extension-debug-page-Dn4Px9KQ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DSnACD7E.js → extension-page-DzLf3fMQ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Dk7k2Pok.js → extension-settings-page-DIchwtvB.js} +1 -1
- package/dist/gateway/static/root/assets/floating-ui.dom-B7uQOZZW.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-IOA1OlHx.js → gateway-config-api-SmTGLhqK.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-BzTbnu4O.js → gateway-config-swr-yUxMMVjK.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-FX7QsgSQ.js → gateway-settings-yCDkOYzA.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-B2zpkNvi.js → gateway-startup-retry-9mrsL84j.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CquIULHX.js +1 -0
- package/dist/gateway/static/root/assets/home-page-COSGBh4c.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-BXRjz-iY.js → image-generation-api-CgFAGDi8.js} +1 -1
- package/dist/gateway/static/root/assets/index-5XkDWH_Q.css +2 -0
- package/dist/gateway/static/root/assets/index-wnDPGRTi.js +74 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BjYiM4xq.js → keyboard-shortcuts-settings-DI2To7yl.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CAF5SZXv.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-7DHvwSgA.js → local-apps-page-CSEJsQ1F.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-iKjqemWG.js → locale-store-CPylQjH9.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-D1KFPHL1.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-BSxppo9Z.js → management-settings-CgyaIyuk.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-D4oDjZtl.js → markdown-split-paG9qap9.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-CUsob4Pz.js +69 -0
- package/dist/gateway/static/root/assets/{media-plugins-BPNTGROA.js → media-plugins-0Q-c_QIy.js} +1 -1
- package/dist/gateway/static/root/assets/messages-B82nsi9k.js +3 -0
- package/dist/gateway/static/root/assets/notes-api-CfKZYrBC.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-DU5tKPTq.js → notes-page-Bvb-ycX_.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-DelxGBof.js +4 -0
- package/dist/gateway/static/root/assets/oauth-authorization-window-Cdolr2wE.js +1 -0
- package/dist/gateway/static/root/assets/{popover-select-BzdnTy3h.js → popover-select-CccGri5Y.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-CPoQvD6P.js → product-open-page-DrvBwAns.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-C2EnYXEQ.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BiMPU6Oa.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-Cx3JxXSL.js → registry-api-B_5D8epF.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CpbNivVs.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-xqnWcvIv.js → runtime-tools-settings-panel-DKjdN4Lr.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CuIDPYu6.js → schema-form-DskqaNqC.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BxKtzsKI.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BfBKMMUx.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-DkAv9ncE.js → settings-form-section-CZlMvHA9.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-BJUQiEKb.js → settings-loading-skeleton-DS6lcAg9.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-KHRbLwmw.js → settings-page-oE5J9tsV.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-C8jd20Db.js → setup-status-panel-C7oFCIqD.js} +1 -1
- package/dist/gateway/static/root/assets/share-preview-page-CPFAj8NE.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-B46DWZK4.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CyKolUZ-.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CKhR9J81.js → skills-page-Bh4gFi8e.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-AYX-e5sD.js → skills-page.utils-BQaUWP9z.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-IIF-K9ML.js → system-settings-panel-COAZoh_O.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-CXkhprf-.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-BOD2D0dJ.js → theme-store-BN-32Fz5.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-DcktF1j1.js → use-autosave-BAkToU15.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-Br5wgARM.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-BMkNTHHE.js → voice-api-key-field-CC4z9-ux.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-DVoiXekA.js → work-discovery-overlay-dLVUYSSE.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cw4LQjuM.js → workflow-run-setup-panel-BYU5-0KF.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-CJ24a1HM.js +5 -0
- package/dist/gateway/static/root/index.html +15 -14
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +3 -0
- package/dist/src/agent/agent-manager.d.ts +3 -0
- package/dist/src/agent/agent-manager.js +34 -28
- package/dist/src/agent/embedded/index.d.ts +1 -1
- package/dist/src/agent/embedded/index.js +2 -2
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +102 -63
- package/dist/src/agent/embedded/run-turn.js +56 -28
- package/dist/src/agent/embedded/runs.d.ts +16 -29
- package/dist/src/agent/embedded/runs.js +44 -65
- package/dist/src/agent/embedded/types.d.ts +4 -0
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/ipc/inbox.js +1 -1
- package/dist/src/agent/memory/create-memory-manager.js +1 -1
- package/dist/src/agent/orchestration/agent-run-supervisor.d.ts +28 -0
- package/dist/src/agent/orchestration/agent-run-supervisor.js +49 -0
- package/dist/src/agent/orchestration/agent-turn-policy.d.ts +18 -0
- package/dist/src/agent/orchestration/agent-turn-policy.js +36 -0
- package/dist/src/agent/orchestration/llm-turn-retry.d.ts +5 -0
- package/dist/src/agent/orchestration/llm-turn-retry.js +34 -4
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +10 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +25 -4
- package/dist/src/agent/service/async-queue.d.ts +16 -3
- package/dist/src/agent/service/async-queue.js +29 -11
- package/dist/src/agent/service/process-direct-streaming.js +27 -4
- package/dist/src/agent/service.js +3 -2
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/tasks/task-judge-service.js +3 -3
- package/dist/src/agent/tools/exec-command.d.ts +2 -0
- package/dist/src/agent/tools/exec-command.js +70 -7
- package/dist/src/agent-runtime/index.js +1 -1
- package/dist/src/agent-runtime/runtime-profile.js +1 -1
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/oauth/index.js +3 -3
- package/dist/src/auth/oauth/registry.d.ts +2 -0
- package/dist/src/auth/oauth/registry.js +20 -12
- package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
- package/dist/src/auth/oauth/xopc-cloud.js +32 -16
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +1 -1
- package/dist/src/channels/attachments/voice-stt-webchat.js +20 -3
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/tunnel.js +4 -5
- package/dist/src/config/index.js +4 -4
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +18 -0
- package/dist/src/config/schema.js +19 -1
- package/dist/src/connectors/learning-coordinator.js +3 -19
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/hono/app.js +2 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/oauth-async.d.ts +1 -0
- package/dist/src/gateway/hono/oauth-async.js +11 -4
- package/dist/src/gateway/hono/routes/config.js +10 -0
- package/dist/src/gateway/hono/routes/host-fs.js +40 -1
- package/dist/src/gateway/hono/routes/media.js +33 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/notes.js +162 -7
- package/dist/src/gateway/hono/routes/shares.js +141 -6
- package/dist/src/gateway/hono/routes/tunnel.js +47 -10
- package/dist/src/gateway/hono/routes/voice.d.ts +2 -6
- package/dist/src/gateway/hono/routes/voice.js +28 -5
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service.js +3 -3
- package/dist/src/notes/service.d.ts +6 -2
- package/dist/src/notes/service.js +36 -4
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +3 -3
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/share/note-share-service.d.ts +67 -0
- package/dist/src/share/note-share-service.js +283 -0
- package/dist/src/share/share-config.js +32 -3
- package/dist/src/share/share-landing.d.ts +5 -1
- package/dist/src/share/share-landing.js +28 -1
- package/dist/src/share/share-store.d.ts +34 -5
- package/dist/src/share/share-store.js +125 -19
- package/dist/src/share/share-thumbnail.js +4 -2
- package/dist/src/share/share-types.d.ts +52 -14
- package/dist/src/share/share-types.js +9 -0
- package/dist/src/share/share-zip.d.ts +2 -2
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/tunnel/env.d.ts +12 -6
- package/dist/src/tunnel/env.js +34 -26
- package/dist/src/tunnel/gateway-lifecycle.js +2 -13
- package/dist/src/tunnel/index.d.ts +1 -1
- package/dist/src/tunnel/index.js +2 -2
- package/dist/src/tunnel/tunnel-audit.d.ts +1 -1
- package/dist/src/tunnel/tunnel-config.d.ts +1 -1
- package/dist/src/tunnel/tunnel-config.js +9 -4
- package/dist/src/tunnel/tunnel-service.d.ts +1 -1
- package/dist/src/tunnel/tunnel-service.js +3 -0
- package/dist/src/tunnel/well-known.d.ts +1 -1
- package/dist/src/tunnel/well-known.js +1 -1
- package/dist/src/tunnel/xopc-cloud-registration.d.ts +9 -0
- package/dist/src/tunnel/xopc-cloud-registration.js +42 -0
- package/dist/src/voice/audio/normalize.d.ts +7 -0
- package/dist/src/voice/audio/normalize.js +30 -4
- package/dist/src/voice/local/runtime-worker.js +26 -6
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +8 -14
- package/dist/gateway/static/root/assets/agents-Brs2-m6t.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-DJ_Dsb1j.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-DehLRXfd.js +0 -6
- package/dist/gateway/static/root/assets/block-editor-i4CfDqLG.js +0 -184
- package/dist/gateway/static/root/assets/browser-settings-page-C3QIO4Ti.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BHhUp7FW.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DoClNVLz.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-Je-9a5ZC.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-ByRbxC6z.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-D8z9Trw4.js +0 -2
- package/dist/gateway/static/root/assets/dist-C230izr8.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-D5CGVyci.js +0 -1
- package/dist/gateway/static/root/assets/home-page-DzfZFZx5.js +0 -1
- package/dist/gateway/static/root/assets/index-Dcj5KJRg.css +0 -2
- package/dist/gateway/static/root/assets/index-EvA8c7fo.js +0 -74
- package/dist/gateway/static/root/assets/local-app-workbench-page-hPyTaVYU.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-DW0xMKWP.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-DYkxMtJA.js +0 -69
- package/dist/gateway/static/root/assets/messages-kx5W39dO.js +0 -3
- package/dist/gateway/static/root/assets/notes-api-DJizatxh.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-D669d98r.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-CpsQ9PTA.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CitO1LMc.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C9-bL4V6.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CPSARi4y.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BxT80Fmr.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-WCVtJ3sX.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-DrQ_cOXh.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-C_4cG30x.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-CYjsecEr.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-Cy1D2hkt.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DKKH1_Yt.js +0 -5
|
@@ -1,91 +1,70 @@
|
|
|
1
|
-
import { createLogger } from "../../utils/logger/index.js";
|
|
2
|
-
import { init_logger } from "../../utils/logger.js";
|
|
3
1
|
//#region src/agent/embedded/runs.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*/
|
|
2
|
+
var EmbeddedRunConflictError = class extends Error {
|
|
3
|
+
constructor(sessionKey, activeRunId) {
|
|
4
|
+
super(`Session '${sessionKey}' already has active embedded run '${activeRunId}'`);
|
|
5
|
+
this.sessionKey = sessionKey;
|
|
6
|
+
this.activeRunId = activeRunId;
|
|
7
|
+
this.name = "EmbeddedRunConflictError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
/** Owns one process-local execution lease per session while leaving steer/abort on the control plane. */
|
|
13
11
|
var EmbeddedRunRegistry = class {
|
|
14
12
|
bySessionKey = /* @__PURE__ */ new Map();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.byRunId.delete(handle.runId);
|
|
13
|
+
acquire(identity) {
|
|
14
|
+
const active = this.bySessionKey.get(identity.sessionKey);
|
|
15
|
+
if (active) throw new EmbeddedRunConflictError(identity.sessionKey, active.runId);
|
|
16
|
+
const entry = {
|
|
17
|
+
...identity,
|
|
18
|
+
abortController: new AbortController()
|
|
19
|
+
};
|
|
20
|
+
this.bySessionKey.set(identity.sessionKey, entry);
|
|
21
|
+
return {
|
|
22
|
+
signal: entry.abortController.signal,
|
|
23
|
+
attach: async (session, abort) => {
|
|
24
|
+
entry.handle = {
|
|
25
|
+
...identity,
|
|
26
|
+
session,
|
|
27
|
+
abort
|
|
28
|
+
};
|
|
29
|
+
if (entry.abortController.signal.aborted) await abort();
|
|
30
|
+
},
|
|
31
|
+
release: () => {
|
|
32
|
+
if (this.bySessionKey.get(identity.sessionKey) === entry) this.bySessionKey.delete(identity.sessionKey);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
38
35
|
}
|
|
39
36
|
getBySessionKey(sessionKey) {
|
|
40
|
-
return this.bySessionKey.get(sessionKey);
|
|
41
|
-
}
|
|
42
|
-
getByRunId(runId) {
|
|
43
|
-
return this.byRunId.get(runId);
|
|
37
|
+
return this.bySessionKey.get(sessionKey)?.handle;
|
|
44
38
|
}
|
|
45
39
|
async abortBySessionKey(sessionKey) {
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
48
|
-
|
|
40
|
+
const entry = this.bySessionKey.get(sessionKey);
|
|
41
|
+
if (!entry) return false;
|
|
42
|
+
entry.abortController.abort(/* @__PURE__ */ new Error("Embedded run aborted"));
|
|
43
|
+
if (entry.handle) await entry.handle.abort();
|
|
49
44
|
return true;
|
|
50
45
|
}
|
|
51
46
|
async steerBySessionKey(sessionKey, text) {
|
|
52
|
-
const handle = this.
|
|
47
|
+
const handle = this.getBySessionKey(sessionKey);
|
|
53
48
|
if (!handle) return false;
|
|
54
49
|
await handle.session.steer(text);
|
|
55
50
|
return true;
|
|
56
51
|
}
|
|
57
|
-
/** Test-only helper to drop all registrations without touching live sessions. */
|
|
58
|
-
resetForTest() {
|
|
59
|
-
this.bySessionKey.clear();
|
|
60
|
-
this.byRunId.clear();
|
|
61
|
-
}
|
|
62
52
|
size() {
|
|
63
53
|
return this.bySessionKey.size;
|
|
64
54
|
}
|
|
65
55
|
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
* keep working until every caller has been migrated.
|
|
70
|
-
*/
|
|
71
|
-
const defaultEmbeddedRunRegistry = new EmbeddedRunRegistry();
|
|
72
|
-
function registerEmbeddedRun(handle) {
|
|
73
|
-
defaultEmbeddedRunRegistry.register(handle);
|
|
74
|
-
}
|
|
75
|
-
function unregisterEmbeddedRun(handle) {
|
|
76
|
-
defaultEmbeddedRunRegistry.unregister(handle);
|
|
56
|
+
const embeddedRunRegistry = new EmbeddedRunRegistry();
|
|
57
|
+
function acquireEmbeddedRunLease(identity) {
|
|
58
|
+
return embeddedRunRegistry.acquire(identity);
|
|
77
59
|
}
|
|
78
60
|
function getEmbeddedRunBySessionKey(sessionKey) {
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
function getEmbeddedRunByRunId(runId) {
|
|
82
|
-
return defaultEmbeddedRunRegistry.getByRunId(runId);
|
|
61
|
+
return embeddedRunRegistry.getBySessionKey(sessionKey);
|
|
83
62
|
}
|
|
84
63
|
function abortEmbeddedRun(sessionKey) {
|
|
85
|
-
return
|
|
64
|
+
return embeddedRunRegistry.abortBySessionKey(sessionKey);
|
|
86
65
|
}
|
|
87
66
|
function queueEmbeddedSteer(sessionKey, text) {
|
|
88
|
-
return
|
|
67
|
+
return embeddedRunRegistry.steerBySessionKey(sessionKey, text);
|
|
89
68
|
}
|
|
90
69
|
//#endregion
|
|
91
|
-
export { EmbeddedRunRegistry, abortEmbeddedRun,
|
|
70
|
+
export { EmbeddedRunConflictError, EmbeddedRunRegistry, abortEmbeddedRun, acquireEmbeddedRunLease, getEmbeddedRunBySessionKey, queueEmbeddedSteer };
|
|
@@ -2,6 +2,7 @@ import type { AgentMessage, AgentToolResult, ThinkingLevel } from '@earendil-wor
|
|
|
2
2
|
import type { AssistantMessageEvent, Model, Api, ImageContent } from '@earendil-works/pi-ai';
|
|
3
3
|
import type { SessionStore } from '../../session/store.js';
|
|
4
4
|
import type { EmbeddedTranscriptRuntime } from './transcript-runtime.js';
|
|
5
|
+
import type { AgentTurnPolicy } from '../orchestration/agent-turn-policy.js';
|
|
5
6
|
export type EmbeddedStreamEvent = {
|
|
6
7
|
type: 'agent_start';
|
|
7
8
|
runId?: string;
|
|
@@ -97,6 +98,7 @@ export type RunXopcEmbeddedTurnParams = {
|
|
|
97
98
|
sessionStore?: SessionStore;
|
|
98
99
|
transcriptRuntime?: EmbeddedTranscriptRuntime;
|
|
99
100
|
timeoutMs: number;
|
|
101
|
+
turnPolicy?: AgentTurnPolicy;
|
|
100
102
|
abortSignal?: AbortSignal;
|
|
101
103
|
onEvent?: (event: EmbeddedStreamEvent) => void;
|
|
102
104
|
images?: ImageContent[];
|
|
@@ -105,6 +107,8 @@ export type RunXopcEmbeddedTurnParams = {
|
|
|
105
107
|
};
|
|
106
108
|
export type RunXopcEmbeddedTurnResult = {
|
|
107
109
|
ok: boolean;
|
|
110
|
+
/** False for harness failures that must not trigger another model attempt. */
|
|
111
|
+
retryable?: boolean;
|
|
108
112
|
errorMessage?: string;
|
|
109
113
|
lastAssistantText?: string;
|
|
110
114
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getAgentDefaultImageModelConfig, getAgentDefaultModelRef, init_schema, parseModelRef } from "../../config/schema.js";
|
|
2
2
|
import { init_agent_scope, resolveDefaultAgentId } from "../agent-scope.js";
|
|
3
|
-
import { getDefaultModelSync, getModelsByProvider, init_providers, isProviderConfiguredSync, resolveModel } from "../../providers/index.js";
|
|
4
3
|
import { resolveEffectiveAgentManifestForAgent } from "../../config/agent-profile.js";
|
|
4
|
+
import { getDefaultModelSync, getModelsByProvider, init_providers, isProviderConfiguredSync, resolveModel } from "../../providers/index.js";
|
|
5
5
|
import { resolveAgentModelFallbackValues, resolveAgentModelPrimaryValue } from "../../config/model-input.js";
|
|
6
6
|
import { buildCapabilityPlansForConfig } from "../../capabilities/readiness/from-config.js";
|
|
7
7
|
import "../../capabilities/readiness/index.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
4
3
|
import { init_paths, resolveAgentDir } from "../../config/paths.js";
|
|
4
|
+
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
5
5
|
import { join } from "path";
|
|
6
6
|
import { existsSync, watch } from "fs";
|
|
7
7
|
import { mkdir, readFile, readdir, rename } from "fs/promises";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { buildMemoryRuntime } from "../../agent-runtime/memory-runtime.js";
|
|
2
1
|
import { isMemorySubsystemEnabled } from "./memory-config.js";
|
|
3
2
|
import { BuiltinMemoryProvider } from "./builtin-provider.js";
|
|
4
3
|
import { MemoryManager } from "./manager.js";
|
|
5
4
|
import { loadMemoryPluginProviders } from "./plugin-discovery.js";
|
|
5
|
+
import { buildMemoryRuntime } from "../../agent-runtime/memory-runtime.js";
|
|
6
6
|
//#region src/agent/memory/create-memory-manager.ts
|
|
7
7
|
function createMemoryManagerFromConfig(config) {
|
|
8
8
|
const routing = resolveMemoryManagerOptions(config);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type ModelAttemptPlan = {
|
|
2
|
+
ok: true;
|
|
3
|
+
timeoutMs: number;
|
|
4
|
+
remainingMs: number;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
reason: string;
|
|
8
|
+
};
|
|
9
|
+
export interface AgentRunSupervisorOptions {
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
deadlineAtMs?: number;
|
|
12
|
+
parentSignal?: AbortSignal;
|
|
13
|
+
minimumFallbackMs?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Minimal run-level coordination: root cancellation and per-attempt deadline planning. */
|
|
16
|
+
export declare class AgentRunSupervisor {
|
|
17
|
+
readonly deadlineAtMs: number;
|
|
18
|
+
readonly signal: AbortSignal;
|
|
19
|
+
private readonly controller;
|
|
20
|
+
private readonly timeout;
|
|
21
|
+
private readonly forwardParentAbort;
|
|
22
|
+
private readonly timeoutMs;
|
|
23
|
+
private readonly minimumFallbackMs;
|
|
24
|
+
private readonly parentSignal?;
|
|
25
|
+
constructor(options: AgentRunSupervisorOptions);
|
|
26
|
+
planModelAttempt(isFallback: boolean): ModelAttemptPlan;
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//#region src/agent/orchestration/agent-run-supervisor.ts
|
|
2
|
+
/** Minimal run-level coordination: root cancellation and per-attempt deadline planning. */
|
|
3
|
+
var AgentRunSupervisor = class {
|
|
4
|
+
deadlineAtMs;
|
|
5
|
+
signal;
|
|
6
|
+
controller = new AbortController();
|
|
7
|
+
timeout;
|
|
8
|
+
forwardParentAbort;
|
|
9
|
+
timeoutMs;
|
|
10
|
+
minimumFallbackMs;
|
|
11
|
+
parentSignal;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.timeoutMs = options.timeoutMs;
|
|
14
|
+
this.minimumFallbackMs = options.minimumFallbackMs ?? 5e3;
|
|
15
|
+
this.deadlineAtMs = options.deadlineAtMs ?? Date.now() + options.timeoutMs;
|
|
16
|
+
this.parentSignal = options.parentSignal;
|
|
17
|
+
this.signal = this.controller.signal;
|
|
18
|
+
this.forwardParentAbort = () => this.controller.abort(this.parentSignal?.reason);
|
|
19
|
+
if (this.parentSignal?.aborted) this.forwardParentAbort();
|
|
20
|
+
else this.parentSignal?.addEventListener("abort", this.forwardParentAbort, { once: true });
|
|
21
|
+
this.timeout = setTimeout(() => this.controller.abort(/* @__PURE__ */ new Error("Agent run deadline expired")), Math.max(0, this.deadlineAtMs - Date.now()));
|
|
22
|
+
}
|
|
23
|
+
planModelAttempt(isFallback) {
|
|
24
|
+
if (this.signal.aborted) return {
|
|
25
|
+
ok: false,
|
|
26
|
+
reason: "Agent run aborted"
|
|
27
|
+
};
|
|
28
|
+
const remainingMs = this.deadlineAtMs - Date.now();
|
|
29
|
+
if (remainingMs <= 0) return {
|
|
30
|
+
ok: false,
|
|
31
|
+
reason: "Agent run deadline expired before the next model attempt"
|
|
32
|
+
};
|
|
33
|
+
if (isFallback && remainingMs < this.minimumFallbackMs) return {
|
|
34
|
+
ok: false,
|
|
35
|
+
reason: "Agent run deadline left too little time for a fallback model attempt"
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
ok: true,
|
|
39
|
+
remainingMs,
|
|
40
|
+
timeoutMs: Math.max(1, Math.min(this.timeoutMs, remainingMs))
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
dispose() {
|
|
44
|
+
clearTimeout(this.timeout);
|
|
45
|
+
this.parentSignal?.removeEventListener("abort", this.forwardParentAbort);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { AgentRunSupervisor };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AfterToolCallContext, BeforeToolCallContext, BeforeToolCallResult, ShouldStopAfterTurnContext } from '@earendil-works/pi-agent-core';
|
|
2
|
+
export interface AgentTurnPolicy {
|
|
3
|
+
reset(): void;
|
|
4
|
+
beforeToolCall(context: BeforeToolCallContext, signal?: AbortSignal): Promise<BeforeToolCallResult | undefined>;
|
|
5
|
+
afterToolCall(context: AfterToolCallContext): Promise<undefined>;
|
|
6
|
+
shouldStopAfterTurn(context: ShouldStopAfterTurnContext): boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface AgentTurnPolicyOptions {
|
|
9
|
+
maxTurns?: number;
|
|
10
|
+
maxToolFailures?: number;
|
|
11
|
+
resolveToolLimit?: (toolName: string, args: unknown) => {
|
|
12
|
+
id: string;
|
|
13
|
+
maxCalls: number;
|
|
14
|
+
} | undefined;
|
|
15
|
+
authorizeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise<BeforeToolCallResult | undefined>;
|
|
16
|
+
}
|
|
17
|
+
/** One user-visible run policy. A fresh instance is created for every embedded run. */
|
|
18
|
+
export declare function createAgentTurnPolicy(options: AgentTurnPolicyOptions): AgentTurnPolicy;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/agent/orchestration/agent-turn-policy.ts
|
|
2
|
+
function assistantMessageCount(messages) {
|
|
3
|
+
return messages.filter((message) => message.role === "assistant").length;
|
|
4
|
+
}
|
|
5
|
+
/** One user-visible run policy. A fresh instance is created for every embedded run. */
|
|
6
|
+
function createAgentTurnPolicy(options) {
|
|
7
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
8
|
+
let toolFailures = 0;
|
|
9
|
+
return {
|
|
10
|
+
reset() {
|
|
11
|
+
toolCalls.clear();
|
|
12
|
+
toolFailures = 0;
|
|
13
|
+
},
|
|
14
|
+
async beforeToolCall(context, signal) {
|
|
15
|
+
const limit = options.resolveToolLimit?.(context.toolCall.name, context.args);
|
|
16
|
+
if (limit) {
|
|
17
|
+
const count = (toolCalls.get(limit.id) ?? 0) + 1;
|
|
18
|
+
toolCalls.set(limit.id, count);
|
|
19
|
+
if (count > limit.maxCalls) return {
|
|
20
|
+
block: true,
|
|
21
|
+
terminate: true,
|
|
22
|
+
reason: `${limit.id} exceeded its per-turn call limit.`
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return options.authorizeToolCall?.(context, signal);
|
|
26
|
+
},
|
|
27
|
+
async afterToolCall(context) {
|
|
28
|
+
if (context.isError) toolFailures += 1;
|
|
29
|
+
},
|
|
30
|
+
shouldStopAfterTurn(context) {
|
|
31
|
+
return Boolean(options.maxTurns && assistantMessageCount(context.newMessages) >= options.maxTurns || options.maxToolFailures && toolFailures >= options.maxToolFailures);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { createAgentTurnPolicy };
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';
|
|
8
8
|
export declare function isTransientLlmErrorMessage(message: string): boolean;
|
|
9
|
+
export type LlmFailureKind = 'transient_network' | 'context_overflow' | 'aborted' | 'permanent';
|
|
10
|
+
export declare function classifyLlmFailure(message: string): LlmFailureKind;
|
|
9
11
|
export declare function getLastAssistantMessage(messages: AgentMessage[]): AgentMessage | undefined;
|
|
10
12
|
/** Raw provider/LLM error from the last failed assistant message, if any. */
|
|
11
13
|
export declare function getAssistantTurnErrorMessage(agent: Agent): string | undefined;
|
|
@@ -20,6 +22,9 @@ export declare function stripTrailingErrorAssistantMessages(messages: AgentMessa
|
|
|
20
22
|
export interface RetryTransientTurnOptions {
|
|
21
23
|
/** Extra turns after a failed assistant message (default 2). */
|
|
22
24
|
maxContinues?: number;
|
|
25
|
+
/** Initial deterministic backoff. Each later retry doubles it. */
|
|
26
|
+
baseDelayMs?: number;
|
|
27
|
+
signal?: AbortSignal;
|
|
23
28
|
sessionKey: string;
|
|
24
29
|
log: {
|
|
25
30
|
warn: (obj: Record<string, unknown>, msg: string) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isContextOverflowError } from "./context-overflow.js";
|
|
1
2
|
//#region src/agent/orchestration/llm-turn-retry.ts
|
|
2
3
|
const TRANSIENT_LLM_ERROR_SUBSTRINGS = [
|
|
3
4
|
"fetch failed",
|
|
@@ -16,6 +17,13 @@ function isTransientLlmErrorMessage(message) {
|
|
|
16
17
|
const lower = message.toLowerCase();
|
|
17
18
|
return TRANSIENT_LLM_ERROR_SUBSTRINGS.some((s) => lower.includes(s));
|
|
18
19
|
}
|
|
20
|
+
function classifyLlmFailure(message) {
|
|
21
|
+
const normalized = message.trim().toLowerCase();
|
|
22
|
+
if (normalized === "aborted" || normalized.includes("aborterror")) return "aborted";
|
|
23
|
+
if (isContextOverflowError(message)) return "context_overflow";
|
|
24
|
+
if (isTransientLlmErrorMessage(message)) return "transient_network";
|
|
25
|
+
return "permanent";
|
|
26
|
+
}
|
|
19
27
|
function getLastAssistantMessage(messages) {
|
|
20
28
|
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "assistant") return messages[i];
|
|
21
29
|
}
|
|
@@ -56,32 +64,54 @@ function stripTrailingErrorAssistantMessages(messages) {
|
|
|
56
64
|
}
|
|
57
65
|
return out;
|
|
58
66
|
}
|
|
67
|
+
async function waitForRetryDelay(delayMs, signal) {
|
|
68
|
+
signal?.throwIfAborted();
|
|
69
|
+
if (delayMs <= 0) return;
|
|
70
|
+
await new Promise((resolve, reject) => {
|
|
71
|
+
const onAbort = () => {
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
reject(signal?.reason ?? new DOMException("Aborted", "AbortError"));
|
|
74
|
+
};
|
|
75
|
+
const timer = setTimeout(() => {
|
|
76
|
+
signal?.removeEventListener("abort", onAbort);
|
|
77
|
+
resolve();
|
|
78
|
+
}, delayMs);
|
|
79
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
59
82
|
/**
|
|
60
83
|
* After waitForIdle(), call this to optionally re-run the last user turn when the
|
|
61
84
|
* assistant message only contains a transient provider/network error.
|
|
62
85
|
*/
|
|
63
86
|
async function maybeRetryTurnAfterTransientLlmFailure(agent, options) {
|
|
64
87
|
const maxContinues = options.maxContinues ?? 2;
|
|
88
|
+
const baseDelayMs = Math.max(0, options.baseDelayMs ?? 300);
|
|
65
89
|
let continues = 0;
|
|
66
90
|
while (continues < maxContinues) {
|
|
67
91
|
const last = getLastAssistantMessage(agent.state.messages);
|
|
68
92
|
if (!last) return;
|
|
69
93
|
if (last.stopReason !== "error") return;
|
|
70
94
|
const errMsg = String(last.errorMessage || "");
|
|
71
|
-
|
|
95
|
+
const failureKind = classifyLlmFailure(errMsg);
|
|
96
|
+
if (failureKind !== "transient_network") {
|
|
72
97
|
options.log.warn({
|
|
73
98
|
sessionKey: options.sessionKey,
|
|
74
|
-
errorMessage: errMsg
|
|
99
|
+
errorMessage: errMsg,
|
|
100
|
+
failureKind
|
|
75
101
|
}, "Assistant turn ended with error (not retrying as transient)");
|
|
76
102
|
return;
|
|
77
103
|
}
|
|
78
104
|
continues += 1;
|
|
105
|
+
const retryDelayMs = baseDelayMs * 2 ** (continues - 1);
|
|
79
106
|
options.log.warn({
|
|
80
107
|
sessionKey: options.sessionKey,
|
|
81
108
|
errorMessage: errMsg,
|
|
109
|
+
failureKind,
|
|
82
110
|
continueAttempt: continues,
|
|
83
|
-
maxContinues
|
|
111
|
+
maxContinues,
|
|
112
|
+
retryDelayMs
|
|
84
113
|
}, "LLM request failed with a transient network error; retrying the same turn. If this persists, check outbound HTTPS to the provider API and HTTP(S)_PROXY.");
|
|
114
|
+
await waitForRetryDelay(retryDelayMs, options.signal);
|
|
85
115
|
const trimmed = stripTrailingErrorAssistantMessages(agent.state.messages);
|
|
86
116
|
agent.state.messages = trimmed;
|
|
87
117
|
await agent.continue();
|
|
@@ -89,4 +119,4 @@ async function maybeRetryTurnAfterTransientLlmFailure(agent, options) {
|
|
|
89
119
|
}
|
|
90
120
|
}
|
|
91
121
|
//#endregion
|
|
92
|
-
export { getAssistantTurnErrorMessage, getLastAssistantMessage, isAssistantTurnAborted, isAssistantTurnFailed, isTransientLlmErrorMessage, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages };
|
|
122
|
+
export { classifyLlmFailure, getAssistantTurnErrorMessage, getLastAssistantMessage, isAssistantTurnAborted, isAssistantTurnFailed, isTransientLlmErrorMessage, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages };
|
|
@@ -10,6 +10,15 @@ export declare const MIN_AGENT_TURN_TIMEOUT_MS = 60000;
|
|
|
10
10
|
export declare const MAX_AGENT_TURN_TIMEOUT_MS: number;
|
|
11
11
|
/** Default per-turn timeout (30 minutes). */
|
|
12
12
|
export declare const DEFAULT_AGENT_TURN_TIMEOUT_MS: number;
|
|
13
|
+
export declare const DEFAULT_AGENT_ABORT_GRACE_MS = 5000;
|
|
14
|
+
export declare class AgentTurnUnsettledError extends Error {
|
|
15
|
+
readonly timeoutMs: number;
|
|
16
|
+
readonly abortGraceMs: number;
|
|
17
|
+
constructor(timeoutMs: number, abortGraceMs: number);
|
|
18
|
+
}
|
|
19
|
+
export declare function isAgentTurnUnsettledError(err: unknown): err is AgentTurnUnsettledError;
|
|
13
20
|
export declare function resolveAgentTurnTimeoutMs(config?: Config, sessionKey?: string): number;
|
|
14
21
|
export declare function isAgentTurnTimeoutError(err: unknown): boolean;
|
|
15
|
-
export declare function runAgentTurnWithTimeout(agent: Agent, runTurn: () => Promise<void>, timeoutMs: number
|
|
22
|
+
export declare function runAgentTurnWithTimeout(agent: Agent, runTurn: () => Promise<void>, timeoutMs: number, options?: {
|
|
23
|
+
abortGraceMs?: number;
|
|
24
|
+
}): Promise<void>;
|
|
@@ -6,6 +6,18 @@ const MIN_AGENT_TURN_TIMEOUT_MS = 6e4;
|
|
|
6
6
|
const MAX_AGENT_TURN_TIMEOUT_MS = 14400 * 1e3;
|
|
7
7
|
/** Default per-turn timeout (30 minutes). */
|
|
8
8
|
const DEFAULT_AGENT_TURN_TIMEOUT_MS = 1800 * 1e3;
|
|
9
|
+
const DEFAULT_AGENT_ABORT_GRACE_MS = 5e3;
|
|
10
|
+
var AgentTurnUnsettledError = class extends Error {
|
|
11
|
+
constructor(timeoutMs, abortGraceMs) {
|
|
12
|
+
super(`Agent turn timed out after ${timeoutMs / 1e3}s and did not settle within ${abortGraceMs / 1e3}s`);
|
|
13
|
+
this.timeoutMs = timeoutMs;
|
|
14
|
+
this.abortGraceMs = abortGraceMs;
|
|
15
|
+
this.name = "AgentTurnUnsettledError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function isAgentTurnUnsettledError(err) {
|
|
19
|
+
return err instanceof AgentTurnUnsettledError;
|
|
20
|
+
}
|
|
9
21
|
function resolveAgentTurnTimeoutMs(config, sessionKey) {
|
|
10
22
|
if (!config) return DEFAULT_AGENT_TURN_TIMEOUT_MS;
|
|
11
23
|
const configured = resolveEffectiveAgentManifestForSession(config, sessionKey).runtime?.timeoutMs;
|
|
@@ -15,22 +27,31 @@ function resolveAgentTurnTimeoutMs(config, sessionKey) {
|
|
|
15
27
|
function isAgentTurnTimeoutError(err) {
|
|
16
28
|
return err instanceof Error && err.message.startsWith("Agent turn timed out after");
|
|
17
29
|
}
|
|
18
|
-
async function runAgentTurnWithTimeout(agent, runTurn, timeoutMs) {
|
|
30
|
+
async function runAgentTurnWithTimeout(agent, runTurn, timeoutMs, options = {}) {
|
|
19
31
|
let timeoutId;
|
|
20
32
|
const timeoutPromise = new Promise((_, reject) => {
|
|
21
33
|
timeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error(`Agent turn timed out after ${timeoutMs / 1e3}s`)), timeoutMs);
|
|
22
34
|
});
|
|
35
|
+
const runTurnPromise = Promise.resolve().then(runTurn);
|
|
23
36
|
try {
|
|
24
|
-
await Promise.race([
|
|
37
|
+
await Promise.race([runTurnPromise.finally(() => {
|
|
25
38
|
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
26
39
|
}), timeoutPromise]);
|
|
27
40
|
} catch (err) {
|
|
28
41
|
if (isAgentTurnTimeoutError(err)) {
|
|
29
42
|
agent.abort();
|
|
30
|
-
|
|
43
|
+
const abortGraceMs = options.abortGraceMs ?? 5e3;
|
|
44
|
+
let graceTimer;
|
|
45
|
+
try {
|
|
46
|
+
await Promise.race([Promise.allSettled([runTurnPromise, agent.waitForIdle()]), new Promise((_, reject) => {
|
|
47
|
+
graceTimer = setTimeout(() => reject(new AgentTurnUnsettledError(timeoutMs, abortGraceMs)), abortGraceMs);
|
|
48
|
+
})]);
|
|
49
|
+
} finally {
|
|
50
|
+
if (graceTimer !== void 0) clearTimeout(graceTimer);
|
|
51
|
+
}
|
|
31
52
|
}
|
|
32
53
|
throw err;
|
|
33
54
|
}
|
|
34
55
|
}
|
|
35
56
|
//#endregion
|
|
36
|
-
export { DEFAULT_AGENT_TURN_TIMEOUT_MS, MAX_AGENT_TURN_TIMEOUT_MS, MIN_AGENT_TURN_TIMEOUT_MS, isAgentTurnTimeoutError, resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout };
|
|
57
|
+
export { AgentTurnUnsettledError, DEFAULT_AGENT_ABORT_GRACE_MS, DEFAULT_AGENT_TURN_TIMEOUT_MS, MAX_AGENT_TURN_TIMEOUT_MS, MIN_AGENT_TURN_TIMEOUT_MS, isAgentTurnTimeoutError, isAgentTurnUnsettledError, resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout };
|
|
@@ -3,15 +3,28 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Replaces the ad-hoc `eventQueue + resolveWaiting` single-slot pattern that
|
|
5
5
|
* the streaming direct turn used to manage run events. The previous pattern was
|
|
6
|
-
* lossy if two pushes landed before the single waiter resumed; this queue
|
|
7
|
-
*
|
|
6
|
+
* lossy if two pushes landed before the single waiter resumed; this queue buffers
|
|
7
|
+
* until consumed, supports an explicit bound, and drains cleanly on close.
|
|
8
8
|
*/
|
|
9
|
+
export interface AsyncQueueOptions<T> {
|
|
10
|
+
/** Maximum buffer size. Lossy events are evicted; critical-only overflow fails fast. */
|
|
11
|
+
maxBuffered?: number;
|
|
12
|
+
isDroppable?: (value: T) => boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class AsyncQueueOverflowError extends Error {
|
|
15
|
+
readonly maxBuffered: number;
|
|
16
|
+
constructor(maxBuffered: number);
|
|
17
|
+
}
|
|
9
18
|
export declare class AsyncQueue<T> implements AsyncIterable<T> {
|
|
19
|
+
private readonly options;
|
|
10
20
|
private readonly buffer;
|
|
11
21
|
private readonly waiters;
|
|
12
22
|
private closed;
|
|
23
|
+
private dropped;
|
|
24
|
+
constructor(options?: AsyncQueueOptions<T>);
|
|
13
25
|
/** Push a value to the queue. No-op when the queue is closed. */
|
|
14
|
-
push(value: T):
|
|
26
|
+
push(value: T): boolean;
|
|
27
|
+
get droppedCount(): number;
|
|
15
28
|
/** Close the queue. Pending iterators drain any buffered values and then complete. */
|
|
16
29
|
close(): void;
|
|
17
30
|
/** True if the queue is closed and the internal buffer is drained. */
|
|
@@ -1,25 +1,43 @@
|
|
|
1
1
|
//#region src/agent/service/async-queue.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
2
|
+
var AsyncQueueOverflowError = class extends Error {
|
|
3
|
+
constructor(maxBuffered) {
|
|
4
|
+
super(`Async queue exceeded its ${maxBuffered}-event buffer`);
|
|
5
|
+
this.maxBuffered = maxBuffered;
|
|
6
|
+
this.name = "AsyncQueueOverflowError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
10
9
|
var AsyncQueue = class {
|
|
11
10
|
buffer = [];
|
|
12
11
|
waiters = [];
|
|
13
12
|
closed = false;
|
|
13
|
+
dropped = 0;
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
}
|
|
14
17
|
/** Push a value to the queue. No-op when the queue is closed. */
|
|
15
18
|
push(value) {
|
|
16
|
-
if (this.closed) return;
|
|
19
|
+
if (this.closed) return false;
|
|
17
20
|
const waiter = this.waiters.shift();
|
|
18
21
|
if (waiter) {
|
|
19
22
|
waiter(value);
|
|
20
|
-
return;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const maxBuffered = this.options.maxBuffered;
|
|
26
|
+
if (maxBuffered && this.buffer.length >= maxBuffered) {
|
|
27
|
+
const droppableIndex = this.options.isDroppable ? this.buffer.findIndex(this.options.isDroppable) : -1;
|
|
28
|
+
if (droppableIndex >= 0) {
|
|
29
|
+
this.buffer.splice(droppableIndex, 1);
|
|
30
|
+
this.dropped += 1;
|
|
31
|
+
} else if (this.options.isDroppable?.(value)) {
|
|
32
|
+
this.dropped += 1;
|
|
33
|
+
return false;
|
|
34
|
+
} else throw new AsyncQueueOverflowError(maxBuffered);
|
|
21
35
|
}
|
|
22
36
|
this.buffer.push(value);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
get droppedCount() {
|
|
40
|
+
return this.dropped;
|
|
23
41
|
}
|
|
24
42
|
/** Close the queue. Pending iterators drain any buffered values and then complete. */
|
|
25
43
|
close() {
|
|
@@ -48,4 +66,4 @@ var AsyncQueue = class {
|
|
|
48
66
|
};
|
|
49
67
|
const CLOSE_SENTINEL = Symbol("AsyncQueue.close");
|
|
50
68
|
//#endregion
|
|
51
|
-
export { AsyncQueue };
|
|
69
|
+
export { AsyncQueue, AsyncQueueOverflowError };
|