@xopcai/xopc 0.0.6 → 0.0.8
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/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/weixin/src/api/api.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/gateway/static/root/assets/{agents-B6s2BvpH.js → agents-BSNzJWbQ.js} +2 -2
- package/dist/gateway/static/root/assets/{agents-B6s2BvpH.js.map → agents-BSNzJWbQ.js.map} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-BtsZ5ZPx.js → apps-page-BKk9SB4D.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-BtsZ5ZPx.js.map → apps-page-BKk9SB4D.js.map} +1 -1
- package/dist/gateway/static/root/assets/attachment-load-DXcJLSWT.js +1 -0
- package/dist/gateway/static/root/assets/{channels-settings-BUfWBEVU.js → channels-settings-_J6cQN6G.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-BUfWBEVU.js.map → channels-settings-_J6cQN6G.js.map} +1 -1
- package/dist/gateway/static/root/assets/{chat-agents-api-BR30M2YQ.js → chat-agents-api-DPb_0O8M.js} +2 -2
- package/dist/gateway/static/root/assets/{chat-agents-api-BR30M2YQ.js.map → chat-agents-api-DPb_0O8M.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-CMTx0Mjz.js → cron-page-BUJOuuKX.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-CMTx0Mjz.js.map → cron-page-BUJOuuKX.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-BJma9IcD.js → cron-utils-Cn0YVg8x.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-BJma9IcD.js.map → cron-utils-Cn0YVg8x.js.map} +1 -1
- package/dist/gateway/static/root/assets/electron-env-D9bm1FIu.js +2 -0
- package/dist/gateway/static/root/assets/electron-env-D9bm1FIu.js.map +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BCVoNSo6.js → extension-debug-page-DTz4O5Ua.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-BCVoNSo6.js.map → extension-debug-page-DTz4O5Ua.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-iframe-host-PWB-Pw2d.js → extension-iframe-host-Cs1Kde9o.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-iframe-host-PWB-Pw2d.js.map → extension-iframe-host-Cs1Kde9o.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-D2tTklsD.js → extension-page-G52iX0Bo.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-D2tTklsD.js.map → extension-page-G52iX0Bo.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-provider-BpHodVRj.js → extension-provider-CO2jxBA9.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-provider-BpHodVRj.js.map → extension-provider-CO2jxBA9.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BEu6Xw1Z.js → extension-settings-page-D9Ul8uSt.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-BEu6Xw1Z.js.map → extension-settings-page-D9Ul8uSt.js.map} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-C7ZFPhNj.js → gateway-config-swr-Bc8SVD15.js} +2 -2
- package/dist/gateway/static/root/assets/{gateway-config-swr-C7ZFPhNj.js.map → gateway-config-swr-Bc8SVD15.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-BXUJbteW.js +16 -0
- package/dist/gateway/static/root/assets/index-BXUJbteW.js.map +1 -0
- package/dist/gateway/static/root/assets/index-CQLMxWSA.css +2 -0
- package/dist/gateway/static/root/assets/{logs-page-BpsxYdcL.js → logs-page-5V25JkQY.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-BpsxYdcL.js.map → logs-page-5V25JkQY.js.map} +1 -1
- package/dist/gateway/static/root/assets/{model-selector-BiiDq8Pk.js → model-selector-he3aQfme.js} +2 -2
- package/dist/gateway/static/root/assets/{model-selector-BiiDq8Pk.js.map → model-selector-he3aQfme.js.map} +1 -1
- package/dist/gateway/static/root/assets/navigation-DB9S-C6S.js +2 -0
- package/dist/gateway/static/root/assets/navigation-DB9S-C6S.js.map +1 -0
- package/dist/gateway/static/root/assets/page-header-store-DJHD9Ean.js +2 -0
- package/dist/gateway/static/root/assets/{page-header-store-HcRZK5CZ.js.map → page-header-store-DJHD9Ean.js.map} +1 -1
- package/dist/gateway/static/root/assets/{session-api-DxNaAkmX.js → session-api-n-4O5d9U.js} +2 -2
- package/dist/gateway/static/root/assets/{session-api-DxNaAkmX.js.map → session-api-n-4O5d9U.js.map} +1 -1
- package/dist/gateway/static/root/assets/{session-working-directory-control-CDH-Wk4E.js → session-working-directory-control-B6dHLvbr.js} +3 -3
- package/dist/gateway/static/root/assets/{session-working-directory-control-CDH-Wk4E.js.map → session-working-directory-control-B6dHLvbr.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-5PK75r1n.js → sessions-page-rBUfTdm3.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-5PK75r1n.js.map → sessions-page-rBUfTdm3.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-B3QrJm-E.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-B3QrJm-E.js.map +1 -0
- package/dist/gateway/static/root/assets/{skill-api-CxbNlOD_.js → skill-api-vxtE8kI6.js} +2 -2
- package/dist/gateway/static/root/assets/{skill-api-CxbNlOD_.js.map → skill-api-vxtE8kI6.js.map} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-Dd8ZzYJb.js → skills-page-D36_O2Ub.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-Dd8ZzYJb.js.map → skills-page-D36_O2Ub.js.map} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-CPTH77BE.js → theme-store-CmiSsYBd.js} +2 -2
- package/dist/gateway/static/root/assets/{theme-store-CPTH77BE.js.map → theme-store-CmiSsYBd.js.map} +1 -1
- package/dist/gateway/static/root/assets/url-CtSqjF9J.js +2 -0
- package/dist/gateway/static/root/assets/url-CtSqjF9J.js.map +1 -0
- package/dist/gateway/static/root/assets/{useTranslation-BEUWOMuh.js → useTranslation-DYORQ7x6.js} +2 -2
- package/dist/gateway/static/root/assets/{useTranslation-BEUWOMuh.js.map → useTranslation-DYORQ7x6.js.map} +1 -1
- package/dist/gateway/static/root/index.html +16 -16
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +4 -4
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/image/index.d.ts +0 -1
- package/dist/src/agent/image/index.js +1 -2
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +1 -1
- package/dist/src/agent/service.js +3 -3
- package/dist/src/agent/skills/hub-hash.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/browser/tools.js +2 -2
- package/dist/src/agent/tools/browser/tools.js.map +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/image-tool.js +2 -2
- package/dist/src/agent/tools/image-tool.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -1
- package/dist/src/agent/tools/index.js +2 -2
- package/dist/src/agent/tools/read.d.ts +0 -2
- package/dist/src/agent/tools/read.js +1 -3
- package/dist/src/agent/tools/read.js.map +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/channels/plugin-types.d.ts +14 -0
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/channel-config.js +113 -0
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/channel-plugins.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/channel-plugins.js +47 -0
- package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/config-health.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/config-health.js +82 -0
- package/dist/src/cli/commands/doctor/checks/config-health.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/cron-health.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/cron-health.js +116 -0
- package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/gateway-health.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/gateway-health.js +64 -0
- package/dist/src/cli/commands/doctor/checks/gateway-health.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/gateway-service.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/gateway-service.js +64 -0
- package/dist/src/cli/commands/doctor/checks/gateway-service.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/node-version.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/node-version.js +33 -0
- package/dist/src/cli/commands/doctor/checks/node-version.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/provider-auth.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +91 -0
- package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/security-audit.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/security-audit.js +85 -0
- package/dist/src/cli/commands/doctor/checks/security-audit.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/session-integrity.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +118 -0
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/state-integrity.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +99 -0
- package/dist/src/cli/commands/doctor/checks/state-integrity.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/version-check.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/version-check.js +71 -0
- package/dist/src/cli/commands/doctor/checks/version-check.js.map +1 -0
- package/dist/src/cli/commands/doctor/checks/workspace-status.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +73 -0
- package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -0
- package/dist/src/cli/commands/doctor/flow.d.ts +9 -0
- package/dist/src/cli/commands/doctor/flow.js +51 -0
- package/dist/src/cli/commands/doctor/flow.js.map +1 -0
- package/dist/src/cli/commands/doctor/format.d.ts +6 -0
- package/dist/src/cli/commands/doctor/format.js +61 -0
- package/dist/src/cli/commands/doctor/format.js.map +1 -0
- package/dist/src/cli/commands/doctor/index.js +44 -0
- package/dist/src/cli/commands/doctor/index.js.map +1 -0
- package/dist/src/cli/commands/doctor/types.d.ts +20 -0
- package/dist/src/cli/commands/doctor/types.js +1 -0
- package/dist/src/cli/commands/init.js +2 -2
- package/dist/src/cli/index.d.ts +1 -1
- package/dist/src/cli/index.js +1 -1
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/utils/init-workspace.js +1 -1
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.d.ts +15 -15
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/profile.js +1 -1
- package/dist/src/config/schema.d.ts +0 -105
- package/dist/src/config/schema.js +3 -40
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/launchd.js.map +1 -1
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/daemon/systemd.js.map +1 -1
- package/dist/src/extensions/loader.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/lib/static-ui.js +1 -1
- package/dist/src/gateway/hono/routes/doctor.d.ts +3 -0
- package/dist/src/gateway/hono/routes/doctor.js +35 -0
- package/dist/src/gateway/hono/routes/doctor.js.map +1 -0
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +2 -2
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/ports.js +98 -3
- package/dist/src/gateway/ports.js.map +1 -1
- package/dist/src/gateway/service.d.ts +0 -4
- package/dist/src/gateway/service.js +4 -23
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/routing/bindings.js +1 -1
- package/dist/src/routing/index.d.ts +1 -1
- package/dist/src/routing/index.js +2 -2
- package/dist/src/routing/index.js.map +1 -1
- package/dist/src/routing/resolve-route.js +1 -1
- package/dist/src/routing/session-key.d.ts +0 -5
- package/dist/src/routing/session-key.js +1 -27
- package/dist/src/routing/session-key.js.map +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +2 -6
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/types.d.ts +0 -10
- package/dist/src/session/types.js.map +1 -1
- package/package.json +1 -2
- package/dist/gateway/static/root/assets/attachment-load-6pRlDPZ8.js +0 -1
- package/dist/gateway/static/root/assets/index-DBZ5eXW5.js +0 -16
- package/dist/gateway/static/root/assets/index-DBZ5eXW5.js.map +0 -1
- package/dist/gateway/static/root/assets/index-KsVMH-Jo.css +0 -2
- package/dist/gateway/static/root/assets/navigation-BpLKd2Ca.js +0 -2
- package/dist/gateway/static/root/assets/navigation-BpLKd2Ca.js.map +0 -1
- package/dist/gateway/static/root/assets/page-header-store-HcRZK5CZ.js +0 -2
- package/dist/gateway/static/root/assets/preference-select-fields-B4AJBqUY.js +0 -2
- package/dist/gateway/static/root/assets/preference-select-fields-B4AJBqUY.js.map +0 -1
- package/dist/gateway/static/root/assets/settings-page-BvSj0JqX.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-BvSj0JqX.js.map +0 -1
- package/dist/gateway/static/root/assets/url-QmwQTJ-j.js +0 -2
- package/dist/gateway/static/root/assets/url-QmwQTJ-j.js.map +0 -1
- package/dist/src/acp/commands.d.ts +0 -11
- package/dist/src/acp/commands.js +0 -17
- package/dist/src/acp/commands.js.map +0 -1
- package/dist/src/acp/control-plane/identity-reconcile.d.ts +0 -36
- package/dist/src/acp/control-plane/identity-reconcile.js +0 -124
- package/dist/src/acp/control-plane/identity-reconcile.js.map +0 -1
- package/dist/src/acp/control-plane/index.d.ts +0 -10
- package/dist/src/acp/control-plane/index.js +0 -6
- package/dist/src/acp/control-plane/manager.d.ts +0 -86
- package/dist/src/acp/control-plane/manager.js +0 -502
- package/dist/src/acp/control-plane/manager.js.map +0 -1
- package/dist/src/acp/control-plane/manager.types.d.ts +0 -125
- package/dist/src/acp/control-plane/manager.types.js +0 -14
- package/dist/src/acp/control-plane/manager.types.js.map +0 -1
- package/dist/src/acp/control-plane/manager.utils.d.ts +0 -29
- package/dist/src/acp/control-plane/manager.utils.js +0 -46
- package/dist/src/acp/control-plane/manager.utils.js.map +0 -1
- package/dist/src/acp/control-plane/runtime-cache-manager.d.ts +0 -49
- package/dist/src/acp/control-plane/runtime-cache-manager.js +0 -155
- package/dist/src/acp/control-plane/runtime-cache-manager.js.map +0 -1
- package/dist/src/acp/control-plane/runtime-cache.d.ts +0 -45
- package/dist/src/acp/control-plane/runtime-cache.js +0 -58
- package/dist/src/acp/control-plane/runtime-cache.js.map +0 -1
- package/dist/src/acp/control-plane/runtime-options.d.ts +0 -30
- package/dist/src/acp/control-plane/runtime-options.js +0 -92
- package/dist/src/acp/control-plane/runtime-options.js.map +0 -1
- package/dist/src/acp/control-plane/session-actor-queue.d.ts +0 -22
- package/dist/src/acp/control-plane/session-actor-queue.js +0 -70
- package/dist/src/acp/control-plane/session-actor-queue.js.map +0 -1
- package/dist/src/acp/control-plane/session-lifecycle-manager.d.ts +0 -59
- package/dist/src/acp/control-plane/session-lifecycle-manager.js +0 -209
- package/dist/src/acp/control-plane/session-lifecycle-manager.js.map +0 -1
- package/dist/src/acp/control-plane/session-store.d.ts +0 -39
- package/dist/src/acp/control-plane/session-store.js +0 -149
- package/dist/src/acp/control-plane/session-store.js.map +0 -1
- package/dist/src/acp/control-plane/turn-manager.d.ts +0 -40
- package/dist/src/acp/control-plane/turn-manager.js +0 -134
- package/dist/src/acp/control-plane/turn-manager.js.map +0 -1
- package/dist/src/acp/event-mapper.d.ts +0 -48
- package/dist/src/acp/event-mapper.js +0 -94
- package/dist/src/acp/event-mapper.js.map +0 -1
- package/dist/src/acp/index.d.ts +0 -10
- package/dist/src/acp/index.js +0 -5
- package/dist/src/acp/meta.d.ts +0 -15
- package/dist/src/acp/meta.js +0 -36
- package/dist/src/acp/meta.js.map +0 -1
- package/dist/src/acp/routing-integration.d.ts +0 -37
- package/dist/src/acp/routing-integration.js +0 -58
- package/dist/src/acp/routing-integration.js.map +0 -1
- package/dist/src/acp/runtime/backends/index.d.ts +0 -4
- package/dist/src/acp/runtime/backends/index.js +0 -2
- package/dist/src/acp/runtime/backends/local.d.ts +0 -136
- package/dist/src/acp/runtime/backends/local.js +0 -603
- package/dist/src/acp/runtime/backends/local.js.map +0 -1
- package/dist/src/acp/runtime/error-text.d.ts +0 -16
- package/dist/src/acp/runtime/error-text.js +0 -40
- package/dist/src/acp/runtime/error-text.js.map +0 -1
- package/dist/src/acp/runtime/errors.d.ts +0 -31
- package/dist/src/acp/runtime/errors.js +0 -47
- package/dist/src/acp/runtime/errors.js.map +0 -1
- package/dist/src/acp/runtime/index.d.ts +0 -7
- package/dist/src/acp/runtime/index.js +0 -4
- package/dist/src/acp/runtime/registry.d.ts +0 -35
- package/dist/src/acp/runtime/registry.js +0 -85
- package/dist/src/acp/runtime/registry.js.map +0 -1
- package/dist/src/acp/runtime/session-identity.d.ts +0 -35
- package/dist/src/acp/runtime/session-identity.js +0 -134
- package/dist/src/acp/runtime/session-identity.js.map +0 -1
- package/dist/src/acp/runtime/types.d.ts +0 -214
- package/dist/src/acp/secret-file.d.ts +0 -7
- package/dist/src/acp/secret-file.js +0 -19
- package/dist/src/acp/secret-file.js.map +0 -1
- package/dist/src/acp/server.d.ts +0 -48
- package/dist/src/acp/server.js +0 -300
- package/dist/src/acp/server.js.map +0 -1
- package/dist/src/acp/session.d.ts +0 -29
- package/dist/src/acp/session.js +0 -30
- package/dist/src/acp/session.js.map +0 -1
- package/dist/src/acp/types.d.ts +0 -39
- package/dist/src/acp/types.js +0 -13
- package/dist/src/acp/types.js.map +0 -1
- package/dist/src/agent/image/describe-images.d.ts +0 -18
- package/dist/src/agent/image/describe-images.js +0 -19
- package/dist/src/agent/image/describe-images.js.map +0 -1
- package/dist/src/cli/commands/acp.d.ts +0 -4
- package/dist/src/cli/commands/acp.js +0 -200
- package/dist/src/cli/commands/acp.js.map +0 -1
- /package/dist/src/{acp/runtime/types.js → cli/commands/doctor/index.d.ts} +0 -0
|
@@ -1,603 +0,0 @@
|
|
|
1
|
-
import { AcpRuntimeError, normalizeAcpErrorCode } from "../errors.js";
|
|
2
|
-
import { createLogger } from "../../../utils/logger/index.js";
|
|
3
|
-
import { init_logger } from "../../../utils/logger.js";
|
|
4
|
-
import { init_agent_scope, normalizeAgentId, resolveAgentBootstrapDir, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
|
|
5
|
-
import { init_paths, resolveBundledSkillsDir } from "../../../config/paths.js";
|
|
6
|
-
import { init_loader, loadConfig } from "../../../config/loader.js";
|
|
7
|
-
import "../../../config/agent-profile.js";
|
|
8
|
-
import { getApiKeySync, getDefaultModelSync, init_providers, resolveModel } from "../../../providers/index.js";
|
|
9
|
-
import { extractTextContent, loadBootstrapFiles } from "../../../agent/context/workspace.js";
|
|
10
|
-
import { isValidSkillEnvVarName } from "../../../agent/skills/required-env-vars.js";
|
|
11
|
-
import { SkillManager } from "../../../agent/skills/skill-manager.js";
|
|
12
|
-
import "../../../agent/skills/index.js";
|
|
13
|
-
import { SystemPromptBuilder } from "../../../agent/prompt/service-prompt-builder.js";
|
|
14
|
-
import { AgentToolsFactory } from "../../../agent/tools/factory.js";
|
|
15
|
-
import { cleanTrailingErrors, sanitizeMessages } from "../../../agent/memory/message-sanitizer.js";
|
|
16
|
-
import { SessionStore } from "../../../session/store.js";
|
|
17
|
-
import "../../../session/index.js";
|
|
18
|
-
import { tryApplySessionTranscriptHygiene, tryApplySessionTranscriptHygieneForPersistence } from "../../../agent/transcript/transcript-hygiene.js";
|
|
19
|
-
import { randomUUID } from "node:crypto";
|
|
20
|
-
import { Agent } from "@mariozechner/pi-agent-core";
|
|
21
|
-
//#region src/acp/runtime/backends/local.ts
|
|
22
|
-
/**
|
|
23
|
-
* Local ACP Runtime Backend
|
|
24
|
-
*
|
|
25
|
-
* A simple ACP runtime that runs directly in xopc's process,
|
|
26
|
-
* using the existing agent system for turn execution.
|
|
27
|
-
*/
|
|
28
|
-
init_loader();
|
|
29
|
-
init_providers();
|
|
30
|
-
init_paths();
|
|
31
|
-
init_agent_scope();
|
|
32
|
-
init_logger();
|
|
33
|
-
const log = createLogger("LocalAcpRuntime");
|
|
34
|
-
/**
|
|
35
|
-
* Local ACP Runtime
|
|
36
|
-
*
|
|
37
|
-
* Implements AcpRuntime by directly using xopc's AgentCore,
|
|
38
|
-
* with its own session management.
|
|
39
|
-
*/
|
|
40
|
-
var LocalAcpRuntime = class {
|
|
41
|
-
sessions = /* @__PURE__ */ new Map();
|
|
42
|
-
agent;
|
|
43
|
-
/** Resolved default model for transcript hygiene. */
|
|
44
|
-
agentModel;
|
|
45
|
-
sessionStore;
|
|
46
|
-
tools = [];
|
|
47
|
-
workspace;
|
|
48
|
-
config;
|
|
49
|
-
skillManager;
|
|
50
|
-
registeredToolNames = [];
|
|
51
|
-
/** Set during runTurn so skill_view / shell can scope passthrough to the active ACP session. */
|
|
52
|
-
toolContextSessionKey = null;
|
|
53
|
-
constructor(bus, runtimeConfig) {
|
|
54
|
-
this.bus = bus;
|
|
55
|
-
this.runtimeConfig = runtimeConfig;
|
|
56
|
-
this.workspace = runtimeConfig?.workspace || process.cwd();
|
|
57
|
-
this.config = runtimeConfig?.config;
|
|
58
|
-
this.skillManager = new SkillManager(this.workspace, resolveBundledSkillsDir());
|
|
59
|
-
this.sessionStore = new SessionStore({ config: this.config ?? loadConfig() }, {
|
|
60
|
-
maxMessages: 100,
|
|
61
|
-
keepRecentMessages: 20,
|
|
62
|
-
preserveSystemMessages: true
|
|
63
|
-
}, {
|
|
64
|
-
enabled: true,
|
|
65
|
-
mode: "abstractive",
|
|
66
|
-
reserveTokens: 8e3,
|
|
67
|
-
triggerThreshold: .8,
|
|
68
|
-
minMessagesBeforeCompact: 10,
|
|
69
|
-
keepRecentMessages: 10,
|
|
70
|
-
evictionWindow: .2,
|
|
71
|
-
retentionWindow: 6
|
|
72
|
-
});
|
|
73
|
-
this.initializeTools();
|
|
74
|
-
const { agent, model } = this.createAgent();
|
|
75
|
-
this.agent = agent;
|
|
76
|
-
this.agentModel = model;
|
|
77
|
-
this.agent.subscribe((event) => this.handleAgentEvent(event));
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Initialize tools using AgentToolsFactory pattern
|
|
81
|
-
*/
|
|
82
|
-
refreshAgentAfterSkillDiskChange() {
|
|
83
|
-
this.skillManager.reload();
|
|
84
|
-
const appCfg = this.config ?? loadConfig();
|
|
85
|
-
const bootstrapFiles = loadBootstrapFiles(resolveAgentBootstrapDir(appCfg, normalizeAgentId(this.runtimeConfig?.agent ?? resolveDefaultAgentId(appCfg))));
|
|
86
|
-
const agentConfig = this.config || {
|
|
87
|
-
gateway: {},
|
|
88
|
-
agents: {},
|
|
89
|
-
channels: {},
|
|
90
|
-
tools: {}
|
|
91
|
-
};
|
|
92
|
-
const sp = new SystemPromptBuilder({
|
|
93
|
-
workspace: this.workspace,
|
|
94
|
-
config: agentConfig,
|
|
95
|
-
skillManager: this.skillManager
|
|
96
|
-
}).build(bootstrapFiles, { registeredToolNames: this.registeredToolNames });
|
|
97
|
-
this.agent.state.systemPrompt = sp;
|
|
98
|
-
}
|
|
99
|
-
initializeTools() {
|
|
100
|
-
this.tools = new AgentToolsFactory({
|
|
101
|
-
workspace: this.workspace,
|
|
102
|
-
getCurrentContext: () => {
|
|
103
|
-
const k = this.toolContextSessionKey;
|
|
104
|
-
if (!k) return null;
|
|
105
|
-
return {
|
|
106
|
-
sessionKey: k,
|
|
107
|
-
channel: "acp",
|
|
108
|
-
chatId: k,
|
|
109
|
-
senderId: "acp",
|
|
110
|
-
isGroup: false
|
|
111
|
-
};
|
|
112
|
-
},
|
|
113
|
-
bus: this.bus,
|
|
114
|
-
getSkillIndexingContext: () => ({ registeredToolNames: this.registeredToolNames }),
|
|
115
|
-
onSkillsFilesystemMutate: () => this.refreshAgentAfterSkillDiskChange(),
|
|
116
|
-
getSkillPassthroughEnvVarNames: () => {
|
|
117
|
-
const k = this.toolContextSessionKey;
|
|
118
|
-
if (!k) return [];
|
|
119
|
-
return [...this.sessions.get(k)?.skillEnvPassthroughKeys ?? []];
|
|
120
|
-
},
|
|
121
|
-
registerSkillEnvPassthrough: (names) => {
|
|
122
|
-
const k = this.toolContextSessionKey;
|
|
123
|
-
if (!k) return;
|
|
124
|
-
const st = this.sessions.get(k);
|
|
125
|
-
if (!st) return;
|
|
126
|
-
for (const n of names) if (isValidSkillEnvVarName(n)) st.skillEnvPassthroughKeys.add(n.trim());
|
|
127
|
-
}
|
|
128
|
-
}).createAllTools({ getSkillManager: () => this.skillManager });
|
|
129
|
-
this.registeredToolNames = this.tools.map((t) => t.name);
|
|
130
|
-
log.info({ toolCount: this.tools.length }, "Local runtime tools initialized");
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Create agent instance
|
|
134
|
-
*/
|
|
135
|
-
createAgent() {
|
|
136
|
-
let model;
|
|
137
|
-
const modelConfig = this.config?.agents?.defaults?.model;
|
|
138
|
-
if (modelConfig) try {
|
|
139
|
-
model = resolveModel(typeof modelConfig === "string" ? modelConfig : modelConfig.primary);
|
|
140
|
-
} catch {
|
|
141
|
-
const defaultModel = getDefaultModelSync(this.config);
|
|
142
|
-
log.warn({
|
|
143
|
-
modelConfig,
|
|
144
|
-
defaultModel
|
|
145
|
-
}, "Model not found, using default");
|
|
146
|
-
model = resolveModel(defaultModel);
|
|
147
|
-
}
|
|
148
|
-
else model = resolveModel(getDefaultModelSync(this.config));
|
|
149
|
-
const appCfg = this.config ?? loadConfig();
|
|
150
|
-
const bootstrapFiles = loadBootstrapFiles(resolveAgentBootstrapDir(appCfg, normalizeAgentId(this.runtimeConfig?.agent ?? resolveDefaultAgentId(appCfg))));
|
|
151
|
-
const agentConfig = this.config || {
|
|
152
|
-
gateway: {},
|
|
153
|
-
agents: {},
|
|
154
|
-
channels: {},
|
|
155
|
-
tools: {}
|
|
156
|
-
};
|
|
157
|
-
return {
|
|
158
|
-
agent: new Agent({
|
|
159
|
-
initialState: {
|
|
160
|
-
systemPrompt: new SystemPromptBuilder({
|
|
161
|
-
workspace: this.workspace,
|
|
162
|
-
config: agentConfig,
|
|
163
|
-
skillManager: this.skillManager
|
|
164
|
-
}).build(bootstrapFiles, { registeredToolNames: this.registeredToolNames }),
|
|
165
|
-
model,
|
|
166
|
-
tools: this.tools,
|
|
167
|
-
messages: []
|
|
168
|
-
},
|
|
169
|
-
getApiKey: (provider) => getApiKeySync(provider)
|
|
170
|
-
}),
|
|
171
|
-
model
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Handle agent events and convert to ACP events
|
|
176
|
-
*/
|
|
177
|
-
handleAgentEvent(event) {
|
|
178
|
-
log.debug({ eventType: event.type }, "Agent event received");
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Ensure session exists
|
|
182
|
-
*/
|
|
183
|
-
async ensureSession(input) {
|
|
184
|
-
const sessionKey = input.sessionKey || `acp:${randomUUID()}`;
|
|
185
|
-
const agent = input.agent || "main";
|
|
186
|
-
const mode = input.mode || "persistent";
|
|
187
|
-
let messages = [];
|
|
188
|
-
try {
|
|
189
|
-
messages = await this.sessionStore.load(sessionKey);
|
|
190
|
-
} catch {}
|
|
191
|
-
const meta = {
|
|
192
|
-
backend: "local",
|
|
193
|
-
agent,
|
|
194
|
-
runtimeSessionName: sessionKey,
|
|
195
|
-
mode,
|
|
196
|
-
state: "idle",
|
|
197
|
-
lastActivityAt: Date.now(),
|
|
198
|
-
cwd: input.cwd
|
|
199
|
-
};
|
|
200
|
-
this.sessions.set(sessionKey, {
|
|
201
|
-
meta,
|
|
202
|
-
messages,
|
|
203
|
-
skillEnvPassthroughKeys: /* @__PURE__ */ new Set()
|
|
204
|
-
});
|
|
205
|
-
return {
|
|
206
|
-
sessionKey,
|
|
207
|
-
backend: "local",
|
|
208
|
-
runtimeSessionName: sessionKey,
|
|
209
|
-
cwd: input.cwd
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Run a turn - streams events by using the agent
|
|
214
|
-
*/
|
|
215
|
-
async *runTurn(input) {
|
|
216
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
217
|
-
if (!session) throw new AcpRuntimeError(normalizeAcpErrorCode("ACP_SESSION_NOT_FOUND"), `Session ${input.handle.sessionKey} not found`);
|
|
218
|
-
const abortController = new AbortController();
|
|
219
|
-
session.abortController = abortController;
|
|
220
|
-
session.meta.state = "running";
|
|
221
|
-
session.meta.lastActivityAt = Date.now();
|
|
222
|
-
const eventQueue = [];
|
|
223
|
-
let resolveNextEvent = null;
|
|
224
|
-
let eventError = null;
|
|
225
|
-
const getNextEvent = async () => {
|
|
226
|
-
return new Promise((resolve) => {
|
|
227
|
-
if (eventQueue.length > 0) resolve(eventQueue.shift());
|
|
228
|
-
else if (eventError) resolve(null);
|
|
229
|
-
else resolveNextEvent = resolve;
|
|
230
|
-
});
|
|
231
|
-
};
|
|
232
|
-
const pushEvent = (event) => {
|
|
233
|
-
if (resolveNextEvent) {
|
|
234
|
-
const resolve = resolveNextEvent;
|
|
235
|
-
resolveNextEvent = null;
|
|
236
|
-
resolve(event);
|
|
237
|
-
} else eventQueue.push(event);
|
|
238
|
-
};
|
|
239
|
-
input.signal?.addEventListener("abort", () => {
|
|
240
|
-
abortController.abort();
|
|
241
|
-
this.agent.abort();
|
|
242
|
-
});
|
|
243
|
-
this.toolContextSessionKey = input.handle.sessionKey;
|
|
244
|
-
try {
|
|
245
|
-
let loaded = cleanTrailingErrors(session.messages);
|
|
246
|
-
loaded = tryApplySessionTranscriptHygiene(loaded, this.agentModel);
|
|
247
|
-
this.agent.state.messages = loaded;
|
|
248
|
-
yield {
|
|
249
|
-
type: "status",
|
|
250
|
-
text: "Processing..."
|
|
251
|
-
};
|
|
252
|
-
const messageContent = [];
|
|
253
|
-
if (input.text.trim()) messageContent.push({
|
|
254
|
-
type: "text",
|
|
255
|
-
text: input.text
|
|
256
|
-
});
|
|
257
|
-
if (input.attachments) for (const att of input.attachments) if (att.mediaType.startsWith("image/")) messageContent.push({
|
|
258
|
-
type: "image",
|
|
259
|
-
data: att.data,
|
|
260
|
-
mimeType: att.mediaType
|
|
261
|
-
});
|
|
262
|
-
else messageContent.push({
|
|
263
|
-
type: "text",
|
|
264
|
-
text: `[File: ${att.mediaType}]`
|
|
265
|
-
});
|
|
266
|
-
const userMessage = {
|
|
267
|
-
role: "user",
|
|
268
|
-
content: messageContent,
|
|
269
|
-
timestamp: Date.now()
|
|
270
|
-
};
|
|
271
|
-
let accumulatedText = "";
|
|
272
|
-
let currentToolCallId = null;
|
|
273
|
-
let currentToolName = null;
|
|
274
|
-
let currentToolInput = {};
|
|
275
|
-
const unsubscribe = this.agent.subscribe((event) => {
|
|
276
|
-
try {
|
|
277
|
-
switch (event.type) {
|
|
278
|
-
case "agent_start":
|
|
279
|
-
pushEvent({
|
|
280
|
-
type: "status",
|
|
281
|
-
text: "Agent starting..."
|
|
282
|
-
});
|
|
283
|
-
break;
|
|
284
|
-
case "turn_start":
|
|
285
|
-
pushEvent({
|
|
286
|
-
type: "status",
|
|
287
|
-
text: "Processing request..."
|
|
288
|
-
});
|
|
289
|
-
break;
|
|
290
|
-
case "message_start":
|
|
291
|
-
pushEvent({
|
|
292
|
-
type: "status",
|
|
293
|
-
text: "Generating response..."
|
|
294
|
-
});
|
|
295
|
-
break;
|
|
296
|
-
case "message_update": {
|
|
297
|
-
const msgEvent = event;
|
|
298
|
-
if (msgEvent.message?.role === "assistant") {
|
|
299
|
-
const content = msgEvent.message.content;
|
|
300
|
-
const text = Array.isArray(content) ? extractTextContent(content) : String(content);
|
|
301
|
-
if (text.length > accumulatedText.length) {
|
|
302
|
-
const delta = text.slice(accumulatedText.length);
|
|
303
|
-
accumulatedText = text;
|
|
304
|
-
const chunks = this.chunkText(delta, 50);
|
|
305
|
-
for (const chunk of chunks) pushEvent({
|
|
306
|
-
type: "text_delta",
|
|
307
|
-
text: chunk,
|
|
308
|
-
stream: "output"
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
break;
|
|
313
|
-
}
|
|
314
|
-
case "tool_execution_start": {
|
|
315
|
-
const toolEvent = event;
|
|
316
|
-
currentToolCallId = toolEvent.toolCallId || randomUUID();
|
|
317
|
-
currentToolName = toolEvent.toolName || "unknown";
|
|
318
|
-
currentToolInput = toolEvent.args || {};
|
|
319
|
-
pushEvent({
|
|
320
|
-
type: "tool_call",
|
|
321
|
-
text: `Calling tool: ${currentToolName}`,
|
|
322
|
-
toolCallId: currentToolCallId,
|
|
323
|
-
status: "start",
|
|
324
|
-
title: currentToolName,
|
|
325
|
-
input: currentToolInput
|
|
326
|
-
});
|
|
327
|
-
break;
|
|
328
|
-
}
|
|
329
|
-
case "tool_execution_update": {
|
|
330
|
-
const toolEvent = event;
|
|
331
|
-
if (currentToolCallId) pushEvent({
|
|
332
|
-
type: "tool_call",
|
|
333
|
-
text: toolEvent.partialResult || toolEvent.content || "...",
|
|
334
|
-
toolCallId: currentToolCallId,
|
|
335
|
-
status: "progress",
|
|
336
|
-
title: currentToolName || void 0,
|
|
337
|
-
input: currentToolInput
|
|
338
|
-
});
|
|
339
|
-
break;
|
|
340
|
-
}
|
|
341
|
-
case "tool_execution_end": {
|
|
342
|
-
const toolEvent = event;
|
|
343
|
-
if (currentToolCallId && currentToolName) {
|
|
344
|
-
const isError = toolEvent.isError === true;
|
|
345
|
-
let resultText = "";
|
|
346
|
-
let hasError = isError;
|
|
347
|
-
const result = toolEvent.result;
|
|
348
|
-
if (result && typeof result === "object") {
|
|
349
|
-
const resultObj = result;
|
|
350
|
-
if (resultObj.content && Array.isArray(resultObj.content)) {
|
|
351
|
-
for (const item of resultObj.content) if (item && typeof item === "object") {
|
|
352
|
-
const itemObj = item;
|
|
353
|
-
if (itemObj.type === "text") resultText = String(itemObj.text || "");
|
|
354
|
-
else if (itemObj.type === "error") {
|
|
355
|
-
resultText = String(itemObj.error || "Tool execution failed");
|
|
356
|
-
hasError = true;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
} else if (resultObj.error) {
|
|
360
|
-
resultText = String(resultObj.error);
|
|
361
|
-
hasError = true;
|
|
362
|
-
} else if (resultObj.message) resultText = String(resultObj.message);
|
|
363
|
-
} else if (typeof result === "string") resultText = result;
|
|
364
|
-
if (!resultText) resultText = hasError ? "Tool execution failed" : "Tool executed successfully";
|
|
365
|
-
pushEvent({
|
|
366
|
-
type: "tool_call",
|
|
367
|
-
text: resultText,
|
|
368
|
-
toolCallId: currentToolCallId,
|
|
369
|
-
status: hasError ? "error" : "end",
|
|
370
|
-
title: currentToolName,
|
|
371
|
-
input: currentToolInput,
|
|
372
|
-
output: resultText,
|
|
373
|
-
error: hasError ? resultText : void 0
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
currentToolCallId = null;
|
|
377
|
-
currentToolName = null;
|
|
378
|
-
currentToolInput = {};
|
|
379
|
-
break;
|
|
380
|
-
}
|
|
381
|
-
case "message_end":
|
|
382
|
-
pushEvent({
|
|
383
|
-
type: "status",
|
|
384
|
-
text: "Complete"
|
|
385
|
-
});
|
|
386
|
-
break;
|
|
387
|
-
case "turn_end": break;
|
|
388
|
-
case "agent_end": break;
|
|
389
|
-
}
|
|
390
|
-
} catch (err) {
|
|
391
|
-
log.error({
|
|
392
|
-
err,
|
|
393
|
-
eventType: event.type
|
|
394
|
-
}, "Error handling agent event");
|
|
395
|
-
eventError = err instanceof Error ? err : new Error(String(err));
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
try {
|
|
399
|
-
await this.agent.prompt(userMessage);
|
|
400
|
-
await this.agent.waitForIdle();
|
|
401
|
-
while (eventQueue.length > 0 || resolveNextEvent) {
|
|
402
|
-
const event = await getNextEvent();
|
|
403
|
-
if (event) yield event;
|
|
404
|
-
else break;
|
|
405
|
-
}
|
|
406
|
-
const { messages: sanitized } = sanitizeMessages(this.agent.state.messages);
|
|
407
|
-
const persisted = tryApplySessionTranscriptHygieneForPersistence(sanitized, this.agentModel);
|
|
408
|
-
session.messages = [...persisted];
|
|
409
|
-
await this.sessionStore.save(input.handle.sessionKey, persisted);
|
|
410
|
-
} finally {
|
|
411
|
-
unsubscribe();
|
|
412
|
-
}
|
|
413
|
-
yield {
|
|
414
|
-
type: "done",
|
|
415
|
-
stopReason: "done"
|
|
416
|
-
};
|
|
417
|
-
session.meta.state = "idle";
|
|
418
|
-
session.meta.lastActivityAt = Date.now();
|
|
419
|
-
} catch (error) {
|
|
420
|
-
session.meta.state = "error";
|
|
421
|
-
session.meta.lastError = error instanceof Error ? error.message : String(error);
|
|
422
|
-
yield {
|
|
423
|
-
type: "error",
|
|
424
|
-
message: error instanceof Error ? error.message : String(error)
|
|
425
|
-
};
|
|
426
|
-
throw error;
|
|
427
|
-
} finally {
|
|
428
|
-
this.toolContextSessionKey = null;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Execute a tool
|
|
433
|
-
*/
|
|
434
|
-
async executeTool(toolName, toolInput) {
|
|
435
|
-
const tool = this.tools.find((t) => t.name === toolName);
|
|
436
|
-
if (!tool) return {
|
|
437
|
-
content: [{
|
|
438
|
-
type: "text",
|
|
439
|
-
text: `Tool not found: ${toolName}`
|
|
440
|
-
}],
|
|
441
|
-
details: {}
|
|
442
|
-
};
|
|
443
|
-
try {
|
|
444
|
-
const toolCallId = randomUUID();
|
|
445
|
-
return await tool.execute(toolCallId, toolInput);
|
|
446
|
-
} catch (error) {
|
|
447
|
-
return {
|
|
448
|
-
content: [{
|
|
449
|
-
type: "text",
|
|
450
|
-
text: `Error executing tool: ${error instanceof Error ? error.message : String(error)}`
|
|
451
|
-
}],
|
|
452
|
-
details: {}
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Get runtime capabilities
|
|
458
|
-
*/
|
|
459
|
-
async getCapabilities(_input) {
|
|
460
|
-
const toolNames = this.tools.map((t) => t.name);
|
|
461
|
-
return {
|
|
462
|
-
controls: [
|
|
463
|
-
"session/set_mode",
|
|
464
|
-
"session/set_config_option",
|
|
465
|
-
"session/status",
|
|
466
|
-
"session/reset"
|
|
467
|
-
],
|
|
468
|
-
configOptionKeys: [
|
|
469
|
-
"model",
|
|
470
|
-
"temperature",
|
|
471
|
-
"maxTokens"
|
|
472
|
-
],
|
|
473
|
-
toolNames: toolNames.length > 0 ? toolNames : void 0
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Get session status
|
|
478
|
-
*/
|
|
479
|
-
async getStatus(input) {
|
|
480
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
481
|
-
if (!session) throw new AcpRuntimeError(normalizeAcpErrorCode("ACP_SESSION_NOT_FOUND"), `Session ${input.handle.sessionKey} not found`);
|
|
482
|
-
let tokenEstimate = 0;
|
|
483
|
-
try {
|
|
484
|
-
tokenEstimate = await this.sessionStore.estimateTokenUsage(input.handle.sessionKey, session.messages);
|
|
485
|
-
} catch {}
|
|
486
|
-
return {
|
|
487
|
-
summary: `Session: ${input.handle.runtimeSessionName}, Agent: ${session.meta.agent}, State: ${session.meta.state}, Messages: ${session.messages.length}`,
|
|
488
|
-
details: {
|
|
489
|
-
mode: session.meta.mode,
|
|
490
|
-
cwd: session.meta.cwd,
|
|
491
|
-
lastActivityAt: session.meta.lastActivityAt,
|
|
492
|
-
messageCount: session.messages.length,
|
|
493
|
-
tokenEstimate,
|
|
494
|
-
state: session.meta.state,
|
|
495
|
-
lastError: session.meta.lastError
|
|
496
|
-
}
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Set session mode
|
|
501
|
-
*/
|
|
502
|
-
async setMode(input) {
|
|
503
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
504
|
-
if (session) {
|
|
505
|
-
const validModes = ["persistent", "oneshot"];
|
|
506
|
-
if (validModes.includes(input.mode)) {
|
|
507
|
-
session.meta.mode = input.mode;
|
|
508
|
-
log.info({
|
|
509
|
-
sessionKey: input.handle.sessionKey,
|
|
510
|
-
mode: input.mode
|
|
511
|
-
}, "Session mode changed");
|
|
512
|
-
} else throw new AcpRuntimeError(normalizeAcpErrorCode("ACP_INVALID_INPUT"), `Invalid mode: ${input.mode}. Valid modes: ${validModes.join(", ")}`);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Set config option
|
|
517
|
-
*/
|
|
518
|
-
async setConfigOption(input) {
|
|
519
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
520
|
-
if (!session) throw new AcpRuntimeError(normalizeAcpErrorCode("ACP_SESSION_NOT_FOUND"), `Session ${input.handle.sessionKey} not found`);
|
|
521
|
-
if (!session.meta.runtimeOptions) session.meta.runtimeOptions = {};
|
|
522
|
-
switch (input.key) {
|
|
523
|
-
case "model":
|
|
524
|
-
case "temperature":
|
|
525
|
-
case "maxTokens":
|
|
526
|
-
session.meta.runtimeOptions[input.key] = input.value;
|
|
527
|
-
log.info({
|
|
528
|
-
sessionKey: input.handle.sessionKey,
|
|
529
|
-
key: input.key,
|
|
530
|
-
value: input.value
|
|
531
|
-
}, "Config option set");
|
|
532
|
-
break;
|
|
533
|
-
default: log.warn({ key: input.key }, "Unknown config option key");
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Reset session - clears message history
|
|
538
|
-
*/
|
|
539
|
-
async resetSession(input) {
|
|
540
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
541
|
-
if (!session) throw new AcpRuntimeError(normalizeAcpErrorCode("ACP_SESSION_NOT_FOUND"), `Session ${input.handle.sessionKey} not found`);
|
|
542
|
-
session.messages = [];
|
|
543
|
-
this.agent.state.messages = [];
|
|
544
|
-
try {
|
|
545
|
-
await this.sessionStore.delete(input.handle.sessionKey);
|
|
546
|
-
} catch {}
|
|
547
|
-
session.meta.state = "idle";
|
|
548
|
-
session.meta.lastActivityAt = Date.now();
|
|
549
|
-
session.meta.lastError = void 0;
|
|
550
|
-
log.info({ sessionKey: input.handle.sessionKey }, "Session reset");
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* Health check
|
|
554
|
-
*/
|
|
555
|
-
async doctor() {
|
|
556
|
-
return {
|
|
557
|
-
ok: true,
|
|
558
|
-
message: "Local runtime is healthy"
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Cancel current operation
|
|
563
|
-
*/
|
|
564
|
-
async cancel(input) {
|
|
565
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
566
|
-
if (session?.abortController) session.abortController.abort();
|
|
567
|
-
this.agent.abort();
|
|
568
|
-
session.meta.state = "idle";
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
* Close session
|
|
572
|
-
*/
|
|
573
|
-
async close(input) {
|
|
574
|
-
const session = this.sessions.get(input.handle.sessionKey);
|
|
575
|
-
if (session) {
|
|
576
|
-
if (session.abortController) session.abortController.abort();
|
|
577
|
-
if (session.messages.length > 0) await this.sessionStore.save(input.handle.sessionKey, session.messages);
|
|
578
|
-
this.sessions.delete(input.handle.sessionKey);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Split text into chunks
|
|
583
|
-
*/
|
|
584
|
-
chunkText(text, chunkSize) {
|
|
585
|
-
const chunks = [];
|
|
586
|
-
for (let i = 0; i < text.length; i += chunkSize) chunks.push(text.slice(i, i + chunkSize));
|
|
587
|
-
return chunks;
|
|
588
|
-
}
|
|
589
|
-
};
|
|
590
|
-
/**
|
|
591
|
-
* Create a local ACP runtime backend
|
|
592
|
-
*/
|
|
593
|
-
function createLocalAcpRuntimeBackend(bus, config) {
|
|
594
|
-
return {
|
|
595
|
-
id: "local",
|
|
596
|
-
runtime: new LocalAcpRuntime(bus, config),
|
|
597
|
-
healthy: () => true
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
//#endregion
|
|
601
|
-
export { LocalAcpRuntime, createLocalAcpRuntimeBackend };
|
|
602
|
-
|
|
603
|
-
//# sourceMappingURL=local.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local.js","names":[],"sources":["../../../../../src/acp/runtime/backends/local.ts"],"sourcesContent":["/**\n * Local ACP Runtime Backend\n *\n * A simple ACP runtime that runs directly in xopc's process,\n * using the existing agent system for turn execution.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { Agent, type AgentEvent, type AgentMessage, type AgentTool, type AgentToolResult } from \"@mariozechner/pi-agent-core\";\nimport type { Model, Api } from \"@mariozechner/pi-ai\";\nimport type {\n AcpRuntime,\n AcpRuntimeCapabilities,\n AcpRuntimeDoctorReport,\n AcpRuntimeEnsureInput,\n AcpRuntimeEvent,\n AcpRuntimeHandle,\n AcpRuntimeStatus,\n AcpRuntimeTurnInput,\n SessionAcpMeta,\n} from \"../types.js\";\nimport { AcpRuntimeError, normalizeAcpErrorCode } from \"../errors.js\";\nimport type { MessageBus } from \"../../../infra/bus/index.js\";\nimport type { Config } from \"../../../config/schema.js\";\nimport { loadConfig } from \"../../../config/loader.js\";\nimport { SessionStore } from \"../../../session/index.js\";\nimport { resolveModel, getDefaultModelSync, getApiKeySync } from \"../../../providers/index.js\";\nimport { resolveBundledSkillsDir } from \"../../../config/paths.js\";\nimport { AgentToolsFactory } from \"../../../agent/tools/factory.js\";\nimport { SystemPromptBuilder } from \"../../../agent/prompt/service-prompt-builder.js\";\nimport { SkillManager } from \"../../../agent/skills/index.js\";\nimport { isValidSkillEnvVarName } from \"../../../agent/skills/required-env-vars.js\";\nimport { loadBootstrapFiles, extractTextContent } from \"../../../agent/context/workspace.js\";\nimport { resolveAgentBootstrapDir } from \"../../../config/agent-profile.js\";\nimport { normalizeAgentId, resolveDefaultAgentId } from '../../../agent/agent-scope.js';\nimport { cleanTrailingErrors, sanitizeMessages } from \"../../../agent/memory/message-sanitizer.js\";\nimport {\n tryApplySessionTranscriptHygiene,\n tryApplySessionTranscriptHygieneForPersistence,\n} from \"../../../agent/transcript/transcript-hygiene.js\";\nimport { createLogger } from \"../../../utils/logger.js\";\n\nconst log = createLogger(\"LocalAcpRuntime\");\n\n/**\n * Local Runtime Configuration\n */\nexport interface LocalRuntimeConfig {\n /** Agent ID to use */\n agent: string;\n /** Working directory */\n cwd?: string;\n /** Additional environment variables */\n env?: Record<string, string>;\n /** Config */\n config?: Config;\n /** Workspace path */\n workspace?: string;\n}\n\n/**\n * Session state for Local Runtime\n */\ninterface LocalSessionState {\n meta: SessionAcpMeta;\n messages: AgentMessage[];\n abortController?: AbortController;\n /** Declared env names from skill_view; shell reads values from process.env at spawn time. */\n skillEnvPassthroughKeys: Set<string>;\n}\n\n/**\n * Local ACP Runtime\n *\n * Implements AcpRuntime by directly using xopc's AgentCore,\n * with its own session management.\n */\nexport class LocalAcpRuntime implements AcpRuntime {\n private readonly sessions = new Map<string, LocalSessionState>();\n private agent: Agent;\n /** Resolved default model for transcript hygiene. */\n private agentModel: Model<Api>;\n private sessionStore: SessionStore;\n private tools: AgentTool<any, any>[] = [];\n private workspace: string;\n private config?: Config;\n private skillManager: SkillManager;\n private registeredToolNames: string[] = [];\n /** Set during runTurn so skill_view / shell can scope passthrough to the active ACP session. */\n private toolContextSessionKey: string | null = null;\n\n constructor(\n private readonly bus: MessageBus,\n private readonly runtimeConfig?: LocalRuntimeConfig\n ) {\n this.workspace = runtimeConfig?.workspace || process.cwd();\n this.config = runtimeConfig?.config;\n this.skillManager = new SkillManager(this.workspace, resolveBundledSkillsDir());\n\n // Initialize session store\n const appCfg = this.config ?? loadConfig();\n this.sessionStore = new SessionStore({ config: appCfg }, {\n maxMessages: 100,\n keepRecentMessages: 20,\n preserveSystemMessages: true,\n }, {\n enabled: true,\n mode: \"abstractive\",\n reserveTokens: 8000,\n triggerThreshold: 0.8,\n minMessagesBeforeCompact: 10,\n keepRecentMessages: 10,\n evictionWindow: 0.2,\n retentionWindow: 6,\n });\n\n // Initialize tools (registers skill_manage → needs mutate hook before createAgent)\n this.initializeTools();\n\n // Initialize agent\n const { agent, model } = this.createAgent();\n this.agent = agent;\n this.agentModel = model;\n\n // Subscribe to agent events\n this.agent.subscribe((event) => this.handleAgentEvent(event));\n }\n\n /**\n * Initialize tools using AgentToolsFactory pattern\n */\n private refreshAgentAfterSkillDiskChange(): void {\n this.skillManager.reload();\n const appCfg = this.config ?? loadConfig();\n const agentId = normalizeAgentId(this.runtimeConfig?.agent ?? resolveDefaultAgentId(appCfg));\n const bootstrapFiles = loadBootstrapFiles(resolveAgentBootstrapDir(appCfg, agentId));\n const agentConfig = this.config || {\n gateway: {},\n agents: {},\n channels: {},\n tools: {},\n } as Config;\n const sp = new SystemPromptBuilder({\n workspace: this.workspace,\n config: agentConfig,\n skillManager: this.skillManager,\n }).build(bootstrapFiles, { registeredToolNames: this.registeredToolNames });\n this.agent.state.systemPrompt = sp;\n }\n\n private initializeTools(): void {\n const toolsFactory = new AgentToolsFactory({\n workspace: this.workspace,\n getCurrentContext: () => {\n const k = this.toolContextSessionKey;\n if (!k) return null;\n return {\n sessionKey: k,\n channel: \"acp\",\n chatId: k,\n senderId: \"acp\",\n isGroup: false,\n };\n },\n bus: this.bus,\n getSkillIndexingContext: () => ({\n registeredToolNames: this.registeredToolNames,\n }),\n onSkillsFilesystemMutate: () => this.refreshAgentAfterSkillDiskChange(),\n getSkillPassthroughEnvVarNames: () => {\n const k = this.toolContextSessionKey;\n if (!k) return [];\n return [...(this.sessions.get(k)?.skillEnvPassthroughKeys ?? [])];\n },\n registerSkillEnvPassthrough: (names: string[]) => {\n const k = this.toolContextSessionKey;\n if (!k) return;\n const st = this.sessions.get(k);\n if (!st) return;\n for (const n of names) {\n if (isValidSkillEnvVarName(n)) {\n st.skillEnvPassthroughKeys.add(n.trim());\n }\n }\n },\n });\n this.tools = toolsFactory.createAllTools({\n getSkillManager: () => this.skillManager,\n });\n this.registeredToolNames = this.tools.map((t) => t.name);\n log.info({ toolCount: this.tools.length }, \"Local runtime tools initialized\");\n }\n\n /**\n * Create agent instance\n */\n private createAgent(): { agent: Agent; model: Model<Api> } {\n let model: Model<Api>;\n\n const modelConfig = this.config?.agents?.defaults?.model;\n if (modelConfig) {\n try {\n const modelId = typeof modelConfig === \"string\" ? modelConfig : modelConfig.primary;\n model = resolveModel(modelId);\n } catch {\n const defaultModel = getDefaultModelSync(this.config);\n log.warn({ modelConfig, defaultModel }, \"Model not found, using default\");\n model = resolveModel(defaultModel);\n }\n } else {\n const defaultModel = getDefaultModelSync(this.config);\n model = resolveModel(defaultModel);\n }\n\n const appCfg = this.config ?? loadConfig();\n const agentId = normalizeAgentId(this.runtimeConfig?.agent ?? resolveDefaultAgentId(appCfg));\n const bootstrapFiles = loadBootstrapFiles(resolveAgentBootstrapDir(appCfg, agentId));\n // Create a minimal config if none provided\n const agentConfig = this.config || {\n gateway: {},\n agents: {},\n channels: {},\n tools: {},\n } as Config;\n \n const systemPromptBuilder = new SystemPromptBuilder({\n workspace: this.workspace,\n config: agentConfig,\n skillManager: this.skillManager,\n });\n\n const agent = new Agent({\n initialState: {\n systemPrompt: systemPromptBuilder.build(bootstrapFiles, {\n registeredToolNames: this.registeredToolNames,\n }),\n model,\n tools: this.tools,\n messages: [],\n },\n getApiKey: (provider: string) => getApiKeySync(provider),\n });\n return { agent, model };\n }\n\n /**\n * Handle agent events and convert to ACP events\n */\n private handleAgentEvent(event: AgentEvent): void {\n // Event handling is done in runTurn via the eventCallback\n log.debug({ eventType: event.type }, \"Agent event received\");\n }\n\n /**\n * Ensure session exists\n */\n async ensureSession(input: AcpRuntimeEnsureInput): Promise<AcpRuntimeHandle> {\n const sessionKey = input.sessionKey || `acp:${randomUUID()}`;\n const agent = input.agent || \"main\";\n const mode = input.mode || \"persistent\";\n\n // Load existing messages or create new session\n let messages: AgentMessage[] = [];\n try {\n messages = await this.sessionStore.load(sessionKey);\n } catch {\n // Session doesn't exist yet\n }\n\n // Create session metadata\n const meta: SessionAcpMeta = {\n backend: \"local\",\n agent,\n runtimeSessionName: sessionKey,\n mode,\n state: \"idle\",\n lastActivityAt: Date.now(),\n cwd: input.cwd,\n };\n\n this.sessions.set(sessionKey, {\n meta,\n messages,\n skillEnvPassthroughKeys: new Set<string>(),\n });\n\n return {\n sessionKey,\n backend: \"local\",\n runtimeSessionName: sessionKey,\n cwd: input.cwd,\n };\n }\n\n /**\n * Run a turn - streams events by using the agent\n */\n async *runTurn(input: AcpRuntimeTurnInput): AsyncIterable<AcpRuntimeEvent> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (!session) {\n throw new AcpRuntimeError(\n normalizeAcpErrorCode(\"ACP_SESSION_NOT_FOUND\"),\n `Session ${input.handle.sessionKey} not found`\n );\n }\n\n // Create abort controller for cancellation\n const abortController = new AbortController();\n session.abortController = abortController;\n\n // Update session state\n session.meta.state = \"running\";\n session.meta.lastActivityAt = Date.now();\n\n // Create event queue for this turn\n const eventQueue: AcpRuntimeEvent[] = [];\n let resolveNextEvent: ((event: AcpRuntimeEvent | null) => void) | null = null;\n let eventError: Error | null = null;\n\n const getNextEvent = async (): Promise<AcpRuntimeEvent | null> => {\n return new Promise((resolve) => {\n if (eventQueue.length > 0) {\n resolve(eventQueue.shift()!);\n } else if (eventError) {\n resolve(null);\n } else {\n resolveNextEvent = resolve;\n }\n });\n };\n\n const pushEvent = (event: AcpRuntimeEvent): void => {\n if (resolveNextEvent) {\n const resolve = resolveNextEvent;\n resolveNextEvent = null;\n resolve(event);\n } else {\n eventQueue.push(event);\n }\n };\n\n // Set up abort signal handler\n input.signal?.addEventListener(\"abort\", () => {\n abortController.abort();\n this.agent.abort();\n });\n\n this.toolContextSessionKey = input.handle.sessionKey;\n try {\n // Load session messages into agent (transcript hygiene aligned with main AgentService)\n let loaded = cleanTrailingErrors(session.messages);\n loaded = tryApplySessionTranscriptHygiene(loaded, this.agentModel);\n this.agent.state.messages = loaded;\n\n // Yield initial status\n yield {\n type: \"status\" as const,\n text: \"Processing...\",\n };\n\n // Build user message\n const messageContent: Array<{ type: \"text\"; text: string } | { type: \"image\"; data: string; mimeType: string }> = [];\n\n if (input.text.trim()) {\n messageContent.push({ type: \"text\", text: input.text });\n }\n\n // Handle attachments\n if (input.attachments) {\n for (const att of input.attachments) {\n if (att.mediaType.startsWith(\"image/\")) {\n messageContent.push({ type: \"image\", data: att.data, mimeType: att.mediaType });\n } else {\n messageContent.push({\n type: \"text\",\n text: `[File: ${att.mediaType}]`,\n });\n }\n }\n }\n\n const userMessage: AgentMessage = {\n role: \"user\",\n content: messageContent,\n timestamp: Date.now(),\n };\n\n // Process with agent and collect events\n let accumulatedText = \"\";\n let currentToolCallId: string | null = null;\n let currentToolName: string | null = null;\n let currentToolInput: Record<string, unknown> = {};\n\n // Subscribe to events during this turn\n const unsubscribe = this.agent.subscribe((event: AgentEvent) => {\n try {\n switch (event.type) {\n case \"agent_start\": {\n pushEvent({\n type: \"status\",\n text: \"Agent starting...\",\n });\n break;\n }\n\n case \"turn_start\": {\n pushEvent({\n type: \"status\",\n text: \"Processing request...\",\n });\n break;\n }\n\n case \"message_start\": {\n pushEvent({\n type: \"status\",\n text: \"Generating response...\",\n });\n break;\n }\n\n case \"message_update\": {\n const msgEvent = event as any;\n if (msgEvent.message?.role === \"assistant\") {\n const content = msgEvent.message.content;\n const text = Array.isArray(content)\n ? extractTextContent(content as Array<{ type: string; text?: string }>)\n : String(content);\n\n // Yield text delta\n if (text.length > accumulatedText.length) {\n const delta = text.slice(accumulatedText.length);\n accumulatedText = text;\n\n // Split into chunks for streaming\n const chunks = this.chunkText(delta, 50);\n for (const chunk of chunks) {\n pushEvent({\n type: \"text_delta\",\n text: chunk,\n stream: \"output\",\n });\n }\n }\n }\n break;\n }\n\n case \"tool_execution_start\": {\n const toolEvent = event as any;\n currentToolCallId = toolEvent.toolCallId || randomUUID();\n currentToolName = toolEvent.toolName || \"unknown\";\n // Note: pi-agent-core uses 'args' not 'input'\n currentToolInput = (toolEvent.args as Record<string, unknown>) || {};\n\n pushEvent({\n type: \"tool_call\",\n text: `Calling tool: ${currentToolName}`,\n toolCallId: currentToolCallId,\n status: \"start\",\n title: currentToolName,\n input: currentToolInput,\n });\n break;\n }\n\n case \"tool_execution_update\": {\n const toolEvent = event as any;\n if (currentToolCallId) {\n const progressText = toolEvent.partialResult || toolEvent.content || \"...\";\n pushEvent({\n type: \"tool_call\",\n text: progressText,\n toolCallId: currentToolCallId,\n status: \"progress\",\n title: currentToolName || undefined,\n input: currentToolInput,\n });\n }\n break;\n }\n\n case \"tool_execution_end\": {\n const toolEvent = event as any;\n if (currentToolCallId && currentToolName) {\n const isError = toolEvent.isError === true;\n let resultText = \"\";\n let hasError = isError;\n\n const result = toolEvent.result;\n if (result && typeof result === \"object\") {\n // Handle different result formats\n const resultObj = result as Record<string, unknown>;\n if (resultObj.content && Array.isArray(resultObj.content)) {\n for (const item of resultObj.content) {\n if (item && typeof item === \"object\") {\n const itemObj = item as Record<string, unknown>;\n if (itemObj.type === \"text\") {\n resultText = String(itemObj.text || \"\");\n } else if (itemObj.type === \"error\") {\n resultText = String(itemObj.error || \"Tool execution failed\");\n hasError = true;\n }\n }\n }\n } else if (resultObj.error) {\n resultText = String(resultObj.error);\n hasError = true;\n } else if (resultObj.message) {\n resultText = String(resultObj.message);\n }\n } else if (typeof result === \"string\") {\n resultText = result;\n }\n\n if (!resultText) {\n resultText = hasError ? \"Tool execution failed\" : \"Tool executed successfully\";\n }\n\n pushEvent({\n type: \"tool_call\",\n text: resultText,\n toolCallId: currentToolCallId,\n status: hasError ? \"error\" : \"end\",\n title: currentToolName,\n input: currentToolInput,\n output: resultText,\n error: hasError ? resultText : undefined,\n });\n }\n currentToolCallId = null;\n currentToolName = null;\n currentToolInput = {};\n break;\n }\n\n case \"message_end\": {\n pushEvent({\n type: \"status\",\n text: \"Complete\",\n });\n break;\n }\n\n case \"turn_end\": {\n // Turn complete\n break;\n }\n\n case \"agent_end\": {\n // Agent done\n break;\n }\n }\n } catch (err) {\n log.error({ err, eventType: event.type }, \"Error handling agent event\");\n eventError = err instanceof Error ? err : new Error(String(err));\n }\n });\n\n try {\n // Send prompt to agent\n await this.agent.prompt(userMessage);\n\n // Wait for agent to finish\n await this.agent.waitForIdle();\n\n // Collect remaining events from queue\n while (eventQueue.length > 0 || resolveNextEvent) {\n const event = await getNextEvent();\n if (event) {\n yield event;\n } else {\n break;\n }\n }\n\n // Save session messages\n const { messages: sanitized } = sanitizeMessages(this.agent.state.messages);\n const persisted = tryApplySessionTranscriptHygieneForPersistence(sanitized, this.agentModel);\n session.messages = [...persisted];\n await this.sessionStore.save(input.handle.sessionKey, persisted);\n\n } finally {\n unsubscribe();\n }\n\n // Yield done\n yield {\n type: \"done\",\n stopReason: \"done\",\n };\n\n // Update session state\n session.meta.state = \"idle\";\n session.meta.lastActivityAt = Date.now();\n\n } catch (error) {\n session.meta.state = \"error\";\n session.meta.lastError = error instanceof Error ? error.message : String(error);\n\n yield {\n type: \"error\",\n message: error instanceof Error ? error.message : String(error),\n };\n\n throw error;\n } finally {\n this.toolContextSessionKey = null;\n }\n }\n\n /**\n * Execute a tool\n */\n private async executeTool(\n toolName: string,\n toolInput: Record<string, unknown>\n ): Promise<AgentToolResult<unknown>> {\n const tool = this.tools.find((t) => t.name === toolName);\n\n if (!tool) {\n return {\n content: [{ type: \"text\", text: `Tool not found: ${toolName}` }],\n details: {},\n };\n }\n\n try {\n const toolCallId = randomUUID();\n const result = await tool.execute(toolCallId, toolInput);\n return result;\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error executing tool: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: {},\n };\n }\n }\n\n /**\n * Get runtime capabilities\n */\n async getCapabilities(_input?: { handle?: AcpRuntimeHandle }): Promise<AcpRuntimeCapabilities> {\n const toolNames = this.tools.map((t) => t.name);\n\n return {\n controls: [\n \"session/set_mode\",\n \"session/set_config_option\",\n \"session/status\",\n \"session/reset\",\n ],\n configOptionKeys: [\"model\", \"temperature\", \"maxTokens\"],\n toolNames: toolNames.length > 0 ? toolNames : undefined,\n };\n }\n\n /**\n * Get session status\n */\n async getStatus(input: { handle: AcpRuntimeHandle; signal?: AbortSignal }): Promise<AcpRuntimeStatus> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (!session) {\n throw new AcpRuntimeError(\n normalizeAcpErrorCode(\"ACP_SESSION_NOT_FOUND\"),\n `Session ${input.handle.sessionKey} not found`\n );\n }\n\n // Get token estimate if available\n let tokenEstimate = 0;\n try {\n const estimate = await this.sessionStore.estimateTokenUsage(input.handle.sessionKey, session.messages);\n tokenEstimate = estimate;\n } catch {\n // Ignore estimation errors\n }\n\n return {\n summary: `Session: ${input.handle.runtimeSessionName}, Agent: ${session.meta.agent}, State: ${session.meta.state}, Messages: ${session.messages.length}`,\n details: {\n mode: session.meta.mode,\n cwd: session.meta.cwd,\n lastActivityAt: session.meta.lastActivityAt,\n messageCount: session.messages.length,\n tokenEstimate,\n state: session.meta.state,\n lastError: session.meta.lastError,\n },\n };\n }\n\n /**\n * Set session mode\n */\n async setMode(input: { handle: AcpRuntimeHandle; mode: string }): Promise<void> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (session) {\n const validModes = [\"persistent\", \"oneshot\"];\n if (validModes.includes(input.mode)) {\n session.meta.mode = input.mode as \"persistent\" | \"oneshot\";\n log.info({ sessionKey: input.handle.sessionKey, mode: input.mode }, \"Session mode changed\");\n } else {\n throw new AcpRuntimeError(\n normalizeAcpErrorCode(\"ACP_INVALID_INPUT\"),\n `Invalid mode: ${input.mode}. Valid modes: ${validModes.join(\", \")}`\n );\n }\n }\n }\n\n /**\n * Set config option\n */\n async setConfigOption(input: { handle: AcpRuntimeHandle; key: string; value: string }): Promise<void> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (!session) {\n throw new AcpRuntimeError(\n normalizeAcpErrorCode(\"ACP_SESSION_NOT_FOUND\"),\n `Session ${input.handle.sessionKey} not found`\n );\n }\n\n // Store config in runtimeOptions\n if (!session.meta.runtimeOptions) {\n session.meta.runtimeOptions = {};\n }\n\n switch (input.key) {\n case \"model\":\n case \"temperature\":\n case \"maxTokens\":\n session.meta.runtimeOptions[input.key] = input.value;\n log.info({ sessionKey: input.handle.sessionKey, key: input.key, value: input.value }, \"Config option set\");\n break;\n default:\n log.warn({ key: input.key }, \"Unknown config option key\");\n }\n }\n\n /**\n * Reset session - clears message history\n */\n async resetSession(input: { handle: AcpRuntimeHandle }): Promise<void> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (!session) {\n throw new AcpRuntimeError(\n normalizeAcpErrorCode(\"ACP_SESSION_NOT_FOUND\"),\n `Session ${input.handle.sessionKey} not found`\n );\n }\n\n // Clear messages\n session.messages = [];\n \n // Clear agent messages\n this.agent.state.messages = [];\n\n // Delete from session store\n try {\n await this.sessionStore.delete(input.handle.sessionKey);\n } catch {\n // Ignore if not found\n }\n\n // Reset state\n session.meta.state = \"idle\";\n session.meta.lastActivityAt = Date.now();\n session.meta.lastError = undefined;\n\n log.info({ sessionKey: input.handle.sessionKey }, \"Session reset\");\n }\n\n /**\n * Health check\n */\n async doctor(): Promise<AcpRuntimeDoctorReport> {\n return {\n ok: true,\n message: \"Local runtime is healthy\",\n };\n }\n\n /**\n * Cancel current operation\n */\n async cancel(input: { handle: AcpRuntimeHandle; reason?: string }): Promise<void> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (session?.abortController) {\n session.abortController.abort();\n }\n this.agent.abort();\n session.meta.state = \"idle\";\n }\n\n /**\n * Close session\n */\n async close(input: { handle: AcpRuntimeHandle; reason: string }): Promise<void> {\n const session = this.sessions.get(input.handle.sessionKey);\n if (session) {\n if (session.abortController) {\n session.abortController.abort();\n }\n // Save messages before closing\n if (session.messages.length > 0) {\n await this.sessionStore.save(input.handle.sessionKey, session.messages);\n }\n this.sessions.delete(input.handle.sessionKey);\n }\n }\n\n /**\n * Split text into chunks\n */\n private chunkText(text: string, chunkSize: number): string[] {\n const chunks: string[] = [];\n for (let i = 0; i < text.length; i += chunkSize) {\n chunks.push(text.slice(i, i + chunkSize));\n }\n return chunks;\n }\n}\n\n/**\n * Create a local ACP runtime backend\n */\nexport function createLocalAcpRuntimeBackend(\n bus: MessageBus,\n config?: LocalRuntimeConfig,\n): { id: string; runtime: AcpRuntime; healthy: () => boolean } {\n const runtime = new LocalAcpRuntime(bus, config);\n\n return {\n id: \"local\",\n runtime,\n healthy: () => true,\n };\n}\n"],"mappings":"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"}
|