mirror of
https://github.com/cline/cline.git
synced 2026-09-12 00:50:27 +08:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc0675d31f |
@@ -68,19 +68,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.16.1",
|
||||
"@chat-adapter/discord": "^4.23.0",
|
||||
"@chat-adapter/gchat": "^4.23.0",
|
||||
"@chat-adapter/linear": "^4.23.0",
|
||||
"@chat-adapter/slack": "^4.23.0",
|
||||
"@chat-adapter/telegram": "^4.23.0",
|
||||
"@chat-adapter/whatsapp": "^4.23.0",
|
||||
"@clack/prompts": "^1.2.0",
|
||||
"@cline/cline-hub": "workspace:*",
|
||||
"@gramio/format": "^0.7.0",
|
||||
"@opentui-ui/dialog": "^0.1.2",
|
||||
"@opentui/core": "0.1.102",
|
||||
"@opentui/react": "0.1.102",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"fzf": "^0.5.2",
|
||||
"marked": "^15.0.12",
|
||||
|
||||
@@ -21,6 +21,10 @@ import type {
|
||||
StopReason,
|
||||
} from "@agentclientprotocol/sdk";
|
||||
import { PROTOCOL_VERSION, RequestError } from "@agentclientprotocol/sdk";
|
||||
import {
|
||||
resolveSystemPrompt,
|
||||
resolveWorkspaceRoot,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
type AgentEvent,
|
||||
type ClineCore,
|
||||
@@ -30,11 +34,10 @@ import {
|
||||
} from "@cline/core";
|
||||
import type { Message } from "@cline/shared";
|
||||
import { getPersistedProviderApiKey } from "../commands/auth";
|
||||
import { resolveSystemPrompt } from "../runtime/prompt";
|
||||
import { subscribeToAgentEvents } from "../runtime/session-events";
|
||||
import { createCliCore } from "../session/session";
|
||||
import { getCliBuildInfo } from "../utils/common";
|
||||
import { randomSessionId, resolveWorkspaceRoot } from "../utils/helpers";
|
||||
import { randomSessionId } from "../utils/helpers";
|
||||
import type { Config } from "../utils/types";
|
||||
import {
|
||||
ACP_AUTH_METHODS,
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
import { getConnector, listConnectors } from "../connectors/registry";
|
||||
import type { ConnectIo, ConnectStopResult } from "../connectors/types";
|
||||
import {
|
||||
type ConnectIo,
|
||||
type ConnectStopResult,
|
||||
getConnector,
|
||||
listConnectors,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import { createCliLoggerAdapter } from "../logging/adapter";
|
||||
import { resolveCliSessionMetadata } from "../utils/enterprise";
|
||||
import { ensureOAuthProviderApiKey } from "./auth";
|
||||
|
||||
function withConnectorHost(io: ConnectIo): ConnectIo {
|
||||
return {
|
||||
...io,
|
||||
createLogger: createCliLoggerAdapter,
|
||||
resolveSessionMetadata: resolveCliSessionMetadata,
|
||||
ensureProviderApiKey: (input) =>
|
||||
ensureOAuthProviderApiKey({ ...input, io }),
|
||||
};
|
||||
}
|
||||
|
||||
export async function stopAllConnectors(
|
||||
io: ConnectIo,
|
||||
@@ -16,7 +33,7 @@ export async function stopAllConnectors(
|
||||
continue;
|
||||
}
|
||||
executed += 1;
|
||||
const result = await connector.stopAll(io);
|
||||
const result = await connector.stopAll(withConnectorHost(io));
|
||||
stoppedProcesses += result.stoppedProcesses;
|
||||
stoppedSessions += result.stoppedSessions;
|
||||
}
|
||||
@@ -49,7 +66,9 @@ export async function runStopConnector(
|
||||
io.writeErr(`connect adapter "${adapterName}" does not support stop`);
|
||||
return 1;
|
||||
}
|
||||
const result: ConnectStopResult = await connector.stopAll(io);
|
||||
const result: ConnectStopResult = await connector.stopAll(
|
||||
withConnectorHost(io),
|
||||
);
|
||||
io.writeln(
|
||||
`[connect] ${connector.name} stopped processes=${result.stoppedProcesses} sessions=${result.stoppedSessions}`,
|
||||
);
|
||||
@@ -66,7 +85,7 @@ export async function runConnectAdapter(
|
||||
io.writeErr(`unknown connect adapter "${adapterName}"`);
|
||||
return 1;
|
||||
}
|
||||
return connector.run(passthroughArgs, io);
|
||||
return connector.run(passthroughArgs, withConnectorHost(io));
|
||||
}
|
||||
|
||||
export function formatAdapterList(): string {
|
||||
|
||||
@@ -71,8 +71,9 @@ vi.mock("@cline/core", () => ({
|
||||
ensureFileExists: mockEnsureFileExists,
|
||||
}));
|
||||
|
||||
vi.mock("../connectors/common", () => ({
|
||||
vi.mock("@cline/cline-hub/connectors", () => ({
|
||||
isProcessRunning: vi.fn(() => false),
|
||||
listActiveConnectors: vi.fn(() => []),
|
||||
}));
|
||||
|
||||
vi.mock("./connect", () => ({
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { existsSync, readFileSync, rmSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import {
|
||||
type ActiveConnectorRecord,
|
||||
isProcessRunning,
|
||||
listActiveConnectors,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
clearHubDiscovery,
|
||||
ensureFileExists,
|
||||
@@ -14,11 +19,6 @@ import {
|
||||
import { formatUptime, resolveClineBuildEnv } from "@cline/shared";
|
||||
import { Command } from "commander";
|
||||
import open from "open";
|
||||
import { isProcessRunning } from "../connectors/common";
|
||||
import {
|
||||
type ActiveConnectorRecord,
|
||||
listActiveConnectors,
|
||||
} from "../connectors/status";
|
||||
import { getCliBuildInfo } from "../utils/common";
|
||||
import { c, writeln } from "../utils/output";
|
||||
import { stopAllConnectors } from "./connect";
|
||||
|
||||
@@ -11,8 +11,8 @@ vi.mock("@cline/core", () => ({
|
||||
sendHubCommand: mockSendHubCommand,
|
||||
}));
|
||||
|
||||
vi.mock("../utils/hub-runtime", () => ({
|
||||
ensureCliHubServer: mockEnsureCliHubServer,
|
||||
vi.mock("@cline/cline-hub/connectors", () => ({
|
||||
ensureHubServer: mockEnsureCliHubServer,
|
||||
parseHubEndpointOverride: (rawAddress: string | undefined) => {
|
||||
const trimmed = rawAddress?.trim();
|
||||
if (!trimmed) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
createLocalHubScheduleRuntimeHandlers,
|
||||
HubScheduleCommandService,
|
||||
HubScheduleService,
|
||||
sendHubCommand,
|
||||
} from "@cline/core";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
} from "../../utils/hub-runtime";
|
||||
import type { CommandIo } from "./types";
|
||||
|
||||
export class HubScheduleClient {
|
||||
@@ -190,7 +190,7 @@ export async function ensureSchedulerHub(
|
||||
}
|
||||
try {
|
||||
const requestedEndpoint = parseHubEndpointOverride(address);
|
||||
const { url: hubUrl } = await ensureCliHubServer(
|
||||
const { url: hubUrl } = await ensureHubServer(
|
||||
workspaceRoot,
|
||||
requestedEndpoint,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type ChildProcess, spawn } from "node:child_process";
|
||||
import { realpathSync } from "node:fs";
|
||||
import { ensureHubServer } from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
clearHubDiscovery,
|
||||
isAutoUpdateEnabledGlobally,
|
||||
@@ -11,7 +12,6 @@ import {
|
||||
} from "@cline/core";
|
||||
import { resolveClineBuildEnv } from "@cline/shared";
|
||||
import { version } from "../../package.json";
|
||||
import { ensureCliHubServer } from "../utils/hub-runtime";
|
||||
import { c, writeErr, writeln } from "../utils/output";
|
||||
import {
|
||||
getInstalledKanbanVersion,
|
||||
@@ -337,7 +337,7 @@ async function restartHubServerIfRunning(): Promise<void> {
|
||||
|
||||
// Re-ensure a fresh hub instance is spawned.
|
||||
try {
|
||||
await ensureCliHubServer(process.cwd()); // return value intentionally unused here
|
||||
await ensureHubServer(process.cwd()); // return value intentionally unused here
|
||||
writeln(`${c.green}✓${c.reset} ${c.dim}[hub] server restarted${c.reset}`);
|
||||
} catch (err) {
|
||||
writeErr(
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
export type ConnectIo = {
|
||||
writeln: (text?: string) => void;
|
||||
writeErr: (text: string) => void;
|
||||
};
|
||||
|
||||
export type ConnectStopResult = {
|
||||
stoppedProcesses: number;
|
||||
stoppedSessions: number;
|
||||
};
|
||||
|
||||
export interface ConnectCommandDefinition {
|
||||
name: string;
|
||||
description: string;
|
||||
run(args: string[], io: ConnectIo): Promise<number>;
|
||||
showHelp(io: ConnectIo): void;
|
||||
stopAll?(io: ConnectIo): Promise<ConnectStopResult>;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ const loggingMocks = vi.hoisted(() => ({
|
||||
flushCliLoggerAdapters: vi.fn(),
|
||||
}));
|
||||
const hubRuntimeMocks = vi.hoisted(() => ({
|
||||
ensureCliHubServer: vi.fn(async () => ({
|
||||
ensureHubServer: vi.fn(async () => ({
|
||||
url: "ws://127.0.0.1:25463",
|
||||
authToken: "test-token",
|
||||
})),
|
||||
@@ -192,8 +192,10 @@ vi.mock("./utils/feature-flags", () => ({
|
||||
setCliFeatureFlagsAccountContext:
|
||||
featureFlagMocks.setCliFeatureFlagsAccountContext,
|
||||
}));
|
||||
vi.mock("./runtime/prompt", () => ({
|
||||
vi.mock("@cline/cline-hub/connectors", () => ({
|
||||
resolveSystemPrompt: promptMocks.resolveSystemPrompt,
|
||||
resolveWorkspaceRoot: (cwd: string) => cwd,
|
||||
...hubRuntimeMocks,
|
||||
}));
|
||||
vi.mock("./commands/kanban", () => kanbanMocks);
|
||||
vi.mock("./commands/dashboard", () => dashboardMocks);
|
||||
@@ -202,7 +204,6 @@ vi.mock("./commands/update", () => updateMocks);
|
||||
vi.mock("./commands/history", () => historyMocks);
|
||||
vi.mock("./utils/history-resume", () => historyResumeMocks);
|
||||
vi.mock("./logging/adapter", () => loggingMocks);
|
||||
vi.mock("./utils/hub-runtime", () => hubRuntimeMocks);
|
||||
vi.mock("./utils/telemetry", () => telemetryMocks);
|
||||
vi.mock("./utils/worktree", () => worktreeMocks);
|
||||
|
||||
@@ -239,8 +240,8 @@ describe("runCli lightweight command dispatch", () => {
|
||||
taskId: "task-1",
|
||||
repoRoot: "/tmp/source",
|
||||
});
|
||||
hubRuntimeMocks.ensureCliHubServer.mockReset();
|
||||
hubRuntimeMocks.ensureCliHubServer.mockResolvedValue({
|
||||
hubRuntimeMocks.ensureHubServer.mockReset();
|
||||
hubRuntimeMocks.ensureHubServer.mockResolvedValue({
|
||||
url: "ws://127.0.0.1:25463",
|
||||
authToken: "test-token",
|
||||
});
|
||||
@@ -1161,7 +1162,7 @@ describe("runCli lightweight command dispatch", () => {
|
||||
|
||||
await expect(runCli()).resolves.toBeUndefined();
|
||||
expect(runtimeMocks.runAgent).toHaveBeenCalledTimes(1);
|
||||
expect(hubRuntimeMocks.ensureCliHubServer).not.toHaveBeenCalled();
|
||||
expect(hubRuntimeMocks.ensureHubServer).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects yolo runs with a single bare prompt token", async () => {
|
||||
@@ -1179,7 +1180,7 @@ describe("runCli lightweight command dispatch", () => {
|
||||
expect.stringContaining("Unknown command or unquoted prompt: hello"),
|
||||
);
|
||||
expect(runtimeMocks.runAgent).not.toHaveBeenCalled();
|
||||
expect(hubRuntimeMocks.ensureCliHubServer).not.toHaveBeenCalled();
|
||||
expect(hubRuntimeMocks.ensureHubServer).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rewrites /team prompts and enables teams in single-prompt mode", async () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { fstatSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { basename } from "node:path";
|
||||
import { resolveWorkspaceRoot } from "@cline/cline-hub/connectors";
|
||||
import type { ToolPolicy } from "@cline/core";
|
||||
|
||||
import { registerDisposable } from "@cline/shared";
|
||||
@@ -27,7 +28,6 @@ import {
|
||||
import {
|
||||
configureSandboxEnvironment,
|
||||
normalizeAutoApproveArgs,
|
||||
resolveWorkspaceRoot,
|
||||
} from "./utils/helpers";
|
||||
import {
|
||||
c,
|
||||
@@ -72,7 +72,7 @@ async function createProviderSettingsManager() {
|
||||
async function loadCliRuntimeModules() {
|
||||
const [coreServer, prompt, runAgentModule] = await Promise.all([
|
||||
import("@cline/core"),
|
||||
import("./runtime/prompt"),
|
||||
import("@cline/cline-hub/connectors"),
|
||||
import("./runtime/run-agent"),
|
||||
]);
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
type ChatCommandState,
|
||||
chatCommandHost,
|
||||
createChatCommandHost,
|
||||
} from "../../utils/chat-commands";
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { Config } from "../../utils/types";
|
||||
import {
|
||||
type InteractiveChatCommandRuntime,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { InteractiveTurnResult } from "../../tui/types";
|
||||
import type { ChatCommandHost } from "../../utils/chat-commands";
|
||||
import type { ChatCommandHost } from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
type ChatCommandState,
|
||||
maybeHandleChatCommand,
|
||||
} from "../../utils/chat-commands";
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import type { InteractiveTurnResult } from "../../tui/types";
|
||||
import {
|
||||
enableTeamsForPrompt,
|
||||
rewriteTeamPrompt,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { resolveSystemPrompt } from "@cline/cline-hub/connectors";
|
||||
import { createTool } from "@cline/shared";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { Config } from "../../utils/types";
|
||||
import { resolveSystemPrompt } from "../prompt";
|
||||
import {
|
||||
ACT_MODE_CONTINUATION_PROMPT,
|
||||
type AppliedModeChange,
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
sendTurnWithActModeContinuation,
|
||||
} from "./mode";
|
||||
|
||||
vi.mock("../prompt", () => ({
|
||||
vi.mock("@cline/cline-hub/connectors", () => ({
|
||||
resolveSystemPrompt: vi.fn(async (input: { mode?: string }) => {
|
||||
return `system prompt for ${input.mode ?? "unknown"}`;
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { resolveSystemPrompt } from "@cline/cline-hub/connectors";
|
||||
import { createTool } from "@cline/shared";
|
||||
import type { Config } from "../../utils/types";
|
||||
import { resolveSystemPrompt } from "../prompt";
|
||||
|
||||
export type InteractiveUiMode = "plan" | "act";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ChatCommandState } from "@cline/cline-hub/connectors";
|
||||
import type { TeamEvent } from "@cline/core";
|
||||
import type { ChatCommandState } from "../../utils/chat-commands";
|
||||
import type { Config } from "../../utils/types";
|
||||
import {
|
||||
CLI_DEFAULT_CHECKPOINT_CONFIG,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { ChatCommandState } from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
createSessionCompactionState,
|
||||
type ProviderSettingsManager,
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
} from "@cline/core";
|
||||
import type { AgentTool, Message } from "@cline/shared";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ChatCommandState } from "../../utils/chat-commands";
|
||||
import type { Config } from "../../utils/types";
|
||||
|
||||
const createCliCoreMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import type {
|
||||
ChatCommandState,
|
||||
ForkSessionResult,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
type AgentEvent,
|
||||
type AgentHooks,
|
||||
@@ -18,10 +22,6 @@ import {
|
||||
import type { Message } from "@cline/shared";
|
||||
import { createCliCore } from "../../session/session";
|
||||
import { submitAndExitInTerminal } from "../../utils/approval";
|
||||
import type {
|
||||
ChatCommandState,
|
||||
ForkSessionResult,
|
||||
} from "../../utils/chat-commands";
|
||||
import { createRuntimeHooks } from "../../utils/hooks";
|
||||
import { setActiveCliSession } from "../../utils/output";
|
||||
import { loadInteractiveResumeMessages } from "../../utils/resume";
|
||||
|
||||
@@ -105,7 +105,7 @@ vi.mock("./interactive-welcome", () => ({
|
||||
resolveClineWelcomeLine: vi.fn(async () => undefined),
|
||||
}));
|
||||
|
||||
vi.mock("./prompt", () => ({
|
||||
vi.mock("@cline/cline-hub/connectors", () => ({
|
||||
buildUserInputMessage: vi.fn(async () => ({
|
||||
prompt: "prompt",
|
||||
userImages: [],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { buildUserInputMessage } from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
type AgentEvent,
|
||||
type AgentResult,
|
||||
@@ -41,7 +42,6 @@ import {
|
||||
CLI_DEFAULT_LOOP_DETECTION,
|
||||
} from "./defaults";
|
||||
import { describeAbortSource, resolveMistakeLimitDecision } from "./format";
|
||||
import { buildUserInputMessage } from "./prompt";
|
||||
import { subscribeToAgentEvents } from "./session-events";
|
||||
|
||||
function printModelProviderInfo(config: Config): void {
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
import {
|
||||
buildUserInputMessage,
|
||||
type ChatCommandState,
|
||||
chatCommandHost,
|
||||
createWorkspaceChatCommandHost,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import {
|
||||
getCurrentContextSize,
|
||||
type ProviderSettings,
|
||||
@@ -24,7 +30,6 @@ import {
|
||||
} from "../tui/interactive-welcome";
|
||||
import { disableOpenTuiGraphicsProbe } from "../tui/opentui-env";
|
||||
import type { QueuedPromptItem } from "../tui/types";
|
||||
import { type ChatCommandState, chatCommandHost } from "../utils/chat-commands";
|
||||
import { applyCliCompactionMode } from "../utils/compaction-mode";
|
||||
import {
|
||||
shouldZeroClineFreeModelCost,
|
||||
@@ -36,7 +41,6 @@ import {
|
||||
writeErr,
|
||||
writeln,
|
||||
} from "../utils/output";
|
||||
import { createWorkspaceChatCommandHost } from "../utils/plugin-chat-commands";
|
||||
import { readRepoStatus } from "../utils/repo-status";
|
||||
import type { Config } from "../utils/types";
|
||||
import {
|
||||
@@ -62,7 +66,6 @@ import {
|
||||
} from "./interactive/mode";
|
||||
import { assertInteractivePreflight } from "./interactive/preflight";
|
||||
import { createInteractiveSessionRuntime } from "./interactive/session-runtime";
|
||||
import { buildUserInputMessage } from "./prompt";
|
||||
import { getUIEventEmitter } from "./session-events";
|
||||
|
||||
type ModelChangeReasoningConfig = {
|
||||
|
||||
@@ -6,7 +6,7 @@ const {
|
||||
startRuntimeSession,
|
||||
sendRuntimeSession,
|
||||
buildUserInputMessage,
|
||||
ensureCliHubServer,
|
||||
ensureHubServer,
|
||||
emitJsonLine,
|
||||
writeErr,
|
||||
writeln,
|
||||
@@ -16,7 +16,7 @@ const {
|
||||
startRuntimeSession: vi.fn(),
|
||||
sendRuntimeSession: vi.fn(),
|
||||
buildUserInputMessage: vi.fn(),
|
||||
ensureCliHubServer: vi.fn(),
|
||||
ensureHubServer: vi.fn(),
|
||||
emitJsonLine: vi.fn(),
|
||||
writeErr: vi.fn(),
|
||||
writeln: vi.fn(),
|
||||
@@ -31,12 +31,9 @@ vi.mock("@cline/core", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./prompt", () => ({
|
||||
vi.mock("@cline/cline-hub/connectors", () => ({
|
||||
buildUserInputMessage,
|
||||
}));
|
||||
|
||||
vi.mock("../utils/hub-runtime", () => ({
|
||||
ensureCliHubServer,
|
||||
ensureHubServer,
|
||||
}));
|
||||
|
||||
vi.mock("../utils/output", () => ({
|
||||
@@ -69,7 +66,7 @@ describe("runZen", () => {
|
||||
userImages: [],
|
||||
userFiles: [],
|
||||
});
|
||||
ensureCliHubServer.mockResolvedValue({
|
||||
ensureHubServer.mockResolvedValue({
|
||||
url: "ws://127.0.0.1:25463/hub",
|
||||
authToken: "test-token",
|
||||
});
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import {
|
||||
buildUserInputMessage,
|
||||
ensureHubServer,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import type { UserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core";
|
||||
import type { ChatStartSessionRequest } from "@cline/shared";
|
||||
import { resolveCliSessionMetadata } from "../utils/enterprise";
|
||||
import { ensureCliHubServer } from "../utils/hub-runtime";
|
||||
import { c, emitJsonLine, writeErr, writeln } from "../utils/output";
|
||||
import type { Config } from "../utils/types";
|
||||
import { buildUserInputMessage } from "./prompt";
|
||||
|
||||
const ZEN_DISPATCH_ACK_TIMEOUT_MS = 5_000;
|
||||
|
||||
@@ -51,7 +53,7 @@ export async function runZen(
|
||||
let hubUrl: string;
|
||||
let hubAuthToken: string;
|
||||
try {
|
||||
const hub = await ensureCliHubServer(workspaceRoot);
|
||||
const hub = await ensureHubServer(workspaceRoot);
|
||||
hubUrl = hub.url;
|
||||
hubAuthToken = hub.authToken;
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { resolveWorkspaceRoot } from "@cline/cline-hub/connectors";
|
||||
import type {
|
||||
AgentConfig,
|
||||
BasicLogger,
|
||||
@@ -16,7 +17,6 @@ import {
|
||||
prepareCliEnterpriseIntegration,
|
||||
} from "../utils/enterprise";
|
||||
import { getCliFeatureFlagsService } from "../utils/feature-flags";
|
||||
import { resolveWorkspaceRoot } from "../utils/helpers";
|
||||
import { getCliTelemetryService } from "../utils/telemetry";
|
||||
import type { ConversationHistory } from "./export";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
isImagePath,
|
||||
loadImageAsDataUrl,
|
||||
resolveExistingImagePath,
|
||||
} from "../../utils/image-attachments";
|
||||
} from "@cline/cline-hub/connectors";
|
||||
|
||||
const COMMAND_TIMEOUT_MS = 1500;
|
||||
const MAX_CLIPBOARD_BYTES = 20 * 1024 * 1024;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { appendFileSync, existsSync, unlinkSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
@@ -40,19 +39,6 @@ export function randomSessionId(): string {
|
||||
return `${Date.now()}_${nanoid(5)}_cli`;
|
||||
}
|
||||
|
||||
export function resolveWorkspaceRoot(cwd: string): string {
|
||||
const result = spawnSync("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
||||
encoding: "utf8",
|
||||
});
|
||||
if (result.status === 0) {
|
||||
const value = result.stdout.trim();
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
export function truncate(str: string, maxLen: number): string {
|
||||
const oneLine = str.replace(/\n/g, " ").trim();
|
||||
if (oneLine.length <= maxLen) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolveCliLaunchSpec } from "./internal-launch";
|
||||
import { resolveCliLaunchSpec } from "@cline/cline-hub/connectors";
|
||||
|
||||
export interface HistoryResumeCommand {
|
||||
launcher: string;
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"description": "Browser dashboard for the Cline hub: live clients, sessions, streaming chat, and hub restart.",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/server.ts"
|
||||
".": "./src/server.ts",
|
||||
"./connectors": "./src/connectors/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"build:webview": "bun run --cwd src/webview build",
|
||||
@@ -16,8 +17,18 @@
|
||||
"typecheck": "bun tsc -p tsconfig.json --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chat-adapter/discord": "^4.23.0",
|
||||
"@chat-adapter/gchat": "^4.23.0",
|
||||
"@chat-adapter/linear": "^4.23.0",
|
||||
"@chat-adapter/slack": "^4.23.0",
|
||||
"@chat-adapter/telegram": "^4.23.0",
|
||||
"@chat-adapter/whatsapp": "^4.23.0",
|
||||
"@cline/core": "workspace:*",
|
||||
"@cline/llms": "workspace:*",
|
||||
"@cline/shared": "workspace:*"
|
||||
"@cline/shared": "workspace:*",
|
||||
"@gramio/format": "^0.7.0",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"zod": "^4.3.6"
|
||||
}
|
||||
}
|
||||
|
||||
+19
-21
@@ -2,24 +2,15 @@ import {
|
||||
createDiscordAdapter,
|
||||
type DiscordAdapter,
|
||||
} from "@chat-adapter/discord";
|
||||
import type { ChatStartSessionRequest } from "@cline/core";
|
||||
import {
|
||||
createUserInstructionConfigService,
|
||||
HubSessionClient,
|
||||
} from "@cline/core";
|
||||
import { createUserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
ConnectDiscordOptions,
|
||||
DiscordConnectorState,
|
||||
} from "@cline/shared";
|
||||
import { Chat, ConsoleLogger, type Thread, ThreadImpl } from "chat";
|
||||
import type { Command } from "commander";
|
||||
import { createCliLoggerAdapter } from "../../logging/adapter";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultCliRpcAddress,
|
||||
} from "../../utils/hub-runtime";
|
||||
import { createWorkspaceChatCommandHost } from "../../utils/plugin-chat-commands";
|
||||
import { ConnectorBase } from "../base";
|
||||
import {
|
||||
createChatSdkLogger,
|
||||
@@ -33,6 +24,13 @@ import {
|
||||
maybeHandleConnectorApprovalReply,
|
||||
} from "../connector-host";
|
||||
import { dispatchConnectorHook } from "../hooks";
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultHubRpcAddress,
|
||||
} from "../hub-runtime";
|
||||
import { createConnectorLogger } from "../logger";
|
||||
import { createWorkspaceChatCommandHost } from "../plugin-chat-commands";
|
||||
import {
|
||||
type PendingConnectorApproval,
|
||||
truncateConnectorText,
|
||||
@@ -686,7 +684,7 @@ function isRestorableThread(
|
||||
async function restoreDiscordThreadSubscriptions(input: {
|
||||
bot: Pick<Chat, "reviver">;
|
||||
bindingsPath: string;
|
||||
logger: ReturnType<typeof createCliLoggerAdapter>;
|
||||
logger: ReturnType<typeof createConnectorLogger>;
|
||||
}): Promise<number> {
|
||||
const bindings = readBindings<DiscordThreadState>(input.bindingsPath);
|
||||
const restoredThreadIds = new Set<string>();
|
||||
@@ -761,7 +759,7 @@ class DiscordConnector extends ConnectorBase<
|
||||
.option(
|
||||
"--rpc-address <host:port>",
|
||||
"RPC address",
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultCliRpcAddress(),
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultHubRpcAddress(),
|
||||
)
|
||||
.option("--host <host>", "Webhook listen host")
|
||||
.option("--port <port>", "Webhook listen port")
|
||||
@@ -859,7 +857,7 @@ class DiscordConnector extends ConnectorBase<
|
||||
rpcAddress:
|
||||
opts.rpcAddress?.trim() ||
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() ||
|
||||
resolveDefaultCliRpcAddress(),
|
||||
resolveDefaultHubRpcAddress(),
|
||||
hookCommand:
|
||||
opts.hookCommand?.trim() ||
|
||||
process.env.CLINE_CONNECT_HOOK_COMMAND?.trim(),
|
||||
@@ -993,7 +991,7 @@ class DiscordConnector extends ConnectorBase<
|
||||
return 0;
|
||||
}
|
||||
|
||||
const loggerAdapter = createCliLoggerAdapter({
|
||||
const loggerAdapter = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: "discord-connect",
|
||||
});
|
||||
@@ -1039,11 +1037,10 @@ class DiscordConnector extends ConnectorBase<
|
||||
cwd: commandCwd,
|
||||
workspaceRoot: startRequest.workspaceRoot || commandCwd,
|
||||
});
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } =
|
||||
await ensureCliHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } = await ensureHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
|
||||
const clientId = `discord-${process.pid}-${Date.now()}`;
|
||||
const client = new HubSessionClient({
|
||||
@@ -1139,6 +1136,7 @@ class DiscordConnector extends ConnectorBase<
|
||||
resolveMuteTarget: ({ target }) => resolveDiscordMuteTarget(target),
|
||||
createEmptyRuntimeReplyResolver:
|
||||
createDiscordEmptyRuntimeReplyResolver,
|
||||
resolveSessionMetadata: io.resolveSessionMetadata,
|
||||
getSessionMetadata: (currentThread, _clientId, currentState) => ({
|
||||
userName: options.userName,
|
||||
applicationId: options.applicationId,
|
||||
+20
-22
@@ -1,23 +1,13 @@
|
||||
import { createGoogleChatAdapter } from "@chat-adapter/gchat";
|
||||
import type { ChatStartSessionRequest } from "@cline/core";
|
||||
import {
|
||||
createUserInstructionConfigService,
|
||||
HubSessionClient,
|
||||
} from "@cline/core";
|
||||
import { createUserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
ConnectGoogleChatOptions,
|
||||
GoogleChatConnectorState,
|
||||
} from "@cline/shared";
|
||||
import { Chat, ConsoleLogger, type Thread } from "chat";
|
||||
import type { Command } from "commander";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import { createCliLoggerAdapter } from "../../logging/adapter";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultCliRpcAddress,
|
||||
} from "../../utils/hub-runtime";
|
||||
import { createWorkspaceChatCommandHost } from "../../utils/plugin-chat-commands";
|
||||
import { ConnectorBase } from "../base";
|
||||
import {
|
||||
createChatSdkLogger,
|
||||
@@ -31,6 +21,13 @@ import {
|
||||
maybeHandleConnectorApprovalReply,
|
||||
} from "../connector-host";
|
||||
import { dispatchConnectorHook } from "../hooks";
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultHubRpcAddress,
|
||||
} from "../hub-runtime";
|
||||
import { createConnectorLogger } from "../logger";
|
||||
import { createWorkspaceChatCommandHost } from "../plugin-chat-commands";
|
||||
import {
|
||||
type PendingConnectorApproval,
|
||||
truncateConnectorText,
|
||||
@@ -55,6 +52,7 @@ import {
|
||||
import type {
|
||||
ConnectCommandDefinition,
|
||||
ConnectIo,
|
||||
ConnectorLoggerAdapter,
|
||||
ConnectStopResult,
|
||||
} from "../types";
|
||||
import {
|
||||
@@ -166,7 +164,7 @@ async function persistGoogleChatThreadContext(input: {
|
||||
async function deliverScheduledResult(input: {
|
||||
bot: Chat;
|
||||
client: HubSessionClient;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
bindingsPath: string;
|
||||
userName: string;
|
||||
scheduleId: string;
|
||||
@@ -253,7 +251,7 @@ class GoogleChatConnector extends ConnectorBase<
|
||||
.option(
|
||||
"--rpc-address <host:port>",
|
||||
"RPC address",
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultCliRpcAddress(),
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultHubRpcAddress(),
|
||||
)
|
||||
.option("--host <host>", "Webhook listen host")
|
||||
.option("--port <port>", "Webhook listen port")
|
||||
@@ -319,7 +317,7 @@ class GoogleChatConnector extends ConnectorBase<
|
||||
rpcAddress:
|
||||
opts.rpcAddress?.trim() ||
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() ||
|
||||
resolveDefaultCliRpcAddress(),
|
||||
resolveDefaultHubRpcAddress(),
|
||||
hookCommand:
|
||||
opts.hookCommand?.trim() ||
|
||||
process.env.CLINE_CONNECT_HOOK_COMMAND?.trim(),
|
||||
@@ -446,7 +444,7 @@ class GoogleChatConnector extends ConnectorBase<
|
||||
return 0;
|
||||
}
|
||||
|
||||
const loggerAdapter = createCliLoggerAdapter({
|
||||
const loggerAdapter = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: "gchat-connect",
|
||||
});
|
||||
@@ -543,11 +541,10 @@ class GoogleChatConnector extends ConnectorBase<
|
||||
cwd: commandCwd,
|
||||
workspaceRoot: startRequest.workspaceRoot || commandCwd,
|
||||
});
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } =
|
||||
await ensureCliHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } = await ensureHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
|
||||
const clientId = `gchat-${process.pid}-${Date.now()}`;
|
||||
const client = new HubSessionClient({
|
||||
@@ -614,6 +611,7 @@ class GoogleChatConnector extends ConnectorBase<
|
||||
chatCommandHost,
|
||||
activeTurns,
|
||||
turnKey: queueKey,
|
||||
resolveSessionMetadata: io.resolveSessionMetadata,
|
||||
getSessionMetadata: (currentThread, _clientId, currentState) => ({
|
||||
userName: options.userName,
|
||||
gchatThreadId: currentThread.id,
|
||||
+24
-23
@@ -1,19 +1,12 @@
|
||||
import type { ChatStartSessionRequest } from "@cline/core";
|
||||
import {
|
||||
createUserInstructionConfigService,
|
||||
HubSessionClient,
|
||||
} from "@cline/core";
|
||||
import type { ConnectLinearOptions, LinearConnectorState } from "@cline/shared";
|
||||
import { createUserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
ConnectLinearOptions,
|
||||
LinearConnectorState,
|
||||
} from "@cline/shared";
|
||||
import { type Adapter, Chat, ConsoleLogger, type Thread } from "chat";
|
||||
import type { Command } from "commander";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import { createCliLoggerAdapter } from "../../logging/adapter";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultCliRpcAddress,
|
||||
} from "../../utils/hub-runtime";
|
||||
import { createWorkspaceChatCommandHost } from "../../utils/plugin-chat-commands";
|
||||
import { ConnectorBase } from "../base";
|
||||
import {
|
||||
createChatSdkLogger,
|
||||
@@ -27,6 +20,13 @@ import {
|
||||
maybeHandleConnectorApprovalReply,
|
||||
} from "../connector-host";
|
||||
import { dispatchConnectorHook } from "../hooks";
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultHubRpcAddress,
|
||||
} from "../hub-runtime";
|
||||
import { createConnectorLogger } from "../logger";
|
||||
import { createWorkspaceChatCommandHost } from "../plugin-chat-commands";
|
||||
import {
|
||||
type PendingConnectorApproval,
|
||||
truncateConnectorText,
|
||||
@@ -51,6 +51,7 @@ import {
|
||||
import type {
|
||||
ConnectCommandDefinition,
|
||||
ConnectIo,
|
||||
ConnectorLoggerAdapter,
|
||||
ConnectStopResult,
|
||||
} from "../types";
|
||||
import { getConnectorSystemPrompt } from "./prompts";
|
||||
@@ -204,7 +205,7 @@ async function persistLinearThreadContext(input: {
|
||||
async function deliverScheduledResult(input: {
|
||||
bot: Chat;
|
||||
client: HubSessionClient;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
bindingsPath: string;
|
||||
userName: string;
|
||||
scheduleId: string;
|
||||
@@ -313,7 +314,7 @@ class LinearConnector extends ConnectorBase<
|
||||
.option(
|
||||
"--rpc-address <host:port>",
|
||||
"RPC address",
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultCliRpcAddress(),
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultHubRpcAddress(),
|
||||
)
|
||||
.option("--host <host>", "Webhook listen host")
|
||||
.option("--port <port>", "Webhook listen port")
|
||||
@@ -399,7 +400,7 @@ class LinearConnector extends ConnectorBase<
|
||||
rpcAddress:
|
||||
opts.rpcAddress?.trim() ||
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() ||
|
||||
resolveDefaultCliRpcAddress(),
|
||||
resolveDefaultHubRpcAddress(),
|
||||
hookCommand:
|
||||
opts.hookCommand?.trim() ||
|
||||
process.env.CLINE_CONNECT_HOOK_COMMAND?.trim(),
|
||||
@@ -513,7 +514,7 @@ class LinearConnector extends ConnectorBase<
|
||||
return 0;
|
||||
}
|
||||
|
||||
const loggerAdapter = createCliLoggerAdapter({
|
||||
const loggerAdapter = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: "linear-connect",
|
||||
});
|
||||
@@ -578,11 +579,10 @@ class LinearConnector extends ConnectorBase<
|
||||
cwd: commandCwd,
|
||||
workspaceRoot: startRequest.workspaceRoot || commandCwd,
|
||||
});
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } =
|
||||
await ensureCliHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } = await ensureHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
|
||||
const clientId = `linear-${process.pid}-${Date.now()}`;
|
||||
const client = new HubSessionClient({
|
||||
@@ -651,6 +651,7 @@ class LinearConnector extends ConnectorBase<
|
||||
chatCommandHost,
|
||||
activeTurns,
|
||||
turnKey: queueKey,
|
||||
resolveSessionMetadata: io.resolveSessionMetadata,
|
||||
getSessionMetadata: (currentThread, _clientId, currentState) => ({
|
||||
userName: options.userName,
|
||||
linearThreadId: currentThread.id,
|
||||
+24
-23
@@ -1,10 +1,11 @@
|
||||
import { createSlackAdapter, type SlackAdapter } from "@chat-adapter/slack";
|
||||
import type { ChatStartSessionRequest } from "@cline/core";
|
||||
import {
|
||||
createUserInstructionConfigService,
|
||||
HubSessionClient,
|
||||
} from "@cline/core";
|
||||
import type { ConnectSlackOptions, SlackConnectorState } from "@cline/shared";
|
||||
import { createUserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
ConnectSlackOptions,
|
||||
SlackConnectorState,
|
||||
} from "@cline/shared";
|
||||
import {
|
||||
type Adapter,
|
||||
Chat,
|
||||
@@ -14,14 +15,6 @@ import {
|
||||
ThreadImpl,
|
||||
} from "chat";
|
||||
import type { Command } from "commander";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import { createCliLoggerAdapter } from "../../logging/adapter";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultCliRpcAddress,
|
||||
} from "../../utils/hub-runtime";
|
||||
import { createWorkspaceChatCommandHost } from "../../utils/plugin-chat-commands";
|
||||
import { ConnectorBase } from "../base";
|
||||
import {
|
||||
createChatSdkLogger,
|
||||
@@ -35,6 +28,13 @@ import {
|
||||
maybeHandleConnectorApprovalReply,
|
||||
} from "../connector-host";
|
||||
import { dispatchConnectorHook } from "../hooks";
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultHubRpcAddress,
|
||||
} from "../hub-runtime";
|
||||
import { createConnectorLogger } from "../logger";
|
||||
import { createWorkspaceChatCommandHost } from "../plugin-chat-commands";
|
||||
import {
|
||||
type PendingConnectorApproval,
|
||||
truncateConnectorText,
|
||||
@@ -61,6 +61,7 @@ import {
|
||||
import type {
|
||||
ConnectCommandDefinition,
|
||||
ConnectIo,
|
||||
ConnectorLoggerAdapter,
|
||||
ConnectStopResult,
|
||||
} from "../types";
|
||||
import {
|
||||
@@ -351,7 +352,7 @@ async function deliverScheduledResult(input: {
|
||||
bot: Chat;
|
||||
slack: SlackAdapter;
|
||||
client: HubSessionClient;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
bindingsPath: string;
|
||||
userName: string;
|
||||
scheduleId: string;
|
||||
@@ -481,7 +482,7 @@ class SlackConnector extends ConnectorBase<
|
||||
.option(
|
||||
"--rpc-address <host:port>",
|
||||
"RPC address",
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultCliRpcAddress(),
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultHubRpcAddress(),
|
||||
)
|
||||
.option("--host <host>", "Webhook listen host")
|
||||
.option("--port <port>", "Webhook listen port")
|
||||
@@ -592,7 +593,7 @@ class SlackConnector extends ConnectorBase<
|
||||
rpcAddress:
|
||||
opts.rpcAddress?.trim() ||
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() ||
|
||||
resolveDefaultCliRpcAddress(),
|
||||
resolveDefaultHubRpcAddress(),
|
||||
hookCommand:
|
||||
opts.hookCommand?.trim() ||
|
||||
process.env.CLINE_CONNECT_HOOK_COMMAND?.trim(),
|
||||
@@ -707,7 +708,7 @@ class SlackConnector extends ConnectorBase<
|
||||
return 0;
|
||||
}
|
||||
|
||||
const loggerAdapter = createCliLoggerAdapter({
|
||||
const loggerAdapter = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: "slack-connect",
|
||||
});
|
||||
@@ -772,11 +773,10 @@ class SlackConnector extends ConnectorBase<
|
||||
cwd: commandCwd,
|
||||
workspaceRoot: startRequest.workspaceRoot || commandCwd,
|
||||
});
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } =
|
||||
await ensureCliHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } = await ensureHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
|
||||
const clientId = `slack-${process.pid}-${Date.now()}`;
|
||||
const client = new HubSessionClient({
|
||||
@@ -856,6 +856,7 @@ class SlackConnector extends ConnectorBase<
|
||||
chatCommandHost,
|
||||
activeTurns,
|
||||
turnKey: queueKey,
|
||||
resolveSessionMetadata: io.resolveSessionMetadata,
|
||||
getSessionMetadata: (
|
||||
currentThread,
|
||||
_clientId,
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import type { SentMessage, Thread } from "chat";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import type { ConnectorThreadState } from "../thread-bindings";
|
||||
import type { ConnectorLoggerAdapter } from "../types";
|
||||
import {
|
||||
buildTelegramFormattedPayload,
|
||||
buildTelegramFormattedPayloads,
|
||||
@@ -16,7 +16,7 @@ function createLogger() {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
},
|
||||
} as unknown as CliLoggerAdapter;
|
||||
} as unknown as ConnectorLoggerAdapter;
|
||||
}
|
||||
|
||||
function createThread(id = "telegram:123") {
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { markdownToFormattable } from "@gramio/format/markdown";
|
||||
import type { Thread } from "chat";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import type { ConnectorThreadState } from "../thread-bindings";
|
||||
import type { ConnectorLoggerAdapter } from "../types";
|
||||
|
||||
const TELEGRAM_API_BASE = "https://api.telegram.org";
|
||||
const TELEGRAM_MESSAGE_LIMIT = 4096;
|
||||
@@ -211,7 +211,7 @@ export async function postTelegramFormattedReply<
|
||||
thread: Thread<TState>;
|
||||
text: string;
|
||||
botToken: string;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
apiBaseUrl?: string;
|
||||
fetchImpl?: FetchLike;
|
||||
}): Promise<void> {
|
||||
+20
-22
@@ -1,23 +1,13 @@
|
||||
import { createTelegramAdapter } from "@chat-adapter/telegram";
|
||||
import type { ChatStartSessionRequest } from "@cline/core";
|
||||
import {
|
||||
createUserInstructionConfigService,
|
||||
HubSessionClient,
|
||||
} from "@cline/core";
|
||||
import { createUserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
ConnectTelegramOptions,
|
||||
TelegramConnectorState,
|
||||
} from "@cline/shared";
|
||||
import { Chat, ConsoleLogger, type Thread } from "chat";
|
||||
import type { Command } from "commander";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import { createCliLoggerAdapter } from "../../logging/adapter";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultCliRpcAddress,
|
||||
} from "../../utils/hub-runtime";
|
||||
import { createWorkspaceChatCommandHost } from "../../utils/plugin-chat-commands";
|
||||
import { ConnectorBase } from "../base";
|
||||
import { createChatSdkLogger, enqueueThreadTurn } from "../chat-runtime";
|
||||
import { isProcessRunning } from "../common";
|
||||
@@ -27,6 +17,13 @@ import {
|
||||
maybeHandleConnectorApprovalReply,
|
||||
} from "../connector-host";
|
||||
import { dispatchConnectorHook } from "../hooks";
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultHubRpcAddress,
|
||||
} from "../hub-runtime";
|
||||
import { createConnectorLogger } from "../logger";
|
||||
import { createWorkspaceChatCommandHost } from "../plugin-chat-commands";
|
||||
import {
|
||||
type PendingConnectorApproval,
|
||||
truncateConnectorText,
|
||||
@@ -51,6 +48,7 @@ import {
|
||||
import type {
|
||||
ConnectCommandDefinition,
|
||||
ConnectIo,
|
||||
ConnectorLoggerAdapter,
|
||||
ConnectStopResult,
|
||||
} from "../types";
|
||||
import {
|
||||
@@ -268,7 +266,7 @@ async function persistTelegramThreadContext(input: {
|
||||
async function deliverScheduledResult(input: {
|
||||
bot: Chat;
|
||||
client: HubSessionClient;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
bindingsPath: string;
|
||||
botUsername: string;
|
||||
scheduleId: string;
|
||||
@@ -443,7 +441,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
.option(
|
||||
"--rpc-address <host:port>",
|
||||
"RPC address",
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultCliRpcAddress(),
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultHubRpcAddress(),
|
||||
)
|
||||
.addHelpText(
|
||||
"after",
|
||||
@@ -508,7 +506,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
rpcAddress:
|
||||
opts.rpcAddress?.trim() ||
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() ||
|
||||
resolveDefaultCliRpcAddress(),
|
||||
resolveDefaultHubRpcAddress(),
|
||||
hookCommand: allowedUserId
|
||||
? buildTelegramAllowedUserHookCommand(
|
||||
normalizeAllowedTelegramUserId(allowedUserId),
|
||||
@@ -670,7 +668,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
return 0;
|
||||
}
|
||||
|
||||
const loggerAdapter = createCliLoggerAdapter({
|
||||
const loggerAdapter = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: "telegram-connect",
|
||||
});
|
||||
@@ -713,11 +711,10 @@ class TelegramConnector extends ConnectorBase<
|
||||
cwd: commandCwd,
|
||||
workspaceRoot: startRequest.workspaceRoot || commandCwd,
|
||||
});
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } =
|
||||
await ensureCliHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } = await ensureHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
|
||||
const clientId = `telegram-${process.pid}-${Date.now()}`;
|
||||
const client = new HubSessionClient({
|
||||
@@ -826,6 +823,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
logger: loggerAdapter,
|
||||
});
|
||||
},
|
||||
resolveSessionMetadata: io.resolveSessionMetadata,
|
||||
getSessionMetadata: (currentThread, _clientId, currentState) => ({
|
||||
botUserName: options.botUsername,
|
||||
telegramThreadId: currentThread.id,
|
||||
+20
-22
@@ -1,23 +1,13 @@
|
||||
import { createWhatsAppAdapter } from "@chat-adapter/whatsapp";
|
||||
import type { ChatStartSessionRequest } from "@cline/core";
|
||||
import {
|
||||
createUserInstructionConfigService,
|
||||
HubSessionClient,
|
||||
} from "@cline/core";
|
||||
import { createUserInstructionConfigService } from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
ConnectWhatsAppOptions,
|
||||
WhatsAppConnectorState,
|
||||
} from "@cline/shared";
|
||||
import { Chat, ConsoleLogger, type Thread } from "chat";
|
||||
import type { Command } from "commander";
|
||||
import type { CliLoggerAdapter } from "../../logging/adapter";
|
||||
import { createCliLoggerAdapter } from "../../logging/adapter";
|
||||
import {
|
||||
ensureCliHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultCliRpcAddress,
|
||||
} from "../../utils/hub-runtime";
|
||||
import { createWorkspaceChatCommandHost } from "../../utils/plugin-chat-commands";
|
||||
import { ConnectorBase } from "../base";
|
||||
import {
|
||||
createChatSdkLogger,
|
||||
@@ -31,6 +21,13 @@ import {
|
||||
maybeHandleConnectorApprovalReply,
|
||||
} from "../connector-host";
|
||||
import { dispatchConnectorHook } from "../hooks";
|
||||
import {
|
||||
ensureHubServer,
|
||||
parseHubEndpointOverride,
|
||||
resolveDefaultHubRpcAddress,
|
||||
} from "../hub-runtime";
|
||||
import { createConnectorLogger } from "../logger";
|
||||
import { createWorkspaceChatCommandHost } from "../plugin-chat-commands";
|
||||
import {
|
||||
type PendingConnectorApproval,
|
||||
truncateConnectorText,
|
||||
@@ -55,6 +52,7 @@ import {
|
||||
import type {
|
||||
ConnectCommandDefinition,
|
||||
ConnectIo,
|
||||
ConnectorLoggerAdapter,
|
||||
ConnectStopResult,
|
||||
} from "../types";
|
||||
import {
|
||||
@@ -190,7 +188,7 @@ async function persistWhatsAppThreadContext(input: {
|
||||
async function deliverScheduledResult(input: {
|
||||
bot: Chat;
|
||||
client: HubSessionClient;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
bindingsPath: string;
|
||||
options: ConnectWhatsAppOptions;
|
||||
scheduleId: string;
|
||||
@@ -296,7 +294,7 @@ class WhatsAppConnector extends ConnectorBase<
|
||||
.option(
|
||||
"--rpc-address <host:port>",
|
||||
"RPC address",
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultCliRpcAddress(),
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() || resolveDefaultHubRpcAddress(),
|
||||
)
|
||||
.option("--host <host>", "Webhook listen host")
|
||||
.option("--port <port>", "Webhook listen port")
|
||||
@@ -367,7 +365,7 @@ class WhatsAppConnector extends ConnectorBase<
|
||||
rpcAddress:
|
||||
opts.rpcAddress?.trim() ||
|
||||
process.env.CLINE_RPC_ADDRESS?.trim() ||
|
||||
resolveDefaultCliRpcAddress(),
|
||||
resolveDefaultHubRpcAddress(),
|
||||
hookCommand:
|
||||
opts.hookCommand?.trim() ||
|
||||
process.env.CLINE_CONNECT_HOOK_COMMAND?.trim(),
|
||||
@@ -485,7 +483,7 @@ class WhatsAppConnector extends ConnectorBase<
|
||||
return 0;
|
||||
}
|
||||
|
||||
const loggerAdapter = createCliLoggerAdapter({
|
||||
const loggerAdapter = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: "whatsapp-connect",
|
||||
});
|
||||
@@ -545,11 +543,10 @@ class WhatsAppConnector extends ConnectorBase<
|
||||
cwd: commandCwd,
|
||||
workspaceRoot: startRequest.workspaceRoot || commandCwd,
|
||||
});
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } =
|
||||
await ensureCliHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
const { url: rpcAddress, authToken: rpcAuthToken } = await ensureHubServer(
|
||||
startRequest.workspaceRoot || startRequest.cwd || process.cwd(),
|
||||
parseHubEndpointOverride(options.rpcAddress),
|
||||
);
|
||||
|
||||
const clientId = `whatsapp-${process.pid}-${Date.now()}`;
|
||||
const client = new HubSessionClient({
|
||||
@@ -623,6 +620,7 @@ class WhatsAppConnector extends ConnectorBase<
|
||||
chatCommandHost,
|
||||
activeTurns,
|
||||
turnKey: queueKey,
|
||||
resolveSessionMetadata: io.resolveSessionMetadata,
|
||||
getSessionMetadata: (currentThread, _clientId, currentState) => ({
|
||||
userName: options.userName,
|
||||
phoneNumberId: options.phoneNumberId,
|
||||
@@ -1,6 +1,6 @@
|
||||
import { existsSync, readdirSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { resolveClineDataDir } from "@cline/core";
|
||||
import { resolveClineDataDir } from "@cline/shared/storage";
|
||||
import { Command, CommanderError } from "commander";
|
||||
import {
|
||||
isProcessRunning,
|
||||
@@ -158,6 +158,7 @@ export abstract class ConnectorBase<Options, State>
|
||||
["connect", this.name],
|
||||
input.rawArgs,
|
||||
input.childEnvVar,
|
||||
input.io,
|
||||
);
|
||||
if (!pid) {
|
||||
input.io.writeErr(input.launchFailureMessage);
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { stat } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
import { resolveWorkspaceRoot } from "./helpers";
|
||||
import { resolveWorkspaceRoot } from "./workspace";
|
||||
|
||||
export type ChatCommandState = {
|
||||
enableTools: boolean;
|
||||
+13
-11
@@ -1,6 +1,6 @@
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import type { ConnectorLoggerAdapter } from "./types";
|
||||
|
||||
export function createChatSdkLogger(adapter: CliLoggerAdapter) {
|
||||
export function createChatSdkLogger(adapter: ConnectorLoggerAdapter) {
|
||||
return {
|
||||
child(prefix: string) {
|
||||
return createChatSdkLogger(adapter.child({ chatLogger: prefix }));
|
||||
@@ -80,18 +80,20 @@ export async function startConnectorWebhookServer(input: {
|
||||
const hostHeader = req.headers.host || `${input.host}:${input.port}`;
|
||||
const requestUrl = new URL(req.url || "/", `http://${hostHeader}`);
|
||||
const body = await readRequestBody(req);
|
||||
const headers = new Headers();
|
||||
for (const [key, value] of Object.entries(req.headers)) {
|
||||
if (Array.isArray(value)) {
|
||||
for (const entry of value) {
|
||||
headers.append(key, entry);
|
||||
}
|
||||
} else if (typeof value === "string") {
|
||||
headers.append(key, value);
|
||||
}
|
||||
}
|
||||
const request = new Request(requestUrl.toString(), {
|
||||
method: req.method,
|
||||
headers: new Headers(
|
||||
Object.entries(req.headers).flatMap(([key, value]) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((entry) => [key, entry] as [string, string]);
|
||||
}
|
||||
return typeof value === "string" ? [[key, value]] : [];
|
||||
}),
|
||||
),
|
||||
headers,
|
||||
body,
|
||||
duplex: body ? "half" : undefined,
|
||||
});
|
||||
const handler =
|
||||
input.routes[requestUrl.pathname] ??
|
||||
+9
-11
@@ -1,4 +1,4 @@
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
@@ -26,16 +26,15 @@ describe("spawnDetachedConnector", () => {
|
||||
});
|
||||
|
||||
it("preserves bun conditions and resolves the cli entrypoint for detached launches", () => {
|
||||
const connectorsDir = dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = resolve(connectorsDir, "../../../../");
|
||||
const entryPath = fileURLToPath(import.meta.url);
|
||||
expect(
|
||||
__test__.buildDetachedConnectorCommand(
|
||||
["connect", "telegram"],
|
||||
["-m", "ClineAdapterBot", "-k", "token-123"],
|
||||
"/Users/test/.bun/bin/bun",
|
||||
"./apps/cli/src/index.ts",
|
||||
entryPath,
|
||||
["--conditions=development"],
|
||||
repoRoot,
|
||||
dirname(entryPath),
|
||||
{},
|
||||
),
|
||||
).toEqual({
|
||||
@@ -44,7 +43,7 @@ describe("spawnDetachedConnector", () => {
|
||||
"--inspect=127.0.0.1:0",
|
||||
"--enable-source-maps",
|
||||
"--conditions=development",
|
||||
resolve(repoRoot, "apps/cli/src/index.ts"),
|
||||
entryPath,
|
||||
"connect",
|
||||
"telegram",
|
||||
"-m",
|
||||
@@ -57,16 +56,15 @@ describe("spawnDetachedConnector", () => {
|
||||
});
|
||||
|
||||
it("uses a dynamic connector inspector port for development node launches", () => {
|
||||
const connectorsDir = dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = resolve(connectorsDir, "../../../../");
|
||||
const entryPath = fileURLToPath(import.meta.url);
|
||||
expect(
|
||||
__test__.buildDetachedConnectorCommand(
|
||||
["connect", "telegram"],
|
||||
["-m", "ClineAdapterBot"],
|
||||
"/usr/local/bin/node",
|
||||
"./apps/cli/src/index.ts",
|
||||
entryPath,
|
||||
[],
|
||||
repoRoot,
|
||||
dirname(entryPath),
|
||||
{ CLINE_BUILD_ENV: "development" },
|
||||
),
|
||||
).toEqual({
|
||||
@@ -74,7 +72,7 @@ describe("spawnDetachedConnector", () => {
|
||||
childArgs: [
|
||||
"--inspect=127.0.0.1:0",
|
||||
"--enable-source-maps",
|
||||
resolve(repoRoot, "apps/cli/src/index.ts"),
|
||||
entryPath,
|
||||
"connect",
|
||||
"telegram",
|
||||
"-m",
|
||||
@@ -8,12 +8,12 @@ import {
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import type { HubSessionClient, HubSessionRow } from "@cline/core";
|
||||
import { ensureParentDir, resolveClineDataDir } from "@cline/core";
|
||||
import type { HubSessionClient, HubSessionRow } from "@cline/core/hub";
|
||||
import { withResolvedClineBuildEnv } from "@cline/shared";
|
||||
import { createCliLoggerAdapter } from "../logging/adapter";
|
||||
import { logSpawnedProcess } from "../logging/process";
|
||||
import { resolveCliLaunchSpec } from "../utils/internal-launch";
|
||||
import { ensureParentDir, resolveClineDataDir } from "@cline/shared/storage";
|
||||
import { resolveCliLaunchSpec } from "./internal-launch";
|
||||
import { createConnectorLogger } from "./logger";
|
||||
import type { ConnectIo } from "./types";
|
||||
|
||||
export function parseBooleanFlag(rawArgs: string[], flag: string): boolean {
|
||||
return rawArgs.includes(flag);
|
||||
@@ -154,6 +154,7 @@ export function spawnDetachedConnector(
|
||||
commandPrefixArgs: string[],
|
||||
rawArgs: string[],
|
||||
childEnvKey: string,
|
||||
io: ConnectIo,
|
||||
options?: {
|
||||
logPath?: string;
|
||||
component?: string;
|
||||
@@ -163,7 +164,7 @@ export function spawnDetachedConnector(
|
||||
const command = buildDetachedConnectorCommand(commandPrefixArgs, rawArgs);
|
||||
if (!command) {
|
||||
try {
|
||||
const logger = createCliLoggerAdapter({
|
||||
const logger = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: options?.component ?? "connectors",
|
||||
});
|
||||
@@ -198,24 +199,26 @@ export function spawnDetachedConnector(
|
||||
// processes otherwise allocate a new visible console.
|
||||
windowsHide: true,
|
||||
});
|
||||
logSpawnedProcess({
|
||||
createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: options?.component ?? "connectors",
|
||||
command: [command.launcher, ...command.childArgs],
|
||||
}).core.log("Process spawned", {
|
||||
command: [command.launcher, ...command.childArgs].join(" "),
|
||||
commandArgs: command.childArgs,
|
||||
executable: command.launcher,
|
||||
childPid: child.pid ?? undefined,
|
||||
cwd: process.cwd(),
|
||||
detached: true,
|
||||
metadata: {
|
||||
childEnvKey,
|
||||
purpose: "connector.detached",
|
||||
logPath: options?.logPath,
|
||||
...options?.metadata,
|
||||
},
|
||||
childEnvKey,
|
||||
purpose: "connector.detached",
|
||||
logPath: options?.logPath,
|
||||
...options?.metadata,
|
||||
});
|
||||
child.unref();
|
||||
return child.pid ?? 0;
|
||||
} catch (error) {
|
||||
try {
|
||||
const logger = createCliLoggerAdapter({
|
||||
const logger = createConnectorLogger(io, {
|
||||
runtime: "cli",
|
||||
component: options?.component ?? "connectors",
|
||||
});
|
||||
+9
-7
@@ -1,14 +1,12 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { basename } from "node:path";
|
||||
import type { UserInstructionConfigService } from "@cline/core";
|
||||
import type { HubSessionClient } from "@cline/core/hub";
|
||||
import type {
|
||||
ChatRunTurnRequest,
|
||||
ChatStartSessionRequest,
|
||||
HubSessionClient,
|
||||
UserInstructionConfigService,
|
||||
} from "@cline/core";
|
||||
} from "@cline/shared";
|
||||
import type { SentMessage, Thread } from "chat";
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import { buildUserInputMessage, resolveSystemPrompt } from "../runtime/prompt";
|
||||
import {
|
||||
type ChatCommandHost,
|
||||
type ChatCommandState,
|
||||
@@ -16,8 +14,9 @@ import {
|
||||
type MuteCommandInput,
|
||||
maybeHandleChatCommand,
|
||||
normalizeCommandName,
|
||||
} from "../utils/chat-commands";
|
||||
} from "./chat-commands";
|
||||
import { authorizeConnectorEvent, dispatchConnectorHook } from "./hooks";
|
||||
import { buildUserInputMessage, resolveSystemPrompt } from "./prompt";
|
||||
import {
|
||||
createConnectorRuntimeTurnStream,
|
||||
formatConnectorApprovalPrompt,
|
||||
@@ -44,6 +43,7 @@ import {
|
||||
setParticipantMuted,
|
||||
setThreadMuted,
|
||||
} from "./thread-bindings";
|
||||
import type { ConnectIo, ConnectorLoggerAdapter } from "./types";
|
||||
|
||||
export type ActiveConnectorTurn = {
|
||||
sessionId: string;
|
||||
@@ -211,7 +211,7 @@ export async function handleConnectorUserTurn<
|
||||
baseStartRequest: ChatStartSessionRequest;
|
||||
explicitSystemPrompt: string | undefined;
|
||||
clientId: string;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
transport: string;
|
||||
botUserName?: string;
|
||||
ownerParticipantKeys?: string[];
|
||||
@@ -225,6 +225,7 @@ export async function handleConnectorUserTurn<
|
||||
clientId: string,
|
||||
currentState: TState,
|
||||
) => Record<string, unknown>;
|
||||
resolveSessionMetadata?: ConnectIo["resolveSessionMetadata"];
|
||||
getScheduleDeliveryMetadata?: (
|
||||
thread: Thread<TState>,
|
||||
) => Record<string, unknown>;
|
||||
@@ -939,6 +940,7 @@ export async function handleConnectorUserTurn<
|
||||
input.clientId,
|
||||
currentState,
|
||||
),
|
||||
resolveSessionMetadata: input.resolveSessionMetadata,
|
||||
reusedLogMessage: input.reusedLogMessage,
|
||||
startedLogMessage: input.startedLogMessage,
|
||||
});
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
ConnectorHookEvent,
|
||||
} from "@cline/shared";
|
||||
import { z } from "zod";
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import type { ConnectorLoggerAdapter } from "./types";
|
||||
|
||||
const ConnectorAuthorizationDecisionSchema = z.object({
|
||||
action: z.enum(["allow", "deny"]).default("allow"),
|
||||
@@ -17,7 +17,7 @@ const ConnectorAuthorizationDecisionSchema = z.object({
|
||||
export async function dispatchConnectorHook(
|
||||
command: string | undefined,
|
||||
hookPayload: ConnectorHookEvent,
|
||||
logger: CliLoggerAdapter,
|
||||
logger: ConnectorLoggerAdapter,
|
||||
): Promise<void> {
|
||||
const trimmed = command?.trim();
|
||||
if (!trimmed) {
|
||||
@@ -70,7 +70,7 @@ export async function authorizeConnectorEvent(
|
||||
botUserName?: string;
|
||||
request: ConnectorAuthorizationRequest;
|
||||
},
|
||||
logger: CliLoggerAdapter,
|
||||
logger: ConnectorLoggerAdapter,
|
||||
): Promise<ConnectorAuthorizationDecision> {
|
||||
const trimmed = command?.trim();
|
||||
if (!trimmed) {
|
||||
@@ -4,14 +4,14 @@ import {
|
||||
type HubEndpointOverrides,
|
||||
resolveDefaultHubHost,
|
||||
resolveDefaultHubPort,
|
||||
} from "@cline/core";
|
||||
} from "@cline/core/hub";
|
||||
|
||||
/**
|
||||
* Build a `host:port` rpc address string that respects the current build
|
||||
* environment. In development, this picks the dev hub port to avoid
|
||||
* colliding with a production Cline hub on the standard port.
|
||||
*/
|
||||
export function resolveDefaultCliRpcAddress(): string {
|
||||
export function resolveDefaultHubRpcAddress(): string {
|
||||
return `${resolveDefaultHubHost()}:${resolveDefaultHubPort()}`;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export function parseHubEndpointOverride(
|
||||
}
|
||||
}
|
||||
|
||||
export async function ensureCliHubServer(
|
||||
export async function ensureHubServer(
|
||||
workspaceRoot: string,
|
||||
endpoint: HubEndpointOverrides = {},
|
||||
): Promise<DetachedHubResolution> {
|
||||
@@ -0,0 +1,12 @@
|
||||
export * from "./catalog";
|
||||
export * from "./chat-commands";
|
||||
export { isProcessRunning } from "./common";
|
||||
export * from "./hub-runtime";
|
||||
export * from "./image-attachments";
|
||||
export * from "./internal-launch";
|
||||
export * from "./plugin-chat-commands";
|
||||
export * from "./prompt";
|
||||
export * from "./registry";
|
||||
export * from "./status";
|
||||
export * from "./types";
|
||||
export * from "./workspace";
|
||||
+10
-12
@@ -1,4 +1,4 @@
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
@@ -14,13 +14,12 @@ describe("internal launch helpers", () => {
|
||||
});
|
||||
|
||||
it("resolves the source entrypoint when running from TypeScript", () => {
|
||||
const utilsDir = dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = resolve(utilsDir, "../../../../");
|
||||
const entryPath = fileURLToPath(import.meta.url);
|
||||
const spec = resolveCliLaunchSpec({
|
||||
execPath: "/Users/test/.bun/bin/bun",
|
||||
argv: ["bun", "./apps/cli/src/index.ts"],
|
||||
argv: ["bun", entryPath],
|
||||
execArgv: ["--conditions=development"],
|
||||
cwd: repoRoot,
|
||||
cwd: dirname(entryPath),
|
||||
env: {},
|
||||
});
|
||||
|
||||
@@ -30,9 +29,9 @@ describe("internal launch helpers", () => {
|
||||
"--inspect=127.0.0.1:0",
|
||||
"--enable-source-maps",
|
||||
"--conditions=development",
|
||||
resolve(repoRoot, "apps/cli/src/index.ts"),
|
||||
entryPath,
|
||||
],
|
||||
identityPath: resolve(repoRoot, "apps/cli/src/index.ts"),
|
||||
identityPath: entryPath,
|
||||
mode: "source",
|
||||
});
|
||||
});
|
||||
@@ -52,13 +51,12 @@ describe("internal launch helpers", () => {
|
||||
});
|
||||
|
||||
it("adds node debug flags for development node launches", () => {
|
||||
const utilsDir = dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = resolve(utilsDir, "../../../../");
|
||||
const entryPath = fileURLToPath(import.meta.url);
|
||||
const command = buildCliSubcommandCommand("hub", ["start"], {
|
||||
execPath: "/usr/local/bin/node",
|
||||
argv: ["node", "./apps/cli/src/index.ts"],
|
||||
argv: ["node", entryPath],
|
||||
execArgv: [],
|
||||
cwd: repoRoot,
|
||||
cwd: dirname(entryPath),
|
||||
env: { CLINE_BUILD_ENV: "development" },
|
||||
});
|
||||
|
||||
@@ -67,7 +65,7 @@ describe("internal launch helpers", () => {
|
||||
childArgs: [
|
||||
"--inspect=127.0.0.1:0",
|
||||
"--enable-source-maps",
|
||||
resolve(repoRoot, "apps/cli/src/index.ts"),
|
||||
entryPath,
|
||||
"hub",
|
||||
"start",
|
||||
],
|
||||
@@ -0,0 +1,39 @@
|
||||
import { join } from "node:path";
|
||||
import type { BasicLogger, RuntimeLoggerConfig } from "@cline/shared";
|
||||
import { noopBasicLogger } from "@cline/shared";
|
||||
import { resolveClineDataDir } from "@cline/shared/storage";
|
||||
import type {
|
||||
ConnectIo,
|
||||
ConnectorLoggerAdapter,
|
||||
CreateConnectorLoggerInput,
|
||||
} from "./types";
|
||||
|
||||
function normalizeRuntimeLoggerConfig(
|
||||
input: CreateConnectorLoggerInput,
|
||||
): Required<RuntimeLoggerConfig> {
|
||||
return {
|
||||
enabled: input.runtimeConfig?.enabled ?? false,
|
||||
level: input.runtimeConfig?.level ?? "info",
|
||||
destination:
|
||||
input.runtimeConfig?.destination ??
|
||||
join(resolveClineDataDir(), "logs", "cline.log"),
|
||||
name: input.runtimeConfig?.name ?? `cline.${input.runtime}`,
|
||||
bindings: input.runtimeConfig?.bindings ?? {},
|
||||
};
|
||||
}
|
||||
|
||||
export function createConnectorLogger(
|
||||
io: ConnectIo,
|
||||
input: CreateConnectorLoggerInput,
|
||||
): ConnectorLoggerAdapter {
|
||||
const hosted = io.createLogger?.(input);
|
||||
if (hosted) {
|
||||
return hosted;
|
||||
}
|
||||
const fallback: ConnectorLoggerAdapter = {
|
||||
core: noopBasicLogger as BasicLogger,
|
||||
runtimeConfig: normalizeRuntimeLoggerConfig(input),
|
||||
child: () => fallback,
|
||||
};
|
||||
return fallback;
|
||||
}
|
||||
+4
-3
@@ -1,11 +1,12 @@
|
||||
import { resolveAndLoadAgentPlugins } from "@cline/core";
|
||||
import {
|
||||
type AgentExtensionCommand,
|
||||
type AgentExtensionCommandResult,
|
||||
type AgentTool,
|
||||
type BasicLogger,
|
||||
createContributionRegistry,
|
||||
resolveAndLoadAgentPlugins,
|
||||
} from "@cline/core";
|
||||
import type { AgentTool, Message } from "@cline/shared";
|
||||
type Message,
|
||||
} from "@cline/shared";
|
||||
import {
|
||||
type ChatCommandDefinition,
|
||||
type ChatCommandHost,
|
||||
@@ -1,13 +1,10 @@
|
||||
import { statSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { basename, resolve } from "node:path";
|
||||
import {
|
||||
buildWorkspaceMetadata,
|
||||
mergeRulesForSystemPrompt,
|
||||
type UserInstructionConfigService,
|
||||
} from "@cline/core";
|
||||
import type { UserInstructionConfigService } from "@cline/core";
|
||||
import { buildWorkspaceMetadata, mergeRulesForSystemPrompt } from "@cline/core";
|
||||
import { type AgentMode, buildClineSystemPrompt } from "@cline/shared";
|
||||
import { isImagePath, loadImageAsDataUrl } from "../utils/image-attachments";
|
||||
import { isImagePath, loadImageAsDataUrl } from "./image-attachments";
|
||||
|
||||
const MODE_TAG_INSTRUCTIONS = `# Plan / Act Modes
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import { createConnectorRuntimeTurnStream } from "./runtime-turn";
|
||||
import type { ConnectorLoggerAdapter } from "./types";
|
||||
|
||||
type StreamHandlers = {
|
||||
onEvent: (event: {
|
||||
@@ -50,7 +50,7 @@ describe("createConnectorRuntimeTurnStream", () => {
|
||||
sessionId: "session-1",
|
||||
request,
|
||||
clientId: "client-1",
|
||||
logger: { core: {} } as unknown as CliLoggerAdapter,
|
||||
logger: { core: {} } as unknown as ConnectorLoggerAdapter,
|
||||
transport: "telegram",
|
||||
conversationId: "thread-1",
|
||||
onToolStatus: async (message) => {
|
||||
@@ -82,7 +82,7 @@ describe("createConnectorRuntimeTurnStream", () => {
|
||||
sessionId: "session-1",
|
||||
request: { config: {} as never, prompt: "hi" },
|
||||
clientId: "client-1",
|
||||
logger: { core: { log } } as unknown as CliLoggerAdapter,
|
||||
logger: { core: { log } } as unknown as ConnectorLoggerAdapter,
|
||||
transport: "discord",
|
||||
conversationId: "thread-1",
|
||||
})) {
|
||||
@@ -132,7 +132,7 @@ describe("createConnectorRuntimeTurnStream", () => {
|
||||
sessionId: "session-1",
|
||||
request: { config: {} as never, prompt: "hi" },
|
||||
clientId: "client-1",
|
||||
logger: { core: {} } as unknown as CliLoggerAdapter,
|
||||
logger: { core: {} } as unknown as ConnectorLoggerAdapter,
|
||||
transport: "telegram",
|
||||
conversationId: "thread-1",
|
||||
onFailed: async (error) => {
|
||||
@@ -179,7 +179,7 @@ describe("createConnectorRuntimeTurnStream", () => {
|
||||
sessionId: "session-1",
|
||||
request: { config: {} as never, prompt: "hi" },
|
||||
clientId: "client-1",
|
||||
logger: { core: {} } as unknown as CliLoggerAdapter,
|
||||
logger: { core: {} } as unknown as ConnectorLoggerAdapter,
|
||||
transport: "telegram",
|
||||
conversationId: "thread-1",
|
||||
onFailed: async (error) => {
|
||||
+4
-3
@@ -1,5 +1,6 @@
|
||||
import type { ChatRunTurnRequest, HubSessionClient } from "@cline/core";
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import type { HubSessionClient } from "@cline/core/hub";
|
||||
import type { ChatRunTurnRequest } from "@cline/shared";
|
||||
import type { ConnectorLoggerAdapter } from "./types";
|
||||
|
||||
export type PendingConnectorApproval = {
|
||||
approvalId: string;
|
||||
@@ -136,7 +137,7 @@ export function createConnectorRuntimeTurnStream(input: {
|
||||
sessionId: string;
|
||||
request: ChatRunTurnRequest;
|
||||
clientId: string;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
transport: string;
|
||||
conversationId: string;
|
||||
onToolStatus?: (message: string) => Promise<void>;
|
||||
+12
-32
@@ -1,17 +1,15 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const {
|
||||
mockGetLastUsedProviderSettings,
|
||||
mockGetProviderSettings,
|
||||
mockResolveSystemPrompt,
|
||||
mockGetProviderCollection,
|
||||
mockGetBooleanFlagEnabled,
|
||||
} = vi.hoisted(() => ({
|
||||
mockGetLastUsedProviderSettings: vi.fn(),
|
||||
mockGetProviderSettings: vi.fn(),
|
||||
mockResolveSystemPrompt: vi.fn(),
|
||||
mockGetProviderCollection: vi.fn(),
|
||||
mockGetBooleanFlagEnabled: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@cline/core", async () => {
|
||||
@@ -28,47 +26,29 @@ vi.mock("@cline/core", async () => {
|
||||
return mockGetProviderSettings(providerId);
|
||||
}
|
||||
},
|
||||
CoreSessionService: class {},
|
||||
SqliteSessionStore: class {},
|
||||
Llms: {
|
||||
...actual.Llms,
|
||||
getProviderCollection: mockGetProviderCollection,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../runtime/prompt", () => ({
|
||||
vi.mock("@cline/llms", async () => {
|
||||
const actual =
|
||||
await vi.importActual<typeof import("@cline/llms")>("@cline/llms");
|
||||
return {
|
||||
...actual,
|
||||
getProviderCollection: mockGetProviderCollection,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./prompt", () => ({
|
||||
resolveSystemPrompt: mockResolveSystemPrompt,
|
||||
}));
|
||||
|
||||
vi.mock("../utils/helpers", () => ({
|
||||
vi.mock("./workspace", () => ({
|
||||
resolveWorkspaceRoot: vi.fn((cwd: string) => cwd),
|
||||
}));
|
||||
|
||||
vi.mock("../utils/feature-flags", () => ({
|
||||
getCliFeatureFlagsService: () => ({
|
||||
getBooleanFlagEnabled: mockGetBooleanFlagEnabled,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("../commands/auth", async () => {
|
||||
const actual =
|
||||
await vi.importActual<typeof import("../commands/auth")>(
|
||||
"../commands/auth",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
ensureOAuthProviderApiKey: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
import { buildConnectorStartRequest } from "./session-runtime";
|
||||
|
||||
describe("buildConnectorStartRequest", () => {
|
||||
beforeEach(() => {
|
||||
mockGetBooleanFlagEnabled.mockReturnValue(false);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
delete process.env.OPENROUTER_API_KEY;
|
||||
+24
-21
@@ -1,22 +1,18 @@
|
||||
import type { ChatStartSessionRequest, RuntimeLoggerConfig } from "@cline/core";
|
||||
import {
|
||||
CoreSessionService,
|
||||
HubSessionClient,
|
||||
Llms,
|
||||
ProviderSettingsManager,
|
||||
SqliteSessionStore,
|
||||
} from "@cline/core";
|
||||
import type { Thread } from "chat";
|
||||
import {
|
||||
ensureOAuthProviderApiKey,
|
||||
getPersistedProviderApiKey,
|
||||
isOAuthProvider,
|
||||
normalizeProviderId,
|
||||
} from "../commands/auth";
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import { resolveSystemPrompt } from "../runtime/prompt";
|
||||
import { resolveCliSessionMetadata } from "../utils/enterprise";
|
||||
import { resolveWorkspaceRoot } from "../utils/helpers";
|
||||
ProviderSettingsManager,
|
||||
SqliteSessionStore,
|
||||
} from "@cline/core";
|
||||
import { HubSessionClient } from "@cline/core/hub";
|
||||
import * as Llms from "@cline/llms";
|
||||
import type {
|
||||
ChatStartSessionRequest,
|
||||
RuntimeLoggerConfig,
|
||||
} from "@cline/shared";
|
||||
import type { Thread } from "chat";
|
||||
import {
|
||||
parseLocalRowMetadata,
|
||||
parseRowMetadata,
|
||||
@@ -24,12 +20,14 @@ import {
|
||||
readSessionReplyText,
|
||||
} from "./common";
|
||||
import { dispatchConnectorHook } from "./hooks";
|
||||
import { resolveSystemPrompt } from "./prompt";
|
||||
import {
|
||||
type ConnectorThreadState,
|
||||
loadThreadState,
|
||||
persistMergedThreadState,
|
||||
} from "./thread-bindings";
|
||||
import type { ConnectIo } from "./types";
|
||||
import type { ConnectIo, ConnectorLoggerAdapter } from "./types";
|
||||
import { resolveWorkspaceRoot } from "./workspace";
|
||||
|
||||
async function resolveProviderApiKeyFromEnv(
|
||||
provider: string,
|
||||
@@ -83,12 +81,16 @@ export async function buildConnectorStartRequest(input: {
|
||||
"";
|
||||
|
||||
if (!apiKey && isOAuthProvider(provider)) {
|
||||
const oauthResult = await ensureOAuthProviderApiKey({
|
||||
if (!input.io.ensureProviderApiKey) {
|
||||
throw new Error(
|
||||
`Connector host cannot authenticate OAuth provider "${provider}"`,
|
||||
);
|
||||
}
|
||||
const oauthResult = await input.io.ensureProviderApiKey({
|
||||
providerId: provider,
|
||||
currentApiKey: apiKey,
|
||||
existingSettings: selectedProviderSettings,
|
||||
providerSettingsManager,
|
||||
io: input.io,
|
||||
});
|
||||
selectedProviderSettings = oauthResult.selectedProviderSettings;
|
||||
apiKey = oauthResult.apiKey ?? "";
|
||||
@@ -143,7 +145,7 @@ export async function getOrCreateSessionId<
|
||||
thread: Thread<TState>;
|
||||
client: HubSessionClient;
|
||||
startRequest: ChatStartSessionRequest;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
clientId: string;
|
||||
transport: string;
|
||||
bindingsPath: string;
|
||||
@@ -151,6 +153,7 @@ export async function getOrCreateSessionId<
|
||||
hookCommand?: string;
|
||||
hookBotUserName?: string;
|
||||
sessionMetadata: Record<string, unknown>;
|
||||
resolveSessionMetadata?: ConnectIo["resolveSessionMetadata"];
|
||||
reusedLogMessage: string;
|
||||
startedLogMessage?: string;
|
||||
}): Promise<string> {
|
||||
@@ -219,9 +222,9 @@ export async function getOrCreateSessionId<
|
||||
if (!sessionId) {
|
||||
throw new Error("runtime start returned an empty session id");
|
||||
}
|
||||
const remoteConfigMetadata = await resolveCliSessionMetadata(sessionId).catch(
|
||||
() => undefined,
|
||||
);
|
||||
const remoteConfigMetadata = await input
|
||||
.resolveSessionMetadata?.(sessionId)
|
||||
.catch(() => undefined);
|
||||
|
||||
await input.client
|
||||
.updateSession({
|
||||
@@ -1,6 +1,6 @@
|
||||
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { resolveClineDataDir } from "@cline/core";
|
||||
import { resolveClineDataDir } from "@cline/shared/storage";
|
||||
|
||||
function isProcessRunning(pid: number): boolean {
|
||||
if (!Number.isInteger(pid) || pid <= 0) {
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { ensureParentDir } from "@cline/core";
|
||||
import { ensureParentDir } from "@cline/shared/storage";
|
||||
import type { Lock, QueueEntry, StateAdapter } from "chat";
|
||||
|
||||
type PersistedStateSnapshot = {
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
import type { HubSessionClient } from "@cline/core";
|
||||
import type { HubSessionClient } from "@cline/core/hub";
|
||||
import type { TeamProgressProjectionEvent } from "@cline/shared";
|
||||
import type { Chat, Thread } from "chat";
|
||||
import type { CliLoggerAdapter } from "../logging/adapter";
|
||||
import { truncateConnectorText } from "./runtime-turn";
|
||||
import {
|
||||
type ConnectorThreadBinding,
|
||||
type ConnectorThreadState,
|
||||
readBindings,
|
||||
} from "./thread-bindings";
|
||||
import type { ConnectorLoggerAdapter } from "./types";
|
||||
|
||||
function formatCountLabel(input: {
|
||||
count: number;
|
||||
@@ -139,7 +139,7 @@ export function startConnectorTaskUpdateRelay<
|
||||
client: HubSessionClient;
|
||||
clientId: string;
|
||||
bot: Chat;
|
||||
logger: CliLoggerAdapter;
|
||||
logger: ConnectorLoggerAdapter;
|
||||
bindingsPath: string;
|
||||
transport: string;
|
||||
postToThread?: (input: {
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { ProviderSettings, ProviderSettingsManager } from "@cline/core";
|
||||
import type { BasicLogger, RuntimeLoggerConfig } from "@cline/shared";
|
||||
|
||||
export type ConnectorLoggerAdapter = {
|
||||
readonly core: BasicLogger;
|
||||
readonly runtimeConfig: RuntimeLoggerConfig;
|
||||
child(bindings: Record<string, unknown>): ConnectorLoggerAdapter;
|
||||
};
|
||||
|
||||
export type CreateConnectorLoggerInput = {
|
||||
runtime: "cli" | "rpc-runtime";
|
||||
component?: string;
|
||||
runtimeConfig?: RuntimeLoggerConfig;
|
||||
};
|
||||
|
||||
export type ConnectIo = {
|
||||
writeln: (text?: string) => void;
|
||||
writeErr: (text: string) => void;
|
||||
createLogger?: (input: CreateConnectorLoggerInput) => ConnectorLoggerAdapter;
|
||||
resolveSessionMetadata?: (
|
||||
sessionId: string,
|
||||
) => Promise<Record<string, unknown> | undefined>;
|
||||
ensureProviderApiKey?: (input: {
|
||||
providerId: string;
|
||||
currentApiKey?: string;
|
||||
existingSettings?: ProviderSettings;
|
||||
providerSettingsManager: ProviderSettingsManager;
|
||||
}) => Promise<{
|
||||
apiKey?: string;
|
||||
selectedProviderSettings?: ProviderSettings;
|
||||
}>;
|
||||
};
|
||||
|
||||
export type ConnectStopResult = {
|
||||
stoppedProcesses: number;
|
||||
stoppedSessions: number;
|
||||
};
|
||||
|
||||
export interface ConnectCommandDefinition {
|
||||
name: string;
|
||||
description: string;
|
||||
run(args: string[], io: ConnectIo): Promise<number>;
|
||||
showHelp(io: ConnectIo): void;
|
||||
stopAll?(io: ConnectIo): Promise<ConnectStopResult>;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
|
||||
export function resolveWorkspaceRoot(cwd: string): string {
|
||||
const result = spawnSync("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
||||
encoding: "utf8",
|
||||
});
|
||||
if (result.status === 0) {
|
||||
const value = result.stdout.trim();
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
@@ -2,9 +2,11 @@ import { spawn } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { basename } from "node:path";
|
||||
import process from "node:process";
|
||||
import {
|
||||
listActiveConnectors,
|
||||
listConnectorCatalog,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import { withResolvedClineBuildEnv } from "@cline/shared";
|
||||
import { listConnectorCatalog } from "../../../cli/src/connectors/catalog";
|
||||
import { listActiveConnectors } from "../../../cli/src/connectors/status";
|
||||
import {
|
||||
PLATFORMS,
|
||||
shouldIncludeField,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { listActiveConnectors } from "../../../cli/src/connectors/status";
|
||||
import { listActiveConnectors } from "@cline/cline-hub/connectors";
|
||||
import type { WebviewHubState } from "../webview-protocol";
|
||||
import {
|
||||
clientSummariesPayload,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"clean": "rm -rf webview/.next webview/out node_modules dist && (cd src-tauri && rm -rf target node_modules dist)"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cline/cline-hub": "workspace:*",
|
||||
"@base-ui/react": "^1.2.0",
|
||||
"@cline/core": "workspace:*",
|
||||
"@cline/llms": "workspace:*",
|
||||
|
||||
@@ -2,9 +2,11 @@ import { spawn } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { basename, join, normalize } from "node:path";
|
||||
import process from "node:process";
|
||||
import {
|
||||
listActiveConnectors,
|
||||
listConnectorCatalog,
|
||||
} from "@cline/cline-hub/connectors";
|
||||
import { withResolvedClineBuildEnv } from "@cline/shared";
|
||||
import { listConnectorCatalog } from "../../../cli/src/connectors/catalog";
|
||||
import { listActiveConnectors } from "../../../cli/src/connectors/status";
|
||||
import {
|
||||
PLATFORMS,
|
||||
shouldIncludeField,
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
"@/*": ["./*"],
|
||||
"@cline/agents": ["../../../sdk/packages/agents/src/index.ts"],
|
||||
"@cline/core": ["../../../sdk/packages/core/src/index.ts"],
|
||||
"@cline/cline-hub/connectors": [
|
||||
"../../../apps/cline-hub/src/connectors/index.ts"
|
||||
],
|
||||
"@cline/core/hub": ["../../../sdk/packages/core/src/hub/index.ts"],
|
||||
"@cline/llms": ["../../../sdk/packages/llms/src/index.ts"],
|
||||
"@cline/shared": ["../../../sdk/packages/shared/src/index.ts"],
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
"@/*": ["./*"],
|
||||
"@cline/agents": ["../../../sdk/packages/agents/src/index.ts"],
|
||||
"@cline/core": ["../../../sdk/packages/core/src/index.ts"],
|
||||
"@cline/cline-hub/connectors": [
|
||||
"../../../apps/cline-hub/src/connectors/index.ts"
|
||||
],
|
||||
"@cline/core/hub": ["../../../sdk/packages/core/src/hub/index.ts"],
|
||||
"@cline/llms": ["../../../sdk/packages/llms/src/index.ts"],
|
||||
"@cline/shared": ["../../../sdk/packages/shared/src/index.ts"],
|
||||
|
||||
@@ -19,25 +19,17 @@
|
||||
},
|
||||
"apps/cli": {
|
||||
"name": "@cline/cli",
|
||||
"version": "3.0.38",
|
||||
"version": "3.0.39",
|
||||
"bin": {
|
||||
"cline": "src/index.ts",
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.16.1",
|
||||
"@chat-adapter/discord": "^4.23.0",
|
||||
"@chat-adapter/gchat": "^4.23.0",
|
||||
"@chat-adapter/linear": "^4.23.0",
|
||||
"@chat-adapter/slack": "^4.23.0",
|
||||
"@chat-adapter/telegram": "^4.23.0",
|
||||
"@chat-adapter/whatsapp": "^4.23.0",
|
||||
"@clack/prompts": "^1.2.0",
|
||||
"@cline/cline-hub": "workspace:*",
|
||||
"@gramio/format": "^0.7.0",
|
||||
"@opentui-ui/dialog": "^0.1.2",
|
||||
"@opentui/core": "0.1.102",
|
||||
"@opentui/react": "0.1.102",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"fzf": "^0.5.2",
|
||||
"marked": "^15.0.12",
|
||||
@@ -65,9 +57,19 @@
|
||||
"name": "@cline/cline-hub",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@chat-adapter/discord": "^4.23.0",
|
||||
"@chat-adapter/gchat": "^4.23.0",
|
||||
"@chat-adapter/linear": "^4.23.0",
|
||||
"@chat-adapter/slack": "^4.23.0",
|
||||
"@chat-adapter/telegram": "^4.23.0",
|
||||
"@chat-adapter/whatsapp": "^4.23.0",
|
||||
"@cline/core": "workspace:*",
|
||||
"@cline/llms": "workspace:*",
|
||||
"@cline/shared": "workspace:*",
|
||||
"@gramio/format": "^0.7.0",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"zod": "^4.3.6",
|
||||
},
|
||||
},
|
||||
"apps/cline-hub/src/webview": {
|
||||
@@ -164,6 +166,7 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.2.0",
|
||||
"@cline/cline-hub": "workspace:*",
|
||||
"@cline/core": "workspace:*",
|
||||
"@cline/llms": "workspace:*",
|
||||
"@cline/shared": "workspace:*",
|
||||
|
||||
+6
-1
@@ -21,7 +21,11 @@ Run SDK commands from `sdk/`, not from the legacy repository root. Do not run di
|
||||
- `@cline/shared`: shared contracts, schemas, path helpers, hook engine, extension registry, low-level utilities
|
||||
- `@cline/llms`: provider settings/config, model catalogs, provider manifests, gateway contracts, handler creation
|
||||
- `@cline/agents`: stateless agent loop, tool orchestration, hook/extension runtime, event streaming
|
||||
- `@cline/core`: stateful orchestration, session lifecycle, storage, config watching, plugin loading, default tools, telemetry. Exposes `@cline/core/hub` for discovery, the detached daemon entry, WebSocket clients, and session/UI client adapters, plus `@cline/core/hub/daemon-entry` for launching the shared daemon
|
||||
- `@cline/core`: stateful orchestration, session lifecycle, storage, config watching, plugin loading, default tools, and telemetry. Exposes `@cline/core/hub` for discovery, the detached daemon entry, WebSocket clients, and session/UI client adapters, plus `@cline/core/hub/daemon-entry` for launching the shared daemon
|
||||
|
||||
### Hub App Package
|
||||
|
||||
- `@cline/cline-hub`: Hub dashboard/server behavior and chat connector runtimes exposed through `@cline/cline-hub/connectors`
|
||||
|
||||
### Dependency Direction
|
||||
|
||||
@@ -47,6 +51,7 @@ Route changes to the package that owns the concern:
|
||||
- session lifecycle, storage, config watching, default tools, plugin loading, telemetry, hub runtime services, hub discovery, hub daemon spawn, and session-oriented client helpers (`HubSessionClient`, `HubUIClient`, `connectToHub`): `@cline/core` (hub pieces live under `src/hub/`)
|
||||
- remote-config schemas, managed instruction materialization, blob upload metadata, and OpenTelemetry config normalization: `@cline/shared/src/remote-config`
|
||||
- host-specific UX or shell behavior: app package
|
||||
- chat connector runtimes, adapters, command handling, and process state: `@cline/cline-hub/connectors`
|
||||
|
||||
## Verifying Changes
|
||||
|
||||
|
||||
@@ -114,6 +114,19 @@ Design rules:
|
||||
- `server/` contains WebSocket server startup, native/browser socket adapters, server transport, server helpers, and `handlers/` for hub command dispatch
|
||||
- settings mutations belong in core services and hub commands, not in host-specific file writes. Hosts should call the core settings facade or the `settings.*` hub command family and react to `settings.changed`.
|
||||
|
||||
### `@cline/cline-hub`
|
||||
|
||||
Owns Hub application behavior:
|
||||
|
||||
- chat connector runtimes and transport adapters
|
||||
- connector command handling, thread bindings, and process state
|
||||
- connector discovery and management surfaces for Hub hosts
|
||||
- the `@cline/cline-hub/connectors` entrypoint
|
||||
|
||||
Design rule:
|
||||
|
||||
- connector behavior belongs in the Hub package; CLI and other hosts provide only host-owned services such as logging, interactive provider authentication, and app-specific session metadata through `ConnectIo`.
|
||||
|
||||
## Runtime Flows
|
||||
|
||||
### Local In-Process Runtime
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ cline connect telegram -k "$TELEGRAM_BOT_TOKEN"
|
||||
# Then send /help or /start to the bot in Telegram
|
||||
```
|
||||
|
||||
For Telegram-specific connector behavior, see [`apps/cli/src/connectors/adapters/telegram.md`](./apps/cli/src/connectors/adapters/telegram.md).
|
||||
For Telegram-specific connector behavior, see [`apps/cline-hub/src/connectors/adapters/telegram.md`](../apps/cline-hub/src/connectors/adapters/telegram.md).
|
||||
|
||||
## Providers
|
||||
|
||||
|
||||
Reference in New Issue
Block a user