@clinebot/core 0.0.35 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/ClineCore.d.ts +362 -39
- package/dist/ClineCore.d.ts.map +1 -1
- package/dist/account/cline-account-service.d.ts.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/rpc.d.ts +6 -6
- package/dist/account/rpc.d.ts.map +1 -1
- package/dist/cron/cron-event-ingress.d.ts +38 -0
- package/dist/cron/cron-event-ingress.d.ts.map +1 -0
- package/dist/cron/cron-materializer.d.ts +36 -0
- package/dist/cron/cron-materializer.d.ts.map +1 -0
- package/dist/cron/cron-reconciler.d.ts +62 -0
- package/dist/cron/cron-reconciler.d.ts.map +1 -0
- package/dist/cron/cron-report-writer.d.ts +41 -0
- package/dist/cron/cron-report-writer.d.ts.map +1 -0
- package/dist/cron/cron-runner.d.ts +43 -0
- package/dist/cron/cron-runner.d.ts.map +1 -0
- package/dist/cron/cron-schema.d.ts +3 -0
- package/dist/cron/cron-schema.d.ts.map +1 -0
- package/dist/cron/cron-service.d.ts +57 -0
- package/dist/cron/cron-service.d.ts.map +1 -0
- package/dist/cron/cron-spec-parser.d.ts +27 -0
- package/dist/cron/cron-spec-parser.d.ts.map +1 -0
- package/dist/cron/cron-watcher.d.ts +23 -0
- package/dist/cron/cron-watcher.d.ts.map +1 -0
- package/dist/cron/resource-limiter.d.ts +9 -0
- package/dist/cron/resource-limiter.d.ts.map +1 -0
- package/dist/cron/schedule-command-service.d.ts +10 -0
- package/dist/cron/schedule-command-service.d.ts.map +1 -0
- package/dist/cron/schedule-service.d.ts +100 -0
- package/dist/cron/schedule-service.d.ts.map +1 -0
- package/dist/cron/scheduler.d.ts +68 -0
- package/dist/cron/scheduler.d.ts.map +1 -0
- package/dist/cron/sqlite-cron-store.d.ts +230 -0
- package/dist/cron/sqlite-cron-store.d.ts.map +1 -0
- package/dist/cron/sqlite-schedule-store.d.ts +52 -0
- package/dist/cron/sqlite-schedule-store.d.ts.map +1 -0
- package/dist/extensions/config/agent-config-loader.d.ts +4 -3
- package/dist/extensions/config/agent-config-loader.d.ts.map +1 -1
- package/dist/extensions/config/runtime-commands.d.ts +1 -0
- package/dist/extensions/config/runtime-commands.d.ts.map +1 -1
- package/dist/extensions/config/user-instruction-config-loader.d.ts +1 -0
- package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -1
- package/dist/extensions/context/agentic-compaction.d.ts +2 -2
- package/dist/extensions/context/agentic-compaction.d.ts.map +1 -1
- package/dist/extensions/context/compaction-shared.d.ts +5 -4
- package/dist/extensions/context/compaction-shared.d.ts.map +1 -1
- package/dist/extensions/context/compaction.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-config-loader.d.ts +15 -2
- package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-loader.d.ts +13 -7
- package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-module-import.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-sandbox.d.ts +21 -2
- package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-targeting.d.ts +7 -0
- package/dist/extensions/plugin/plugin-targeting.d.ts.map +1 -0
- package/dist/extensions/plugin-sandbox-bootstrap.js +237 -276
- package/dist/extensions/tools/constants.d.ts +1 -0
- package/dist/extensions/tools/constants.d.ts.map +1 -1
- package/dist/extensions/tools/definitions.d.ts +3 -4
- package/dist/extensions/tools/definitions.d.ts.map +1 -1
- package/dist/extensions/tools/executors/apply-patch.d.ts +3 -1
- package/dist/extensions/tools/executors/apply-patch.d.ts.map +1 -1
- package/dist/extensions/tools/executors/editor.d.ts.map +1 -1
- package/dist/extensions/tools/executors/search.d.ts +1 -1
- package/dist/extensions/tools/executors/search.d.ts.map +1 -1
- package/dist/extensions/tools/helpers.d.ts +1 -0
- package/dist/extensions/tools/helpers.d.ts.map +1 -1
- package/dist/extensions/tools/index.d.ts +3 -2
- package/dist/extensions/tools/index.d.ts.map +1 -1
- package/dist/extensions/tools/presets.d.ts +27 -44
- package/dist/extensions/tools/presets.d.ts.map +1 -1
- package/dist/extensions/tools/runtime.d.ts +25 -0
- package/dist/extensions/tools/runtime.d.ts.map +1 -0
- package/dist/extensions/tools/schemas.d.ts +25 -3
- package/dist/extensions/tools/schemas.d.ts.map +1 -1
- package/dist/extensions/tools/team/delegated-agent.d.ts +2 -2
- package/dist/extensions/tools/team/delegated-agent.d.ts.map +1 -1
- package/dist/extensions/tools/team/multi-agent.d.ts +7 -3
- package/dist/extensions/tools/team/multi-agent.d.ts.map +1 -1
- package/dist/extensions/tools/team/team-tools.d.ts +1 -0
- package/dist/extensions/tools/team/team-tools.d.ts.map +1 -1
- package/dist/extensions/tools/types.d.ts +0 -5
- package/dist/extensions/tools/types.d.ts.map +1 -1
- package/dist/hooks/hook-bridge.d.ts +118 -0
- package/dist/hooks/hook-bridge.d.ts.map +1 -0
- package/dist/hooks/hook-file-hooks.d.ts +6 -2
- package/dist/hooks/hook-file-hooks.d.ts.map +1 -1
- package/dist/hooks/hook-registry.d.ts +16 -0
- package/dist/hooks/hook-registry.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/subprocess.d.ts +8 -1
- package/dist/hooks/subprocess.d.ts.map +1 -1
- package/dist/hub/browser-websocket.d.ts +18 -0
- package/dist/hub/browser-websocket.d.ts.map +1 -0
- package/dist/hub/client.d.ts +51 -0
- package/dist/hub/client.d.ts.map +1 -0
- package/dist/hub/connect.d.ts +15 -0
- package/dist/hub/connect.d.ts.map +1 -0
- package/dist/hub/daemon-entry.d.ts +2 -0
- package/dist/hub/daemon-entry.d.ts.map +1 -0
- package/dist/hub/daemon-entry.js +1305 -0
- package/dist/hub/daemon.d.ts +5 -0
- package/dist/hub/daemon.d.ts.map +1 -0
- package/dist/hub/defaults.d.ts +17 -0
- package/dist/hub/defaults.d.ts.map +1 -0
- package/dist/hub/discovery.d.ts +29 -0
- package/dist/hub/discovery.d.ts.map +1 -0
- package/dist/hub/index.d.ts +15 -0
- package/dist/hub/index.d.ts.map +1 -0
- package/dist/hub/index.js +1294 -0
- package/dist/hub/native-transport.d.ts +17 -0
- package/dist/hub/native-transport.d.ts.map +1 -0
- package/dist/hub/runtime-handlers.d.ts +11 -0
- package/dist/hub/runtime-handlers.d.ts.map +1 -0
- package/dist/hub/server.d.ts +104 -0
- package/dist/hub/server.d.ts.map +1 -0
- package/dist/hub/session-client.d.ts +90 -0
- package/dist/hub/session-client.d.ts.map +1 -0
- package/dist/hub/start-shared-server.d.ts +19 -0
- package/dist/hub/start-shared-server.d.ts.map +1 -0
- package/dist/hub/transport.d.ts +8 -0
- package/dist/hub/transport.d.ts.map +1 -0
- package/dist/hub/ui-client.d.ts +45 -0
- package/dist/hub/ui-client.d.ts.map +1 -0
- package/dist/hub/workspace.d.ts +4 -0
- package/dist/hub/workspace.d.ts.map +1 -0
- package/dist/index.d.ts +29 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +782 -471
- package/dist/llms/cline-recommended-models.d.ts +20 -0
- package/dist/llms/cline-recommended-models.d.ts.map +1 -0
- package/dist/llms/configured-provider-registry.d.ts +28 -0
- package/dist/llms/configured-provider-registry.d.ts.map +1 -0
- package/dist/llms/handler-factory.d.ts +16 -0
- package/dist/llms/handler-factory.d.ts.map +1 -0
- package/dist/llms/provider-defaults.d.ts +27 -0
- package/dist/llms/provider-defaults.d.ts.map +1 -0
- package/dist/llms/provider-settings.d.ts +245 -0
- package/dist/llms/provider-settings.d.ts.map +1 -0
- package/dist/llms/runtime-config.d.ts +4 -0
- package/dist/llms/runtime-config.d.ts.map +1 -0
- package/dist/llms/runtime-registry.d.ts +20 -0
- package/dist/llms/runtime-registry.d.ts.map +1 -0
- package/dist/llms/runtime-types.d.ts +85 -0
- package/dist/llms/runtime-types.d.ts.map +1 -0
- package/dist/runtime/agent-config-adapter.d.ts +148 -0
- package/dist/runtime/agent-config-adapter.d.ts.map +1 -0
- package/dist/runtime/agent-runtime-config-builder.d.ts +96 -0
- package/dist/runtime/agent-runtime-config-builder.d.ts.map +1 -0
- package/dist/runtime/history.d.ts +6 -0
- package/dist/runtime/history.d.ts.map +1 -1
- package/dist/runtime/host.d.ts +1 -2
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/loop-detection.d.ts +59 -0
- package/dist/runtime/loop-detection.d.ts.map +1 -0
- package/dist/runtime/mistake-tracker.d.ts +69 -0
- package/dist/runtime/mistake-tracker.d.ts.map +1 -0
- package/dist/runtime/rules.d.ts +1 -0
- package/dist/runtime/rules.d.ts.map +1 -1
- package/dist/runtime/runtime-builder.d.ts.map +1 -1
- package/dist/runtime/runtime-event-adapter.d.ts +102 -0
- package/dist/runtime/runtime-event-adapter.d.ts.map +1 -0
- package/dist/runtime/runtime-host.d.ts +49 -26
- package/dist/runtime/runtime-host.d.ts.map +1 -1
- package/dist/runtime/runtime-oauth-token-manager.d.ts.map +1 -1
- package/dist/runtime/session-runtime-orchestrator.d.ts +261 -0
- package/dist/runtime/session-runtime-orchestrator.d.ts.map +1 -0
- package/dist/runtime/session-runtime.d.ts +16 -21
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/runtime/user-input-builder.d.ts +24 -0
- package/dist/runtime/user-input-builder.d.ts.map +1 -0
- package/dist/services/global-settings.d.ts +12 -0
- package/dist/services/global-settings.d.ts.map +1 -0
- package/dist/services/index.js +28 -0
- package/dist/services/local-runtime-bootstrap.d.ts +9 -3
- package/dist/services/local-runtime-bootstrap.d.ts.map +1 -1
- package/dist/services/plugin-tools.d.ts +16 -0
- package/dist/services/plugin-tools.d.ts.map +1 -0
- package/dist/services/providers/local-provider-registry.d.ts +199 -23
- package/dist/services/providers/local-provider-registry.d.ts.map +1 -1
- package/dist/services/providers/local-provider-service.d.ts +15 -13
- package/dist/services/providers/local-provider-service.d.ts.map +1 -1
- package/dist/services/session-data.d.ts +1 -1
- package/dist/services/session-data.d.ts.map +1 -1
- package/dist/services/session-telemetry.d.ts +7 -2
- package/dist/services/session-telemetry.d.ts.map +1 -1
- package/dist/services/storage/file-team-store.d.ts.map +1 -1
- package/dist/services/storage/provider-settings-legacy-migration.d.ts +1 -1
- package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +1 -1
- package/dist/services/storage/provider-settings-manager.d.ts +1 -0
- package/dist/services/storage/provider-settings-manager.d.ts.map +1 -1
- package/dist/services/storage/sqlite-team-store.d.ts.map +1 -1
- package/dist/services/workspace-manifest.d.ts +11 -0
- package/dist/services/workspace-manifest.d.ts.map +1 -1
- package/dist/session/conversation-store.d.ts +30 -0
- package/dist/session/conversation-store.d.ts.map +1 -0
- package/dist/session/message-builder.d.ts +65 -0
- package/dist/session/message-builder.d.ts.map +1 -0
- package/dist/session/persistence-service.d.ts +11 -23
- package/dist/session/persistence-service.d.ts.map +1 -1
- package/dist/session/session-manifest-store.d.ts +22 -0
- package/dist/session/session-manifest-store.d.ts.map +1 -0
- package/dist/session/session-manifest.d.ts +1 -1
- package/dist/session/session-row.d.ts +93 -0
- package/dist/session/session-row.d.ts.map +1 -0
- package/dist/session/session-service.d.ts +2 -102
- package/dist/session/session-service.d.ts.map +1 -1
- package/dist/session/subagent-session-manager.d.ts +36 -0
- package/dist/session/subagent-session-manager.d.ts.map +1 -0
- package/dist/session/team-persistence-store.d.ts +24 -0
- package/dist/session/team-persistence-store.d.ts.map +1 -0
- package/dist/transports/hub.d.ts +58 -0
- package/dist/transports/hub.d.ts.map +1 -0
- package/dist/transports/local.d.ts +23 -9
- package/dist/transports/local.d.ts.map +1 -1
- package/dist/transports/remote.d.ts +10 -0
- package/dist/transports/remote.d.ts.map +1 -0
- package/dist/transports/runtime-host-support.d.ts +3 -2
- package/dist/transports/runtime-host-support.d.ts.map +1 -1
- package/dist/types/chat-schema.d.ts +15 -17
- package/dist/types/chat-schema.d.ts.map +1 -1
- package/dist/types/config.d.ts +17 -7
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/events.d.ts +7 -6
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/provider-settings.d.ts +4 -5
- package/dist/types/provider-settings.d.ts.map +1 -1
- package/dist/types/session.d.ts +7 -3
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types.d.ts +11 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -6
- package/src/ClineCore.ts +757 -44
- package/src/account/cline-account-service.ts +44 -6
- package/src/account/index.ts +3 -3
- package/src/account/rpc.ts +12 -12
- package/src/cron/cron-event-ingress.ts +357 -0
- package/src/cron/cron-materializer.ts +97 -0
- package/src/cron/cron-reconciler.ts +241 -0
- package/src/cron/cron-report-writer.ts +153 -0
- package/src/cron/cron-runner.ts +495 -0
- package/src/cron/cron-schema.ts +127 -0
- package/src/cron/cron-service.ts +163 -0
- package/src/cron/cron-spec-parser.ts +489 -0
- package/src/cron/cron-watcher.ts +102 -0
- package/src/cron/index.ts +15 -0
- package/src/cron/resource-limiter.ts +46 -0
- package/src/cron/schedule-command-service.ts +193 -0
- package/src/cron/schedule-service.ts +703 -0
- package/src/cron/scheduler.ts +772 -0
- package/src/cron/sqlite-cron-store.ts +1286 -0
- package/src/cron/sqlite-schedule-store.ts +708 -0
- package/src/extensions/config/agent-config-loader.ts +17 -7
- package/src/extensions/config/runtime-commands.ts +6 -0
- package/src/extensions/config/user-instruction-config-loader.ts +1 -0
- package/src/extensions/context/agentic-compaction.ts +3 -3
- package/src/extensions/context/basic-compaction.ts +2 -2
- package/src/extensions/context/compaction-shared.ts +5 -4
- package/src/extensions/context/compaction.ts +3 -3
- package/src/extensions/plugin/plugin-config-loader.ts +37 -2
- package/src/extensions/plugin/plugin-loader.ts +69 -9
- package/src/extensions/plugin/plugin-module-import.ts +0 -2
- package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +243 -39
- package/src/extensions/plugin/plugin-sandbox.ts +173 -29
- package/src/extensions/plugin/plugin-targeting.ts +32 -0
- package/src/extensions/tools/constants.ts +2 -0
- package/src/extensions/tools/definitions.ts +61 -71
- package/src/extensions/tools/executors/apply-patch.ts +69 -80
- package/src/extensions/tools/executors/editor.ts +4 -3
- package/src/extensions/tools/executors/search.ts +195 -3
- package/src/extensions/tools/helpers.ts +24 -0
- package/src/extensions/tools/index.ts +11 -2
- package/src/extensions/tools/presets.ts +32 -47
- package/src/extensions/tools/runtime.ts +261 -0
- package/src/extensions/tools/schemas.ts +17 -20
- package/src/extensions/tools/team/delegated-agent.ts +8 -3
- package/src/extensions/tools/team/multi-agent.ts +135 -19
- package/src/extensions/tools/team/team-tools.ts +172 -91
- package/src/extensions/tools/types.ts +0 -6
- package/src/hooks/hook-bridge.ts +489 -0
- package/src/hooks/hook-file-hooks.ts +66 -5
- package/src/hooks/hook-registry.ts +257 -0
- package/src/hooks/index.ts +0 -7
- package/src/hooks/subprocess-runner.ts +1 -1
- package/src/hooks/subprocess.ts +9 -0
- package/src/hub/browser-websocket.ts +159 -0
- package/src/hub/client.ts +633 -0
- package/src/hub/connect.ts +156 -0
- package/src/hub/daemon-entry.ts +122 -0
- package/src/hub/daemon.ts +284 -0
- package/src/hub/defaults.ts +70 -0
- package/src/hub/discovery.ts +247 -0
- package/src/hub/index.ts +14 -0
- package/src/hub/native-transport.ts +31 -0
- package/src/hub/runtime-handlers.ts +141 -0
- package/src/hub/server.ts +2317 -0
- package/src/hub/session-client.ts +502 -0
- package/src/hub/start-shared-server.ts +61 -0
- package/src/hub/transport.ts +14 -0
- package/src/hub/ui-client.ts +126 -0
- package/src/hub/workspace.ts +19 -0
- package/src/index.ts +169 -68
- package/src/llms/cline-recommended-models.ts +167 -0
- package/src/llms/configured-provider-registry.ts +193 -0
- package/src/llms/handler-factory.ts +56 -0
- package/src/llms/provider-defaults.ts +653 -0
- package/src/llms/provider-settings.ts +310 -0
- package/src/llms/runtime-config.ts +43 -0
- package/src/llms/runtime-registry.ts +172 -0
- package/src/llms/runtime-types.ts +121 -0
- package/src/runtime/agent-config-adapter.ts +636 -0
- package/src/runtime/agent-runtime-config-builder.ts +205 -0
- package/src/runtime/error-feedback.ts +142 -0
- package/src/runtime/history.ts +137 -0
- package/src/runtime/host.ts +127 -267
- package/src/runtime/index.ts +1 -0
- package/src/runtime/loop-detection.ts +162 -0
- package/src/runtime/mistake-tracker.ts +221 -0
- package/src/runtime/rules.ts +12 -0
- package/src/runtime/runtime-builder.ts +85 -13
- package/src/runtime/runtime-event-adapter.ts +412 -0
- package/src/runtime/runtime-host.ts +134 -62
- package/src/runtime/runtime-oauth-token-manager.ts +11 -15
- package/src/runtime/session-runtime-orchestrator.ts +1253 -0
- package/src/runtime/session-runtime.ts +16 -26
- package/src/runtime/user-input-builder.ts +167 -0
- package/src/services/global-settings.ts +122 -0
- package/src/services/local-runtime-bootstrap.ts +175 -31
- package/src/services/plugin-tools.ts +86 -0
- package/src/services/providers/local-provider-registry.ts +277 -61
- package/src/services/providers/local-provider-service.ts +109 -44
- package/src/services/session-data.ts +18 -10
- package/src/services/session-telemetry.ts +6 -15
- package/src/services/storage/file-team-store.ts +1 -5
- package/src/services/storage/provider-settings-legacy-migration.ts +14 -51
- package/src/services/storage/provider-settings-manager.ts +17 -2
- package/src/services/storage/sqlite-team-store.ts +1 -5
- package/src/services/workspace-manifest.ts +18 -0
- package/src/session/conversation-store.ts +77 -0
- package/src/session/file-session-service.ts +1 -1
- package/src/session/index.ts +6 -27
- package/src/session/message-builder.ts +941 -0
- package/src/session/persistence-service.ts +119 -504
- package/src/session/session-manifest-store.ts +158 -0
- package/src/session/session-row.ts +199 -0
- package/src/session/session-service.ts +17 -376
- package/src/session/session-team-coordination.ts +1 -1
- package/src/session/subagent-session-manager.ts +397 -0
- package/src/session/team-persistence-store.ts +176 -0
- package/src/transports/hub.ts +1081 -0
- package/src/transports/local.ts +419 -93
- package/src/transports/remote.ts +27 -0
- package/src/transports/runtime-host-support.ts +63 -9
- package/src/types/chat-schema.ts +4 -5
- package/src/types/config.ts +17 -7
- package/src/types/events.ts +8 -6
- package/src/types/index.ts +3 -0
- package/src/types/provider-settings.ts +18 -7
- package/src/types/session.ts +7 -6
- package/src/types.ts +42 -2
- package/dist/hooks/persistent.d.ts +0 -64
- package/dist/hooks/persistent.d.ts.map +0 -1
- package/dist/runtime/rpc-runtime-ensure.d.ts +0 -65
- package/dist/runtime/rpc-runtime-ensure.d.ts.map +0 -1
- package/dist/runtime/rpc-spawn-lease.d.ts +0 -8
- package/dist/runtime/rpc-spawn-lease.d.ts.map +0 -1
- package/dist/services/telemetry/index.js +0 -15
- package/dist/session/rpc-session-service.d.ts +0 -16
- package/dist/session/rpc-session-service.d.ts.map +0 -1
- package/dist/session/sqlite-rpc-session-backend.d.ts +0 -31
- package/dist/session/sqlite-rpc-session-backend.d.ts.map +0 -1
- package/dist/transports/rpc.d.ts +0 -51
- package/dist/transports/rpc.d.ts.map +0 -1
- package/src/ClineCore.test.ts +0 -226
- package/src/account/cline-account-service.test.ts +0 -185
- package/src/account/featurebase-token.test.ts +0 -175
- package/src/account/rpc.test.ts +0 -63
- package/src/auth/bounded-ttl-cache.test.ts +0 -38
- package/src/auth/client.test.ts +0 -69
- package/src/auth/cline.test.ts +0 -267
- package/src/auth/codex.test.ts +0 -170
- package/src/auth/oca.test.ts +0 -340
- package/src/auth/server.test.ts +0 -287
- package/src/auth/utils.test.ts +0 -128
- package/src/extensions/config/agent-config-loader.test.ts +0 -236
- package/src/extensions/config/hooks-config-loader.test.ts +0 -20
- package/src/extensions/config/runtime-commands.test.ts +0 -115
- package/src/extensions/config/unified-config-file-watcher.test.ts +0 -196
- package/src/extensions/config/user-instruction-config-loader.test.ts +0 -246
- package/src/extensions/context/compaction.test.ts +0 -483
- package/src/extensions/mcp/config-loader.test.ts +0 -238
- package/src/extensions/mcp/manager.test.ts +0 -105
- package/src/extensions/plugin/plugin-config-loader.test.ts +0 -184
- package/src/extensions/plugin/plugin-loader.test.ts +0 -292
- package/src/extensions/plugin/plugin-sandbox.test.ts +0 -423
- package/src/extensions/tools/definitions.test.ts +0 -780
- package/src/extensions/tools/executors/bash.test.ts +0 -87
- package/src/extensions/tools/executors/editor.test.ts +0 -35
- package/src/extensions/tools/executors/file-read.test.ts +0 -125
- package/src/extensions/tools/model-tool-routing.test.ts +0 -86
- package/src/extensions/tools/presets.test.ts +0 -70
- package/src/extensions/tools/team/multi-agent.lifecycle.test.ts +0 -455
- package/src/extensions/tools/team/spawn-agent-tool.test.ts +0 -381
- package/src/extensions/tools/team/team-tools.test.ts +0 -918
- package/src/hooks/checkpoint-hooks.test.ts +0 -168
- package/src/hooks/hook-file-hooks.test.ts +0 -311
- package/src/hooks/persistent.ts +0 -661
- package/src/runtime/history.test.ts +0 -114
- package/src/runtime/host.test.ts +0 -230
- package/src/runtime/rpc-runtime-ensure.test.ts +0 -123
- package/src/runtime/rpc-runtime-ensure.ts +0 -659
- package/src/runtime/rpc-spawn-lease.test.ts +0 -81
- package/src/runtime/rpc-spawn-lease.ts +0 -156
- package/src/runtime/runtime-builder.team-persistence.test.ts +0 -245
- package/src/runtime/runtime-builder.test.ts +0 -615
- package/src/runtime/runtime-oauth-token-manager.test.ts +0 -137
- package/src/runtime/runtime-parity.test.ts +0 -143
- package/src/services/providers/local-provider-service.test.ts +0 -1062
- package/src/services/session-data.test.ts +0 -160
- package/src/services/storage/provider-settings-legacy-migration.test.ts +0 -424
- package/src/services/storage/provider-settings-manager.test.ts +0 -191
- package/src/services/telemetry/OpenTelemetryAdapter.test.ts +0 -157
- package/src/services/telemetry/OpenTelemetryProvider.test.ts +0 -326
- package/src/services/telemetry/TelemetryLoggerSink.test.ts +0 -42
- package/src/services/telemetry/TelemetryService.test.ts +0 -134
- package/src/services/telemetry/distinct-id.test.ts +0 -57
- package/src/services/workspace/file-indexer.d.ts +0 -11
- package/src/services/workspace/file-indexer.test.ts +0 -156
- package/src/services/workspace/mention-enricher.test.ts +0 -106
- package/src/session/persistence-service.test.ts +0 -300
- package/src/session/rpc-session-service.ts +0 -114
- package/src/session/session-service.team-persistence.test.ts +0 -48
- package/src/session/sqlite-rpc-session-backend.ts +0 -301
- package/src/transports/local.e2e.test.ts +0 -380
- package/src/transports/local.test.ts +0 -2559
- package/src/transports/rpc.test.ts +0 -82
- package/src/transports/rpc.ts +0 -665
package/src/runtime/host.ts
CHANGED
|
@@ -1,42 +1,18 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { closeSync, existsSync, mkdirSync, openSync } from "node:fs";
|
|
3
|
-
import { dirname, join, resolve } from "node:path";
|
|
4
|
-
import { getRpcServerDefaultAddress, getRpcServerHealth } from "@clinebot/rpc";
|
|
5
|
-
import {
|
|
6
|
-
augmentNodeCommandForDebug,
|
|
7
|
-
withResolvedClineBuildEnv,
|
|
8
|
-
} from "@clinebot/shared";
|
|
9
|
-
import {
|
|
10
|
-
resolveClineDataDir,
|
|
11
|
-
resolveSessionDataDir,
|
|
12
|
-
} from "@clinebot/shared/storage";
|
|
13
1
|
import type { ClineCoreOptions } from "../ClineCore";
|
|
2
|
+
import {
|
|
3
|
+
ensureCompatibleLocalHubUrl,
|
|
4
|
+
resolveCompatibleLocalHubUrl,
|
|
5
|
+
} from "../hub/client";
|
|
6
|
+
import { prewarmDetachedHubServer } from "../hub/daemon";
|
|
14
7
|
import { SqliteSessionStore } from "../services/storage/sqlite-session-store";
|
|
15
8
|
import { resolveCoreDistinctId } from "../services/telemetry/distinct-id";
|
|
16
9
|
import { FileSessionService } from "../session/file-session-service";
|
|
17
|
-
import { RpcCoreSessionService } from "../session/rpc-session-service";
|
|
18
10
|
import { CoreSessionService } from "../session/session-service";
|
|
11
|
+
import { HubRuntimeHost } from "../transports/hub";
|
|
19
12
|
import { LocalRuntimeHost } from "../transports/local";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
ensureRpcRuntimeAddress,
|
|
23
|
-
RPC_BUILD_ID_ENV,
|
|
24
|
-
RPC_DISCOVERY_PATH_ENV,
|
|
25
|
-
RPC_OWNER_ID_ENV,
|
|
26
|
-
RPC_STARTUP_LOCK_BYPASS_ENV,
|
|
27
|
-
type RpcOwnerContext,
|
|
28
|
-
resolveRpcOwnerContext,
|
|
29
|
-
} from "./rpc-runtime-ensure";
|
|
30
|
-
import { tryAcquireRpcSpawnLease } from "./rpc-spawn-lease";
|
|
13
|
+
import { RemoteRuntimeHost } from "../transports/remote";
|
|
31
14
|
import type { RuntimeHost, RuntimeHostMode } from "./runtime-host";
|
|
32
15
|
|
|
33
|
-
const DEFAULT_RPC_ADDRESS =
|
|
34
|
-
process.env.CLINE_RPC_ADDRESS?.trim() || getRpcServerDefaultAddress();
|
|
35
|
-
|
|
36
|
-
function requiresLocalRuntimeHost(options: ClineCoreOptions): boolean {
|
|
37
|
-
return !!options.defaultToolExecutors || !!options.teamToolsFactory;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
16
|
function resolveConfiguredBackendMode(
|
|
41
17
|
options: ClineCoreOptions,
|
|
42
18
|
): RuntimeHostMode {
|
|
@@ -47,151 +23,41 @@ function resolveConfiguredBackendMode(
|
|
|
47
23
|
return "local";
|
|
48
24
|
}
|
|
49
25
|
const raw = process.env.CLINE_SESSION_BACKEND_MODE?.trim().toLowerCase();
|
|
50
|
-
if (raw === "
|
|
26
|
+
if (raw === "local" || raw === "hub" || raw === "remote") {
|
|
51
27
|
return raw;
|
|
52
28
|
}
|
|
53
29
|
return "auto";
|
|
54
30
|
}
|
|
55
31
|
|
|
56
|
-
export type SessionBackend =
|
|
57
|
-
| RpcCoreSessionService
|
|
58
|
-
| CoreSessionService
|
|
59
|
-
| FileSessionService;
|
|
32
|
+
export type SessionBackend = CoreSessionService | FileSessionService;
|
|
60
33
|
|
|
61
34
|
let cachedBackend: SessionBackend | undefined;
|
|
62
35
|
let backendInitPromise: Promise<SessionBackend> | undefined;
|
|
63
36
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const service = backend as SessionBackend & {
|
|
68
|
-
reconcileDeadSessions?: (limit?: number) => Promise<number>;
|
|
69
|
-
};
|
|
70
|
-
await service.reconcileDeadSessions?.().catch(() => {});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function openRpcSidecarLogFile(): { fd: number; logPath: string } | undefined {
|
|
74
|
-
try {
|
|
75
|
-
const logPath = join(resolveClineDataDir(), "logs", "rpc-sidecar.log");
|
|
76
|
-
mkdirSync(dirname(logPath), { recursive: true });
|
|
77
|
-
return { fd: openSync(logPath, "a"), logPath };
|
|
78
|
-
} catch {
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function startRpcServerInBackground(
|
|
84
|
-
address: string,
|
|
85
|
-
owner: RpcOwnerContext,
|
|
86
|
-
logger?: ClineCoreOptions["logger"],
|
|
37
|
+
function prewarmLocalHubIfNeeded(
|
|
38
|
+
configuredMode: RuntimeHostMode,
|
|
39
|
+
options: ClineCoreOptions,
|
|
87
40
|
): void {
|
|
88
|
-
|
|
89
|
-
if (!lease) {
|
|
90
|
-
logger?.log("RPC sidecar spawn skipped", {
|
|
91
|
-
address,
|
|
92
|
-
reason: "spawn_lease_unavailable",
|
|
93
|
-
severity: "warn",
|
|
94
|
-
});
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const launcher = process.execPath;
|
|
98
|
-
const entryArg = process.argv[1]?.trim();
|
|
99
|
-
if (!entryArg) {
|
|
100
|
-
lease.release();
|
|
101
|
-
logger?.error?.("RPC sidecar spawn aborted", {
|
|
102
|
-
address,
|
|
103
|
-
reason: "missing_process_entry_arg",
|
|
104
|
-
});
|
|
41
|
+
if (configuredMode !== "auto" && configuredMode !== "hub") {
|
|
105
42
|
return;
|
|
106
43
|
}
|
|
107
|
-
|
|
108
|
-
if (!existsSync(entry)) {
|
|
109
|
-
lease.release();
|
|
110
|
-
logger?.error?.("RPC sidecar spawn aborted", {
|
|
111
|
-
address,
|
|
112
|
-
reason: "entrypoint_missing",
|
|
113
|
-
entryPath: entry,
|
|
114
|
-
});
|
|
44
|
+
if (options.hub?.endpoint?.trim()) {
|
|
115
45
|
return;
|
|
116
46
|
}
|
|
117
|
-
|
|
118
|
-
|
|
47
|
+
prewarmDetachedHubServer(
|
|
48
|
+
options.hub?.workspaceRoot?.trim() ||
|
|
49
|
+
options.hub?.cwd?.trim() ||
|
|
50
|
+
process.cwd(),
|
|
119
51
|
);
|
|
120
|
-
const command = augmentNodeCommandForDebug(
|
|
121
|
-
[
|
|
122
|
-
launcher,
|
|
123
|
-
...(conditionsArg ? [conditionsArg] : []),
|
|
124
|
-
entry,
|
|
125
|
-
"rpc",
|
|
126
|
-
"start",
|
|
127
|
-
"--address",
|
|
128
|
-
address,
|
|
129
|
-
],
|
|
130
|
-
{ debugRole: "rpc" },
|
|
131
|
-
);
|
|
132
|
-
const sidecarLog = openRpcSidecarLogFile();
|
|
133
|
-
logger?.log("Launching detached RPC sidecar", {
|
|
134
|
-
address,
|
|
135
|
-
command: command.join(" "),
|
|
136
|
-
commandArgs: command.slice(1),
|
|
137
|
-
executable: command[0] ?? launcher,
|
|
138
|
-
entryPath: entry,
|
|
139
|
-
cwd: process.cwd(),
|
|
140
|
-
logPath: sidecarLog?.logPath,
|
|
141
|
-
});
|
|
142
|
-
try {
|
|
143
|
-
const child = spawn(command[0] ?? launcher, command.slice(1), {
|
|
144
|
-
detached: true,
|
|
145
|
-
stdio: sidecarLog ? ["ignore", sidecarLog.fd, sidecarLog.fd] : "ignore",
|
|
146
|
-
env: {
|
|
147
|
-
...withResolvedClineBuildEnv(process.env),
|
|
148
|
-
[RPC_STARTUP_LOCK_BYPASS_ENV]: "1",
|
|
149
|
-
[RPC_OWNER_ID_ENV]: owner.ownerId,
|
|
150
|
-
[RPC_BUILD_ID_ENV]: owner.buildId,
|
|
151
|
-
[RPC_DISCOVERY_PATH_ENV]: owner.discoveryPath,
|
|
152
|
-
CLINE_NO_INTERACTIVE: "1",
|
|
153
|
-
},
|
|
154
|
-
cwd: process.cwd(),
|
|
155
|
-
});
|
|
156
|
-
logger?.log("Detached RPC sidecar spawned", {
|
|
157
|
-
address,
|
|
158
|
-
childPid: child.pid,
|
|
159
|
-
logPath: sidecarLog?.logPath,
|
|
160
|
-
});
|
|
161
|
-
child.unref();
|
|
162
|
-
setTimeout(() => lease.release(), 10_000).unref();
|
|
163
|
-
} catch (error) {
|
|
164
|
-
lease.release();
|
|
165
|
-
logger?.error?.("RPC sidecar spawn failed", {
|
|
166
|
-
address,
|
|
167
|
-
logPath: sidecarLog?.logPath,
|
|
168
|
-
error,
|
|
169
|
-
});
|
|
170
|
-
throw error;
|
|
171
|
-
} finally {
|
|
172
|
-
if (sidecarLog) {
|
|
173
|
-
closeSync(sidecarLog.fd);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
52
|
}
|
|
177
53
|
|
|
178
|
-
async function
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return undefined;
|
|
186
|
-
}
|
|
187
|
-
return new RpcCoreSessionService({
|
|
188
|
-
address,
|
|
189
|
-
sessionsDir: resolveSessionDataDir(),
|
|
190
|
-
messagesArtifactUploader: options.messagesArtifactUploader,
|
|
191
|
-
});
|
|
192
|
-
} catch {
|
|
193
|
-
return undefined;
|
|
194
|
-
}
|
|
54
|
+
async function reconcileDeadSessionsIfSupported(
|
|
55
|
+
backend: SessionBackend,
|
|
56
|
+
): Promise<void> {
|
|
57
|
+
const service = backend as SessionBackend & {
|
|
58
|
+
reconcileDeadSessions?: (limit?: number) => Promise<number>;
|
|
59
|
+
};
|
|
60
|
+
await service.reconcileDeadSessions?.().catch(() => {});
|
|
195
61
|
}
|
|
196
62
|
|
|
197
63
|
function createLocalBackend(options: ClineCoreOptions): SessionBackend {
|
|
@@ -202,7 +68,7 @@ function createLocalBackend(options: ClineCoreOptions): SessionBackend {
|
|
|
202
68
|
messagesArtifactUploader: options.messagesArtifactUploader,
|
|
203
69
|
});
|
|
204
70
|
} catch {
|
|
205
|
-
// Fallback to file-based session service if SQLite is unavailable
|
|
71
|
+
// Fallback to file-based session service if SQLite is unavailable.
|
|
206
72
|
options.telemetry?.capture({
|
|
207
73
|
event: "session_backend_fallback",
|
|
208
74
|
properties: {
|
|
@@ -216,6 +82,23 @@ function createLocalBackend(options: ClineCoreOptions): SessionBackend {
|
|
|
216
82
|
}
|
|
217
83
|
}
|
|
218
84
|
|
|
85
|
+
function createLocalRuntimeHost(
|
|
86
|
+
options: ClineCoreOptions,
|
|
87
|
+
distinctId: string,
|
|
88
|
+
backend?: SessionBackend,
|
|
89
|
+
): LocalRuntimeHost {
|
|
90
|
+
return new LocalRuntimeHost({
|
|
91
|
+
sessionService:
|
|
92
|
+
backend ?? options.sessionService ?? createLocalBackend(options),
|
|
93
|
+
defaultToolExecutors: options.defaultToolExecutors,
|
|
94
|
+
telemetry: options.telemetry,
|
|
95
|
+
toolPolicies: options.toolPolicies,
|
|
96
|
+
requestToolApproval: options.requestToolApproval,
|
|
97
|
+
distinctId,
|
|
98
|
+
fetch: options.fetch,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
219
102
|
export async function resolveSessionBackend(
|
|
220
103
|
options: ClineCoreOptions,
|
|
221
104
|
): Promise<SessionBackend> {
|
|
@@ -226,83 +109,7 @@ export async function resolveSessionBackend(
|
|
|
226
109
|
return await backendInitPromise;
|
|
227
110
|
}
|
|
228
111
|
|
|
229
|
-
const mode = resolveConfiguredBackendMode(options);
|
|
230
|
-
const requestedAddress = options.rpc?.address?.trim() || DEFAULT_RPC_ADDRESS;
|
|
231
|
-
const attempts = Math.max(1, options.rpc?.connectAttempts ?? 5);
|
|
232
|
-
const delayMs = Math.max(0, options.rpc?.connectDelayMs ?? 100);
|
|
233
|
-
const autoStartRpc = options.rpc?.autoStart !== false;
|
|
234
|
-
const logger = options.logger;
|
|
235
|
-
|
|
236
112
|
backendInitPromise = (async () => {
|
|
237
|
-
if (mode === "local") {
|
|
238
|
-
cachedBackend = createLocalBackend(options);
|
|
239
|
-
await reconcileDeadSessionsIfSupported(cachedBackend);
|
|
240
|
-
return cachedBackend;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
let address = requestedAddress;
|
|
244
|
-
const existingRpcBackend = await tryConnectRpcBackend(address, options);
|
|
245
|
-
if (existingRpcBackend) {
|
|
246
|
-
logger?.log("Connected to existing RPC session backend", { address });
|
|
247
|
-
cachedBackend = existingRpcBackend;
|
|
248
|
-
await reconcileDeadSessionsIfSupported(cachedBackend);
|
|
249
|
-
return cachedBackend;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (mode === "rpc") {
|
|
253
|
-
throw new Error(`RPC backend unavailable at ${address}`);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (autoStartRpc) {
|
|
257
|
-
try {
|
|
258
|
-
logger?.log("Ensuring RPC runtime for auto session backend", {
|
|
259
|
-
address,
|
|
260
|
-
});
|
|
261
|
-
const ensured = await ensureRpcRuntimeAddress(address, {
|
|
262
|
-
resolveOwner: () => resolveRpcOwnerContext({ ownerPrefix: "core" }),
|
|
263
|
-
spawnIfNeeded: (rpcAddress, owner) => {
|
|
264
|
-
startRpcServerInBackground(rpcAddress, owner, logger);
|
|
265
|
-
},
|
|
266
|
-
});
|
|
267
|
-
address = ensured.address;
|
|
268
|
-
logger?.log("RPC runtime ensure completed", {
|
|
269
|
-
requestedAddress,
|
|
270
|
-
address,
|
|
271
|
-
action: ensured.action,
|
|
272
|
-
});
|
|
273
|
-
} catch (error) {
|
|
274
|
-
logger?.error?.("RPC backend auto-start failed", {
|
|
275
|
-
address,
|
|
276
|
-
requestedAddress,
|
|
277
|
-
error,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
282
|
-
const rpcBackend = await tryConnectRpcBackend(address, options);
|
|
283
|
-
if (rpcBackend) {
|
|
284
|
-
logger?.log("Connected to ensured RPC session backend", {
|
|
285
|
-
address,
|
|
286
|
-
attempt: attempt + 1,
|
|
287
|
-
attempts,
|
|
288
|
-
});
|
|
289
|
-
cachedBackend = rpcBackend;
|
|
290
|
-
await reconcileDeadSessionsIfSupported(cachedBackend);
|
|
291
|
-
return cachedBackend;
|
|
292
|
-
}
|
|
293
|
-
if (delayMs > 0) {
|
|
294
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
logger?.log("Falling back to local session backend", {
|
|
300
|
-
requestedAddress,
|
|
301
|
-
address,
|
|
302
|
-
attempts,
|
|
303
|
-
delayMs,
|
|
304
|
-
severity: "warn",
|
|
305
|
-
});
|
|
306
113
|
cachedBackend = createLocalBackend(options);
|
|
307
114
|
await reconcileDeadSessionsIfSupported(cachedBackend);
|
|
308
115
|
return cachedBackend;
|
|
@@ -319,44 +126,97 @@ export async function createRuntimeHost(
|
|
|
319
126
|
const distinctId = resolveCoreDistinctId(options.distinctId);
|
|
320
127
|
options.telemetry?.setDistinctId(distinctId);
|
|
321
128
|
const configuredMode = resolveConfiguredBackendMode(options);
|
|
322
|
-
|
|
323
|
-
|
|
129
|
+
prewarmLocalHubIfNeeded(configuredMode, options);
|
|
130
|
+
if (configuredMode === "remote") {
|
|
131
|
+
const remoteEndpoint = options.remote?.endpoint?.trim();
|
|
132
|
+
if (!remoteEndpoint) {
|
|
324
133
|
throw new Error(
|
|
325
|
-
"
|
|
134
|
+
"Remote runtime mode requires `remote.endpoint` to be configured.",
|
|
326
135
|
);
|
|
327
136
|
}
|
|
328
|
-
options.logger?.log("Using
|
|
329
|
-
|
|
330
|
-
hasDefaultToolExecutors: !!options.defaultToolExecutors,
|
|
331
|
-
hasTeamToolsFactory: !!options.teamToolsFactory,
|
|
137
|
+
options.logger?.log("Using remote runtime host", {
|
|
138
|
+
endpoint: remoteEndpoint,
|
|
332
139
|
});
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
140
|
+
return new RemoteRuntimeHost({
|
|
141
|
+
endpoint: remoteEndpoint,
|
|
142
|
+
authToken: options.remote?.authToken,
|
|
143
|
+
clientType: options.remote?.clientType,
|
|
144
|
+
displayName: options.remote?.displayName,
|
|
145
|
+
workspaceRoot: options.remote?.workspaceRoot,
|
|
146
|
+
cwd: options.remote?.cwd,
|
|
340
147
|
requestToolApproval: options.requestToolApproval,
|
|
341
|
-
distinctId,
|
|
342
148
|
});
|
|
343
149
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
150
|
+
if (configuredMode === "hub") {
|
|
151
|
+
const explicitEndpoint = options.hub?.endpoint?.trim();
|
|
152
|
+
const hubUrl =
|
|
153
|
+
explicitEndpoint ||
|
|
154
|
+
(await ensureCompatibleLocalHubUrl({
|
|
155
|
+
strategy: options.hub?.strategy ?? "require-hub",
|
|
156
|
+
workspaceRoot: options.hub?.workspaceRoot,
|
|
157
|
+
cwd: options.hub?.cwd,
|
|
158
|
+
}));
|
|
159
|
+
if (!hubUrl) {
|
|
160
|
+
throw new Error("No compatible hub runtime is available.");
|
|
161
|
+
}
|
|
162
|
+
options.logger?.log("Using hub runtime host", {
|
|
163
|
+
url: hubUrl,
|
|
164
|
+
explicitEndpoint: explicitEndpoint || undefined,
|
|
165
|
+
});
|
|
166
|
+
return new HubRuntimeHost(
|
|
167
|
+
{
|
|
168
|
+
url: hubUrl,
|
|
169
|
+
authToken: options.hub?.authToken,
|
|
170
|
+
clientType: options.hub?.clientType,
|
|
171
|
+
displayName: options.hub?.displayName,
|
|
172
|
+
requestToolApproval: options.requestToolApproval,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
workspaceRoot: options.hub?.workspaceRoot,
|
|
176
|
+
cwd: options.hub?.cwd,
|
|
177
|
+
},
|
|
351
178
|
);
|
|
352
179
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
180
|
+
if (configuredMode === "auto") {
|
|
181
|
+
const hubUrl = await resolveCompatibleLocalHubUrl({
|
|
182
|
+
endpoint: options.hub?.endpoint,
|
|
183
|
+
strategy: options.hub?.strategy ?? "prefer-hub",
|
|
184
|
+
workspaceRoot: options.hub?.workspaceRoot,
|
|
185
|
+
cwd: options.hub?.cwd,
|
|
186
|
+
});
|
|
187
|
+
if (hubUrl) {
|
|
188
|
+
options.logger?.log("Using discovered local hub runtime host", {
|
|
189
|
+
url: hubUrl,
|
|
190
|
+
});
|
|
191
|
+
const host = new HubRuntimeHost(
|
|
192
|
+
{
|
|
193
|
+
url: hubUrl,
|
|
194
|
+
authToken: options.hub?.authToken,
|
|
195
|
+
clientType: options.hub?.clientType,
|
|
196
|
+
displayName: options.hub?.displayName,
|
|
197
|
+
requestToolApproval: options.requestToolApproval,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
workspaceRoot: options.hub?.workspaceRoot,
|
|
201
|
+
cwd: options.hub?.cwd,
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
try {
|
|
205
|
+
await host.connect();
|
|
206
|
+
return host;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
options.logger?.log("Falling back to local runtime host", {
|
|
209
|
+
reason: "hub_connect_failed",
|
|
210
|
+
severity: "warn",
|
|
211
|
+
error,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
options.logger?.log("Falling back to local runtime host", {
|
|
216
|
+
reason: "compatible_hub_unavailable",
|
|
217
|
+
severity: "warn",
|
|
218
|
+
});
|
|
219
|
+
return createLocalRuntimeHost(options, distinctId);
|
|
220
|
+
}
|
|
221
|
+
return createLocalRuntimeHost(options, distinctId);
|
|
362
222
|
}
|
package/src/runtime/index.ts
CHANGED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repeated tool-call loop detection.
|
|
3
|
+
*
|
|
4
|
+
* @see PLAN.md §3.1 — helpers moved from `packages/agents/src/context/loop-detection.ts`.
|
|
5
|
+
* @see PLAN.md §3.2.3 — public surface of `LoopDetectionTracker`.
|
|
6
|
+
*
|
|
7
|
+
* The pure helpers (`createLoopDetectionState`, `resetLoopDetectionState`,
|
|
8
|
+
* `toolCallSignature`, `checkRepeatedToolCall`) are ported verbatim. The
|
|
9
|
+
* `LoopDetectionTracker` class is a thin wrapper that owns a
|
|
10
|
+
* `LoopDetectionState` and exposes the `inspect()` / `reset()` surface that
|
|
11
|
+
* `SessionRuntime` installs as a `beforeTool` hook per §3.2.3.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { LoopDetectionConfig } from "@clinebot/shared";
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Pure helpers (verbatim port)
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
export interface LoopDetectionState {
|
|
21
|
+
lastToolName: string;
|
|
22
|
+
lastToolSignature: string;
|
|
23
|
+
consecutiveIdenticalCount: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createLoopDetectionState(): LoopDetectionState {
|
|
27
|
+
return {
|
|
28
|
+
lastToolName: "",
|
|
29
|
+
lastToolSignature: "",
|
|
30
|
+
consecutiveIdenticalCount: 0,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function resetLoopDetectionState(state: LoopDetectionState): void {
|
|
35
|
+
state.lastToolName = "";
|
|
36
|
+
state.lastToolSignature = "";
|
|
37
|
+
state.consecutiveIdenticalCount = 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function sortKeys(value: unknown): unknown {
|
|
41
|
+
if (value == null || typeof value !== "object") return value;
|
|
42
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
43
|
+
const sorted: Record<string, unknown> = {};
|
|
44
|
+
for (const key of Object.keys(value as Record<string, unknown>).sort()) {
|
|
45
|
+
sorted[key] = sortKeys((value as Record<string, unknown>)[key]);
|
|
46
|
+
}
|
|
47
|
+
return sorted;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function toolCallSignature(input: unknown): string {
|
|
51
|
+
if (input == null) return "null";
|
|
52
|
+
if (typeof input === "string") return input;
|
|
53
|
+
if (typeof input !== "object") return String(input);
|
|
54
|
+
try {
|
|
55
|
+
return JSON.stringify(sortKeys(input));
|
|
56
|
+
} catch {
|
|
57
|
+
return String(input);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface LoopCheckResult {
|
|
62
|
+
softWarning: boolean;
|
|
63
|
+
hardEscalation: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function checkRepeatedToolCall(
|
|
67
|
+
state: LoopDetectionState,
|
|
68
|
+
toolName: string,
|
|
69
|
+
signature: string,
|
|
70
|
+
config: LoopDetectionConfig,
|
|
71
|
+
): LoopCheckResult {
|
|
72
|
+
if (
|
|
73
|
+
toolName === state.lastToolName &&
|
|
74
|
+
signature === state.lastToolSignature
|
|
75
|
+
) {
|
|
76
|
+
state.consecutiveIdenticalCount++;
|
|
77
|
+
} else {
|
|
78
|
+
state.consecutiveIdenticalCount = 1;
|
|
79
|
+
}
|
|
80
|
+
state.lastToolName = toolName;
|
|
81
|
+
state.lastToolSignature = signature;
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
softWarning: state.consecutiveIdenticalCount === config.softThreshold,
|
|
85
|
+
hardEscalation: state.consecutiveIdenticalCount >= config.hardThreshold,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// =============================================================================
|
|
90
|
+
// Class wrapper (new — per PLAN.md §3.2.3)
|
|
91
|
+
// =============================================================================
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Verdict returned by {@link LoopDetectionTracker.inspect}.
|
|
95
|
+
*
|
|
96
|
+
* - `"ok"` — no repeated call detected.
|
|
97
|
+
* - `"soft"` — soft-warning threshold reached; SessionRuntime may surface a
|
|
98
|
+
* recovery notice but should not block the call.
|
|
99
|
+
* - `"hard"` — hard-escalation threshold reached; SessionRuntime should
|
|
100
|
+
* stop the run with the provided `message`.
|
|
101
|
+
*/
|
|
102
|
+
export interface LoopDetectionVerdict {
|
|
103
|
+
kind: "ok" | "soft" | "hard";
|
|
104
|
+
message?: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Minimal call shape the tracker needs; matches `AgentToolCallPart` subset. */
|
|
108
|
+
export interface LoopDetectionCall {
|
|
109
|
+
name: string;
|
|
110
|
+
input: unknown;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const DEFAULT_CONFIG: LoopDetectionConfig = {
|
|
114
|
+
softThreshold: 3,
|
|
115
|
+
hardThreshold: 5,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Per-session repeated-tool-call detector.
|
|
120
|
+
*
|
|
121
|
+
* `SessionRuntime` owns the instance and installs a `beforeTool` hook
|
|
122
|
+
* (see `AgentRuntimeHooks.beforeTool`) that calls `inspect()` to decide
|
|
123
|
+
* whether to return `{ skip, stop, reason }`.
|
|
124
|
+
*/
|
|
125
|
+
export class LoopDetectionTracker {
|
|
126
|
+
private readonly config: LoopDetectionConfig;
|
|
127
|
+
private readonly state: LoopDetectionState = createLoopDetectionState();
|
|
128
|
+
|
|
129
|
+
constructor(config?: Partial<LoopDetectionConfig>) {
|
|
130
|
+
this.config = {
|
|
131
|
+
softThreshold: config?.softThreshold ?? DEFAULT_CONFIG.softThreshold,
|
|
132
|
+
hardThreshold: config?.hardThreshold ?? DEFAULT_CONFIG.hardThreshold,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
inspect(call: LoopDetectionCall): LoopDetectionVerdict {
|
|
137
|
+
const signature = toolCallSignature(call.input);
|
|
138
|
+
const result = checkRepeatedToolCall(
|
|
139
|
+
this.state,
|
|
140
|
+
call.name,
|
|
141
|
+
signature,
|
|
142
|
+
this.config,
|
|
143
|
+
);
|
|
144
|
+
if (result.hardEscalation) {
|
|
145
|
+
return {
|
|
146
|
+
kind: "hard",
|
|
147
|
+
message: `Detected ${this.state.consecutiveIdenticalCount} consecutive identical calls to \`${call.name}\`; stopping to avoid a loop.`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (result.softWarning) {
|
|
151
|
+
return {
|
|
152
|
+
kind: "soft",
|
|
153
|
+
message: `Detected ${this.state.consecutiveIdenticalCount} consecutive identical calls to \`${call.name}\`; consider trying a different approach.`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return { kind: "ok" };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
reset(): void {
|
|
160
|
+
resetLoopDetectionState(this.state);
|
|
161
|
+
}
|
|
162
|
+
}
|