@clinebot/core 0.0.35 → 0.0.36
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 +53 -39
- package/dist/ClineCore.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/index.d.ts +6 -0
- package/dist/cron/index.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 +66 -0
- package/dist/cron/scheduler.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 +9 -2
- package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-loader.d.ts +5 -3
- 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 +15 -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 +211 -211
- package/dist/extensions/tools/definitions.d.ts +1 -1
- 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/search.d.ts +1 -1
- package/dist/extensions/tools/executors/search.d.ts.map +1 -1
- package/dist/extensions/tools/index.d.ts +2 -0
- package/dist/extensions/tools/index.d.ts.map +1 -1
- package/dist/extensions/tools/presets.d.ts +26 -43
- 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.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/hooks/hook-file-hooks.d.ts +4 -1
- package/dist/hooks/hook-file-hooks.d.ts.map +1 -1
- 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 +45 -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 +1045 -0
- package/dist/hub/daemon.d.ts +5 -0
- package/dist/hub/daemon.d.ts.map +1 -0
- package/dist/hub/defaults.d.ts +13 -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 +1044 -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 +86 -0
- package/dist/hub/server.d.ts.map +1 -0
- package/dist/hub/session-client.d.ts +87 -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 +44 -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 +26 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +498 -476
- package/dist/llms/configured-provider-registry.d.ts +28 -0
- package/dist/llms/configured-provider-registry.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 +202 -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/host.d.ts +1 -2
- package/dist/runtime/host.d.ts.map +1 -1
- 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-host.d.ts +22 -24
- 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.d.ts +1 -19
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/services/global-settings.d.ts +12 -0
- package/dist/services/global-settings.d.ts.map +1 -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 +4 -4
- package/dist/services/providers/local-provider-registry.d.ts.map +1 -1
- package/dist/services/providers/local-provider-service.d.ts +13 -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/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/telemetry/index.js +28 -15
- package/dist/services/workspace-manifest.d.ts +11 -0
- package/dist/services/workspace-manifest.d.ts.map +1 -1
- 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-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 +47 -0
- package/dist/transports/hub.d.ts.map +1 -0
- package/dist/transports/local.d.ts +10 -6
- 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 +10 -12
- package/dist/types/chat-schema.d.ts.map +1 -1
- package/dist/types/config.d.ts +8 -7
- package/dist/types/config.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 +2 -1
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -6
- package/src/ClineCore.ts +68 -40
- package/src/account/index.ts +3 -3
- package/src/account/rpc.ts +12 -12
- package/src/cron/index.ts +5 -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 +637 -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 +17 -2
- package/src/extensions/plugin/plugin-loader.ts +48 -4
- package/src/extensions/plugin/plugin-module-import.ts +0 -2
- package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +93 -39
- package/src/extensions/plugin/plugin-sandbox.ts +47 -27
- package/src/extensions/plugin/plugin-targeting.ts +32 -0
- package/src/extensions/tools/definitions.ts +30 -49
- package/src/extensions/tools/executors/apply-patch.ts +69 -80
- package/src/extensions/tools/executors/search.ts +195 -3
- package/src/extensions/tools/index.ts +10 -0
- package/src/extensions/tools/presets.ts +31 -46
- package/src/extensions/tools/runtime.ts +261 -0
- package/src/extensions/tools/schemas.ts +4 -2
- package/src/extensions/tools/team/team-tools.ts +21 -0
- package/src/hooks/hook-file-hooks.ts +8 -2
- 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 +137 -0
- package/src/hub/client.ts +574 -0
- package/src/hub/connect.ts +156 -0
- package/src/hub/daemon-entry.ts +87 -0
- package/src/hub/daemon.ts +181 -0
- package/src/hub/defaults.ts +43 -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 +140 -0
- package/src/hub/server.ts +1888 -0
- package/src/hub/session-client.ts +460 -0
- package/src/hub/start-shared-server.ts +58 -0
- package/src/hub/transport.ts +14 -0
- package/src/hub/ui-client.ts +122 -0
- package/src/hub/workspace.ts +19 -0
- package/src/index.ts +124 -68
- package/src/llms/configured-provider-registry.ts +193 -0
- package/src/llms/provider-defaults.ts +637 -0
- package/src/llms/provider-settings.ts +263 -0
- package/src/llms/runtime-config.ts +43 -0
- package/src/llms/runtime-registry.ts +171 -0
- package/src/llms/runtime-types.ts +121 -0
- package/src/runtime/host.ts +107 -269
- package/src/runtime/index.ts +1 -0
- package/src/runtime/rules.ts +12 -0
- package/src/runtime/runtime-builder.ts +24 -8
- package/src/runtime/runtime-host.ts +89 -61
- package/src/runtime/runtime-oauth-token-manager.ts +11 -15
- package/src/runtime/session-runtime.ts +0 -24
- package/src/services/global-settings.ts +122 -0
- package/src/services/local-runtime-bootstrap.ts +51 -13
- package/src/services/plugin-tools.ts +85 -0
- package/src/services/providers/local-provider-registry.ts +6 -6
- package/src/services/providers/local-provider-service.ts +42 -37
- package/src/services/session-data.ts +15 -9
- package/src/services/storage/provider-settings-legacy-migration.ts +6 -4
- package/src/services/storage/provider-settings-manager.ts +1 -1
- package/src/services/workspace-manifest.ts +18 -0
- package/src/session/file-session-service.ts +1 -1
- package/src/session/index.ts +6 -27
- 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 +656 -0
- package/src/transports/local.ts +135 -40
- package/src/transports/remote.ts +26 -0
- package/src/transports/runtime-host-support.ts +63 -9
- package/src/types/chat-schema.ts +4 -5
- package/src/types/config.ts +8 -7
- package/src/types/provider-settings.ts +11 -7
- package/src/types/session.ts +2 -4
- package/src/types.ts +27 -1
- 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/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
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { resolveHubEndpointOptions } from "./defaults";
|
|
2
|
+
import { createLocalHubScheduleRuntimeHandlers } from "./runtime-handlers";
|
|
3
|
+
import { startHubWebSocketServer } from "./server";
|
|
4
|
+
import { resolveSharedHubOwnerContext } from "./workspace";
|
|
5
|
+
|
|
6
|
+
function parseArgs(argv: string[]): {
|
|
7
|
+
cwd: string;
|
|
8
|
+
host?: string;
|
|
9
|
+
port?: number;
|
|
10
|
+
pathname?: string;
|
|
11
|
+
} {
|
|
12
|
+
let cwd = process.cwd();
|
|
13
|
+
let host: string | undefined;
|
|
14
|
+
let port: number | undefined;
|
|
15
|
+
let pathname: string | undefined;
|
|
16
|
+
|
|
17
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
18
|
+
const arg = argv[index];
|
|
19
|
+
const value = argv[index + 1];
|
|
20
|
+
if (arg === "--cwd" && value) {
|
|
21
|
+
cwd = value;
|
|
22
|
+
index += 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (arg === "--host" && value) {
|
|
26
|
+
host = value;
|
|
27
|
+
index += 1;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (arg === "--port" && value) {
|
|
31
|
+
const parsed = Number(value);
|
|
32
|
+
if (Number.isFinite(parsed)) {
|
|
33
|
+
port = parsed;
|
|
34
|
+
}
|
|
35
|
+
index += 1;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (arg === "--pathname" && value) {
|
|
39
|
+
pathname = value;
|
|
40
|
+
index += 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return { cwd, host, port, pathname };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function main(): Promise<void> {
|
|
48
|
+
const options = parseArgs(process.argv.slice(2));
|
|
49
|
+
process.chdir(options.cwd);
|
|
50
|
+
|
|
51
|
+
const endpoint = resolveHubEndpointOptions({
|
|
52
|
+
host: options.host,
|
|
53
|
+
port: options.port,
|
|
54
|
+
pathname: options.pathname,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const server = await startHubWebSocketServer({
|
|
58
|
+
host: endpoint.host,
|
|
59
|
+
port: endpoint.port,
|
|
60
|
+
pathname: endpoint.pathname,
|
|
61
|
+
owner: resolveSharedHubOwnerContext(),
|
|
62
|
+
runtimeHandlers: createLocalHubScheduleRuntimeHandlers(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const shutdown = async (): Promise<void> => {
|
|
66
|
+
await server.close();
|
|
67
|
+
process.exit(0);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
process.on("SIGINT", () => {
|
|
71
|
+
void shutdown();
|
|
72
|
+
});
|
|
73
|
+
process.on("SIGTERM", () => {
|
|
74
|
+
void shutdown();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await new Promise<void>(() => {
|
|
78
|
+
// keep daemon process alive
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
void main().catch((error) => {
|
|
83
|
+
const message =
|
|
84
|
+
error instanceof Error ? error.stack || error.message : String(error);
|
|
85
|
+
process.stderr.write(`[hub-daemon] fatal: ${message}\n`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { closeSync, mkdirSync, openSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { withResolvedClineBuildEnv } from "@clinebot/shared";
|
|
6
|
+
import { verifyHubConnection } from "./client";
|
|
7
|
+
import {
|
|
8
|
+
type HubEndpointOverrides,
|
|
9
|
+
resolveHubEndpointOptions,
|
|
10
|
+
} from "./defaults";
|
|
11
|
+
import {
|
|
12
|
+
createHubServerUrl,
|
|
13
|
+
probeHubServer,
|
|
14
|
+
readHubDiscovery,
|
|
15
|
+
resolveClineDataDir,
|
|
16
|
+
writeHubDiscovery,
|
|
17
|
+
} from "./discovery";
|
|
18
|
+
import { resolveSharedHubOwnerContext } from "./workspace";
|
|
19
|
+
|
|
20
|
+
const HUB_STARTUP_TIMEOUT_MS = 8_000;
|
|
21
|
+
const HUB_STARTUP_POLL_MS = 200;
|
|
22
|
+
|
|
23
|
+
function endpointArgs(endpoint: HubEndpointOverrides): string[] {
|
|
24
|
+
return [
|
|
25
|
+
...(endpoint.host ? ["--host", endpoint.host] : []),
|
|
26
|
+
...(typeof endpoint.port === "number"
|
|
27
|
+
? ["--port", String(endpoint.port)]
|
|
28
|
+
: []),
|
|
29
|
+
...(endpoint.pathname ? ["--pathname", endpoint.pathname] : []),
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function openDetachedHubLogFile(): { fd: number; logPath: string } | undefined {
|
|
34
|
+
try {
|
|
35
|
+
const logPath = join(resolveClineDataDir(), "logs", "hub-daemon.log");
|
|
36
|
+
mkdirSync(dirname(logPath), { recursive: true });
|
|
37
|
+
return { fd: openSync(logPath, "a"), logPath };
|
|
38
|
+
} catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function resolveDaemonEntryPath(): string {
|
|
44
|
+
const extension = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
|
45
|
+
return fileURLToPath(new URL(`./daemon-entry.${extension}`, import.meta.url));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function resolveLaunchCommand(
|
|
49
|
+
workspaceRoot: string,
|
|
50
|
+
endpoint: HubEndpointOverrides,
|
|
51
|
+
): {
|
|
52
|
+
launcher: string;
|
|
53
|
+
args: string[];
|
|
54
|
+
cwd: string;
|
|
55
|
+
env: NodeJS.ProcessEnv;
|
|
56
|
+
} {
|
|
57
|
+
const daemonEntryPath = resolveDaemonEntryPath();
|
|
58
|
+
const execPath = process.execPath?.trim();
|
|
59
|
+
if (!execPath) {
|
|
60
|
+
throw new Error("unable to resolve runtime executable for hub daemon");
|
|
61
|
+
}
|
|
62
|
+
const isBunRuntime = basename(execPath).toLowerCase().includes("bun");
|
|
63
|
+
const useDevelopmentConditions =
|
|
64
|
+
isBunRuntime && daemonEntryPath.toLowerCase().endsWith(".ts");
|
|
65
|
+
return {
|
|
66
|
+
launcher: execPath,
|
|
67
|
+
args: [
|
|
68
|
+
...(useDevelopmentConditions ? ["--conditions=development"] : []),
|
|
69
|
+
daemonEntryPath,
|
|
70
|
+
"--cwd",
|
|
71
|
+
workspaceRoot,
|
|
72
|
+
...endpointArgs(endpoint),
|
|
73
|
+
],
|
|
74
|
+
cwd: workspaceRoot,
|
|
75
|
+
env: {
|
|
76
|
+
...withResolvedClineBuildEnv(process.env),
|
|
77
|
+
CLINE_NO_INTERACTIVE: "1",
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function spawnDetachedHubServer(
|
|
83
|
+
workspaceRoot: string,
|
|
84
|
+
endpoint: HubEndpointOverrides = {},
|
|
85
|
+
): void {
|
|
86
|
+
const command = resolveLaunchCommand(workspaceRoot, endpoint);
|
|
87
|
+
const logFile = openDetachedHubLogFile();
|
|
88
|
+
try {
|
|
89
|
+
const child = spawn(command.launcher, command.args, {
|
|
90
|
+
detached: true,
|
|
91
|
+
stdio: logFile ? ["ignore", logFile.fd, logFile.fd] : "ignore",
|
|
92
|
+
env: command.env,
|
|
93
|
+
cwd: command.cwd,
|
|
94
|
+
});
|
|
95
|
+
child.unref();
|
|
96
|
+
} finally {
|
|
97
|
+
if (logFile) {
|
|
98
|
+
closeSync(logFile.fd);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function prewarmDetachedHubServer(
|
|
104
|
+
workspaceRoot: string,
|
|
105
|
+
endpoint: HubEndpointOverrides = {},
|
|
106
|
+
): void {
|
|
107
|
+
const owner = resolveSharedHubOwnerContext();
|
|
108
|
+
const resolvedEndpoint = resolveHubEndpointOptions(endpoint);
|
|
109
|
+
const expectedUrl = createHubServerUrl(
|
|
110
|
+
resolvedEndpoint.host,
|
|
111
|
+
resolvedEndpoint.port,
|
|
112
|
+
resolvedEndpoint.pathname,
|
|
113
|
+
);
|
|
114
|
+
void readHubDiscovery(owner.discoveryPath)
|
|
115
|
+
.then(async (discovered) => {
|
|
116
|
+
if (discovered?.url) {
|
|
117
|
+
const healthy = await probeHubServer(discovered.url);
|
|
118
|
+
if (healthy?.url && (await verifyHubConnection(healthy.url))) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const expected = await probeHubServer(expectedUrl);
|
|
123
|
+
if (expected?.url && (await verifyHubConnection(expected.url))) {
|
|
124
|
+
await writeHubDiscovery(owner.discoveryPath, expected);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const spawnEndpoint =
|
|
128
|
+
expected?.url && resolvedEndpoint.port !== 0
|
|
129
|
+
? { ...resolvedEndpoint, port: 0 }
|
|
130
|
+
: resolvedEndpoint;
|
|
131
|
+
spawnDetachedHubServer(workspaceRoot, spawnEndpoint);
|
|
132
|
+
})
|
|
133
|
+
.catch(() => {
|
|
134
|
+
// best-effort prewarm only
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function ensureDetachedHubServer(
|
|
139
|
+
workspaceRoot: string,
|
|
140
|
+
endpointOverrides: HubEndpointOverrides = {},
|
|
141
|
+
): Promise<string> {
|
|
142
|
+
const owner = resolveSharedHubOwnerContext();
|
|
143
|
+
const endpoint = resolveHubEndpointOptions(endpointOverrides);
|
|
144
|
+
const expectedUrl = createHubServerUrl(
|
|
145
|
+
endpoint.host,
|
|
146
|
+
endpoint.port,
|
|
147
|
+
endpoint.pathname,
|
|
148
|
+
);
|
|
149
|
+
const discovered = await readHubDiscovery(owner.discoveryPath);
|
|
150
|
+
if (discovered?.url) {
|
|
151
|
+
const healthy = await probeHubServer(discovered.url);
|
|
152
|
+
if (healthy?.url && (await verifyHubConnection(healthy.url))) {
|
|
153
|
+
return healthy.url;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const expected = await probeHubServer(expectedUrl);
|
|
157
|
+
if (expected?.url && (await verifyHubConnection(expected.url))) {
|
|
158
|
+
await writeHubDiscovery(owner.discoveryPath, expected);
|
|
159
|
+
return expected.url;
|
|
160
|
+
}
|
|
161
|
+
const spawnEndpoint =
|
|
162
|
+
expected?.url && endpoint.port !== 0 ? { ...endpoint, port: 0 } : endpoint;
|
|
163
|
+
spawnDetachedHubServer(workspaceRoot, spawnEndpoint);
|
|
164
|
+
const deadline = Date.now() + HUB_STARTUP_TIMEOUT_MS;
|
|
165
|
+
while (Date.now() < deadline) {
|
|
166
|
+
const nextDiscovery = await readHubDiscovery(owner.discoveryPath);
|
|
167
|
+
if (nextDiscovery?.url) {
|
|
168
|
+
const healthy = await probeHubServer(nextDiscovery.url);
|
|
169
|
+
if (healthy?.url && (await verifyHubConnection(healthy.url))) {
|
|
170
|
+
return healthy.url;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const nextExpected = await probeHubServer(expectedUrl);
|
|
174
|
+
if (nextExpected?.url && (await verifyHubConnection(nextExpected.url))) {
|
|
175
|
+
await writeHubDiscovery(owner.discoveryPath, nextExpected);
|
|
176
|
+
return nextExpected.url;
|
|
177
|
+
}
|
|
178
|
+
await new Promise((resolve) => setTimeout(resolve, HUB_STARTUP_POLL_MS));
|
|
179
|
+
}
|
|
180
|
+
throw new Error("Timed out waiting for detached hub startup.");
|
|
181
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const HUB_HOST_ENV = "CLINE_HUB_HOST";
|
|
2
|
+
const HUB_PORT_ENV = "CLINE_HUB_PORT";
|
|
3
|
+
const HUB_PATHNAME_ENV = "CLINE_HUB_PATHNAME";
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_HUB_HOST = "127.0.0.1";
|
|
6
|
+
export const DEFAULT_HUB_PORT = 25463;
|
|
7
|
+
export const DEFAULT_HUB_PATHNAME = "/hub";
|
|
8
|
+
|
|
9
|
+
export interface HubEndpointOverrides {
|
|
10
|
+
host?: string;
|
|
11
|
+
port?: number;
|
|
12
|
+
pathname?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function resolveDefaultHubHost(): string {
|
|
16
|
+
return process.env[HUB_HOST_ENV]?.trim() || DEFAULT_HUB_HOST;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function resolveDefaultHubPort(): number {
|
|
20
|
+
const raw = process.env[HUB_PORT_ENV]?.trim();
|
|
21
|
+
if (!raw) {
|
|
22
|
+
return DEFAULT_HUB_PORT;
|
|
23
|
+
}
|
|
24
|
+
const port = Number.parseInt(raw, 10);
|
|
25
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535) {
|
|
26
|
+
return DEFAULT_HUB_PORT;
|
|
27
|
+
}
|
|
28
|
+
return port;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function resolveDefaultHubPathname(): string {
|
|
32
|
+
return process.env[HUB_PATHNAME_ENV]?.trim() || DEFAULT_HUB_PATHNAME;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function resolveHubEndpointOptions(
|
|
36
|
+
overrides: HubEndpointOverrides = {},
|
|
37
|
+
): Required<HubEndpointOverrides> {
|
|
38
|
+
return {
|
|
39
|
+
host: overrides.host ?? resolveDefaultHubHost(),
|
|
40
|
+
port: overrides.port ?? resolveDefaultHubPort(),
|
|
41
|
+
pathname: overrides.pathname ?? resolveDefaultHubPathname(),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { resolveClineDataDir, resolveClineDir } from "@clinebot/shared/storage";
|
|
6
|
+
import corePackage from "../../package.json";
|
|
7
|
+
|
|
8
|
+
const HUB_DISCOVERY_ENV = "CLINE_HUB_DISCOVERY_PATH";
|
|
9
|
+
const HUB_BUILD_ID_ENV = "CLINE_HUB_BUILD_ID";
|
|
10
|
+
const HUB_STARTUP_LOCK_MAX_AGE_MS = 30_000;
|
|
11
|
+
const HUB_STARTUP_LOCK_WAIT_MS = 15_000;
|
|
12
|
+
const HUB_STARTUP_LOCK_POLL_MS = 100;
|
|
13
|
+
|
|
14
|
+
export interface HubServerDiscoveryRecord {
|
|
15
|
+
hubId: string;
|
|
16
|
+
protocolVersion: string;
|
|
17
|
+
buildId?: string;
|
|
18
|
+
host: string;
|
|
19
|
+
port: number;
|
|
20
|
+
url: string;
|
|
21
|
+
pid?: number;
|
|
22
|
+
startedAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface HubOwnerContext {
|
|
27
|
+
ownerId: string;
|
|
28
|
+
discoveryPath: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function sanitizeKey(value: string): string {
|
|
32
|
+
return value.replace(/[^a-zA-Z0-9_.-]+/g, "_");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function hashValue(value: string): string {
|
|
36
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 12);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isPidAlive(pid: number | undefined): boolean {
|
|
40
|
+
if (!Number.isInteger(pid) || !pid || pid <= 0) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
process.kill(pid, 0);
|
|
45
|
+
return true;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return error instanceof Error && "code" in error
|
|
48
|
+
? String((error as NodeJS.ErrnoException).code) === "EPERM"
|
|
49
|
+
: false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sleep(ms: number): Promise<void> {
|
|
54
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getStartupLockDir(discoveryPath: string): string {
|
|
58
|
+
return `${discoveryPath}.lock`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function readStartupLockRecord(
|
|
62
|
+
lockDir: string,
|
|
63
|
+
): Promise<{ pid: number; acquiredAt: string } | undefined> {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(
|
|
66
|
+
await readFile(join(lockDir, "owner.json"), "utf8"),
|
|
67
|
+
) as Partial<{ pid: number; acquiredAt: string }>;
|
|
68
|
+
if (
|
|
69
|
+
typeof parsed.pid !== "number" ||
|
|
70
|
+
typeof parsed.acquiredAt !== "string"
|
|
71
|
+
) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
return { pid: parsed.pid, acquiredAt: parsed.acquiredAt };
|
|
75
|
+
} catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function removeStartupLock(lockDir: string): Promise<void> {
|
|
81
|
+
await rm(lockDir, { recursive: true, force: true }).catch(() => undefined);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function resolveHubBuildId(): string {
|
|
85
|
+
return process.env[HUB_BUILD_ID_ENV]?.trim() || String(corePackage.version);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function resolveHubOwnerContext(
|
|
89
|
+
ownerBasis: string = process.argv[1]?.trim() || process.cwd(),
|
|
90
|
+
): HubOwnerContext {
|
|
91
|
+
const ownerId = `hub-${hashValue(ownerBasis)}`;
|
|
92
|
+
const discoveryPath =
|
|
93
|
+
process.env[HUB_DISCOVERY_ENV]?.trim() ||
|
|
94
|
+
join(
|
|
95
|
+
resolveClineDataDir(),
|
|
96
|
+
"locks",
|
|
97
|
+
"hub",
|
|
98
|
+
"owners",
|
|
99
|
+
`${sanitizeKey(ownerId)}.json`,
|
|
100
|
+
);
|
|
101
|
+
return { ownerId, discoveryPath };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function createInMemoryHubOwnerContext(
|
|
105
|
+
label = `hub-${Date.now().toString(36)}`,
|
|
106
|
+
): HubOwnerContext {
|
|
107
|
+
return resolveHubOwnerContext(label);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function readHubDiscovery(
|
|
111
|
+
discoveryPath: string,
|
|
112
|
+
): Promise<HubServerDiscoveryRecord | undefined> {
|
|
113
|
+
try {
|
|
114
|
+
const parsed = JSON.parse(
|
|
115
|
+
await readFile(discoveryPath, "utf8"),
|
|
116
|
+
) as Partial<HubServerDiscoveryRecord>;
|
|
117
|
+
if (
|
|
118
|
+
typeof parsed.hubId !== "string" ||
|
|
119
|
+
typeof parsed.protocolVersion !== "string" ||
|
|
120
|
+
typeof parsed.host !== "string" ||
|
|
121
|
+
typeof parsed.port !== "number" ||
|
|
122
|
+
typeof parsed.url !== "string" ||
|
|
123
|
+
typeof parsed.startedAt !== "string" ||
|
|
124
|
+
typeof parsed.updatedAt !== "string"
|
|
125
|
+
) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
hubId: parsed.hubId,
|
|
130
|
+
protocolVersion: parsed.protocolVersion,
|
|
131
|
+
buildId: typeof parsed.buildId === "string" ? parsed.buildId : undefined,
|
|
132
|
+
host: parsed.host,
|
|
133
|
+
port: parsed.port,
|
|
134
|
+
url: parsed.url,
|
|
135
|
+
pid: typeof parsed.pid === "number" ? parsed.pid : undefined,
|
|
136
|
+
startedAt: parsed.startedAt,
|
|
137
|
+
updatedAt: parsed.updatedAt,
|
|
138
|
+
};
|
|
139
|
+
} catch {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export async function writeHubDiscovery(
|
|
145
|
+
discoveryPath: string,
|
|
146
|
+
record: HubServerDiscoveryRecord,
|
|
147
|
+
): Promise<void> {
|
|
148
|
+
await mkdir(dirname(discoveryPath), { recursive: true });
|
|
149
|
+
await writeFile(
|
|
150
|
+
discoveryPath,
|
|
151
|
+
`${JSON.stringify(record, null, 2)}\n`,
|
|
152
|
+
"utf8",
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function clearHubDiscovery(discoveryPath: string): Promise<void> {
|
|
157
|
+
await rm(discoveryPath, { force: true }).catch(() => undefined);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export async function withHubStartupLock<T>(
|
|
161
|
+
discoveryPath: string,
|
|
162
|
+
callback: () => Promise<T>,
|
|
163
|
+
): Promise<T> {
|
|
164
|
+
const lockDir = getStartupLockDir(discoveryPath);
|
|
165
|
+
await mkdir(dirname(lockDir), { recursive: true });
|
|
166
|
+
const deadline = Date.now() + HUB_STARTUP_LOCK_WAIT_MS;
|
|
167
|
+
|
|
168
|
+
while (true) {
|
|
169
|
+
try {
|
|
170
|
+
await mkdir(lockDir, { recursive: false });
|
|
171
|
+
await writeFile(
|
|
172
|
+
join(lockDir, "owner.json"),
|
|
173
|
+
`${JSON.stringify(
|
|
174
|
+
{ pid: process.pid, acquiredAt: new Date().toISOString() },
|
|
175
|
+
null,
|
|
176
|
+
2,
|
|
177
|
+
)}\n`,
|
|
178
|
+
"utf8",
|
|
179
|
+
);
|
|
180
|
+
try {
|
|
181
|
+
return await callback();
|
|
182
|
+
} finally {
|
|
183
|
+
await removeStartupLock(lockDir);
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
const code =
|
|
187
|
+
error instanceof Error && "code" in error
|
|
188
|
+
? String((error as NodeJS.ErrnoException).code)
|
|
189
|
+
: "";
|
|
190
|
+
if (code !== "EEXIST") {
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
const record = await readStartupLockRecord(lockDir);
|
|
194
|
+
const lockAge = record
|
|
195
|
+
? Date.now() - Date.parse(record.acquiredAt)
|
|
196
|
+
: HUB_STARTUP_LOCK_MAX_AGE_MS + 1;
|
|
197
|
+
if (
|
|
198
|
+
!record ||
|
|
199
|
+
!isPidAlive(record.pid) ||
|
|
200
|
+
lockAge > HUB_STARTUP_LOCK_MAX_AGE_MS
|
|
201
|
+
) {
|
|
202
|
+
await removeStartupLock(lockDir);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (Date.now() >= deadline) {
|
|
206
|
+
throw new Error(`Timed out waiting for hub startup lock ${lockDir}`);
|
|
207
|
+
}
|
|
208
|
+
await sleep(HUB_STARTUP_LOCK_POLL_MS);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export async function probeHubServer(
|
|
214
|
+
url: string,
|
|
215
|
+
): Promise<HubServerDiscoveryRecord | undefined> {
|
|
216
|
+
try {
|
|
217
|
+
const response = await fetch(toHubHealthUrl(url));
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
return (await response.json()) as HubServerDiscoveryRecord;
|
|
222
|
+
} catch {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function createHubServerUrl(
|
|
228
|
+
host: string,
|
|
229
|
+
port: number,
|
|
230
|
+
pathname = "/hub",
|
|
231
|
+
): string {
|
|
232
|
+
return new URL(`ws://${host}:${port}${pathname}`).toString();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function toHubHealthUrl(wsUrl: string): string {
|
|
236
|
+
const parsed = new URL(wsUrl);
|
|
237
|
+
parsed.protocol = parsed.protocol === "wss:" ? "https:" : "http:";
|
|
238
|
+
parsed.pathname = "/health";
|
|
239
|
+
parsed.search = "";
|
|
240
|
+
return parsed.toString();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function isDiscoveryFilePresent(pathname: string): boolean {
|
|
244
|
+
return existsSync(pathname);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export { resolveClineDataDir, resolveClineDir };
|
package/src/hub/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./browser-websocket";
|
|
2
|
+
export * from "./client";
|
|
3
|
+
export * from "./connect";
|
|
4
|
+
export * from "./daemon";
|
|
5
|
+
export * from "./defaults";
|
|
6
|
+
export * from "./discovery";
|
|
7
|
+
export * from "./native-transport";
|
|
8
|
+
export * from "./runtime-handlers";
|
|
9
|
+
export * from "./server";
|
|
10
|
+
export * from "./session-client";
|
|
11
|
+
export * from "./start-shared-server";
|
|
12
|
+
export * from "./transport";
|
|
13
|
+
export * from "./ui-client";
|
|
14
|
+
export * from "./workspace";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
HubCommandEnvelope,
|
|
3
|
+
HubEventEnvelope,
|
|
4
|
+
HubReplyEnvelope,
|
|
5
|
+
} from "@clinebot/shared";
|
|
6
|
+
import type { HubCommandTransport } from "./transport";
|
|
7
|
+
|
|
8
|
+
export interface NativeHubTransport {
|
|
9
|
+
handleCommand(envelope: HubCommandEnvelope): Promise<HubReplyEnvelope>;
|
|
10
|
+
subscribe(
|
|
11
|
+
clientId: string,
|
|
12
|
+
listener: (event: HubEventEnvelope) => void,
|
|
13
|
+
options?: { sessionId?: string },
|
|
14
|
+
): () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class NativeHubTransportAdapter implements HubCommandTransport {
|
|
18
|
+
constructor(private readonly transport: NativeHubTransport) {}
|
|
19
|
+
|
|
20
|
+
command(envelope: HubCommandEnvelope): Promise<HubReplyEnvelope> {
|
|
21
|
+
return this.transport.handleCommand(envelope);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
subscribe(
|
|
25
|
+
clientId: string,
|
|
26
|
+
listener: (event: HubEventEnvelope) => void,
|
|
27
|
+
options?: { sessionId?: string },
|
|
28
|
+
): () => void {
|
|
29
|
+
return this.transport.subscribe(clientId, listener, options);
|
|
30
|
+
}
|
|
31
|
+
}
|