@ai-sdk/harness-cline 1.0.18 → 1.0.20
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/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/dist/index.d.ts +9 -5
- package/dist/index.js +188 -93
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/cline-auth.ts +23 -9
- package/src/cline-harness.ts +22 -4
- package/src/cline-remote-ops.ts +5 -29
- package/src/cline-session.ts +44 -44
- package/src/cline-skills.ts +173 -48
- package/src/cline-tools.ts +5 -3
- package/src/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-cline",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-sdk/harness": "1.0.
|
|
29
|
+
"@ai-sdk/harness": "1.0.93",
|
|
30
30
|
"@ai-sdk/provider": "4.0.8",
|
|
31
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
32
|
-
"@cline/agents": "^0.0.
|
|
33
|
-
"@cline/core": "^0.0.
|
|
31
|
+
"@ai-sdk/provider-utils": "5.0.33",
|
|
32
|
+
"@cline/agents": "^0.0.79",
|
|
33
|
+
"@cline/core": "^0.0.79"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"zod": "^3.25.76 || ^4.1.8"
|
package/src/cline-auth.ts
CHANGED
|
@@ -1,31 +1,45 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { HarnessV1Authentication } from '@ai-sdk/harness';
|
|
2
|
+
import {
|
|
3
|
+
getAiGatewayAuthFromEnv,
|
|
4
|
+
isHarnessAuthenticationEnvironment,
|
|
5
|
+
} from '@ai-sdk/harness/utils';
|
|
2
6
|
|
|
3
|
-
export type ClineAuthenticationMode =
|
|
4
|
-
|
|
5
|
-
export type ClineAuthOptions = ClineAuthenticationMode;
|
|
7
|
+
export type ClineAuthenticationMode = HarnessV1Authentication;
|
|
6
8
|
|
|
7
9
|
export function resolveClineEnv({
|
|
8
10
|
auth = 'auto',
|
|
9
11
|
env = process.env,
|
|
10
12
|
}: {
|
|
11
|
-
auth?:
|
|
13
|
+
auth?: ClineAuthenticationMode;
|
|
12
14
|
env?: Record<string, string | undefined>;
|
|
13
15
|
}): Record<string, string> {
|
|
16
|
+
if (isHarnessAuthenticationEnvironment(auth)) {
|
|
17
|
+
const gatewayAuth = getAiGatewayAuthFromEnv({ env: auth });
|
|
18
|
+
return gatewayAuth.apiKey
|
|
19
|
+
? toGatewayClineEnv(gatewayAuth)
|
|
20
|
+
: pickDirectClineEnv({ env: auth });
|
|
21
|
+
}
|
|
14
22
|
if (auth === 'direct') {
|
|
15
23
|
return pickDirectClineEnv({ env });
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
const gatewayAuth = getAiGatewayAuthFromEnv({ env });
|
|
19
27
|
if (auth === 'ai-gateway' || gatewayAuth.apiKey) {
|
|
20
|
-
return
|
|
21
|
-
...(gatewayAuth.apiKey ? { AI_GATEWAY_API_KEY: gatewayAuth.apiKey } : {}),
|
|
22
|
-
AI_GATEWAY_BASE_URL: gatewayAuth.baseUrl,
|
|
23
|
-
};
|
|
28
|
+
return toGatewayClineEnv(gatewayAuth);
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
return pickDirectClineEnv({ env });
|
|
27
32
|
}
|
|
28
33
|
|
|
34
|
+
function toGatewayClineEnv(
|
|
35
|
+
gatewayAuth: ReturnType<typeof getAiGatewayAuthFromEnv>,
|
|
36
|
+
): Record<string, string> {
|
|
37
|
+
return {
|
|
38
|
+
...(gatewayAuth.apiKey ? { AI_GATEWAY_API_KEY: gatewayAuth.apiKey } : {}),
|
|
39
|
+
AI_GATEWAY_BASE_URL: gatewayAuth.baseUrl,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
29
43
|
function pickDirectClineEnv({
|
|
30
44
|
env,
|
|
31
45
|
}: {
|
package/src/cline-harness.ts
CHANGED
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
type HarnessV1,
|
|
4
4
|
type HarnessV1BuiltinTool,
|
|
5
5
|
} from '@ai-sdk/harness';
|
|
6
|
+
import { isHarnessAuthenticationEnvironment } from '@ai-sdk/harness/utils';
|
|
6
7
|
import { tool } from '@ai-sdk/provider-utils';
|
|
7
8
|
import { z } from 'zod/v4';
|
|
8
|
-
import { resolveClineEnv, type
|
|
9
|
+
import { resolveClineEnv, type ClineAuthenticationMode } from './cline-auth';
|
|
9
10
|
import { clineResumeStateSchema } from './cline-resume-state';
|
|
10
11
|
import { createClineSession, type ClineReasoningEffort } from './cline-session';
|
|
11
12
|
import { VERSION } from './version';
|
|
@@ -22,7 +23,7 @@ const CLINE_CLIENT_APP = `ai-sdk/harness-cline/${VERSION}`;
|
|
|
22
23
|
*/
|
|
23
24
|
export type ClineHarnessSettings = {
|
|
24
25
|
/** Where Cline sources direct or AI Gateway credentials from. */
|
|
25
|
-
readonly auth?:
|
|
26
|
+
readonly auth?: ClineAuthenticationMode;
|
|
26
27
|
/**
|
|
27
28
|
* MCP server definitions keyed by server name. Each definition uses the
|
|
28
29
|
* underlying runtime's native MCP server configuration format.
|
|
@@ -36,11 +37,14 @@ export type ClineHarnessSettings = {
|
|
|
36
37
|
/**
|
|
37
38
|
* Model id for the configured provider. When omitted, Cline selects the
|
|
38
39
|
* provider's default model.
|
|
40
|
+
*
|
|
41
|
+
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
39
42
|
*/
|
|
40
43
|
readonly modelId?: string;
|
|
41
44
|
/**
|
|
42
45
|
* Provider API key. When omitted, the Cline gateway falls back to the
|
|
43
46
|
* provider's environment variable (e.g. `ANTHROPIC_API_KEY`).
|
|
47
|
+
* A record-shaped authentication override disables that fallback.
|
|
44
48
|
*/
|
|
45
49
|
readonly apiKey?: string;
|
|
46
50
|
/** Custom provider endpoint. */
|
|
@@ -138,6 +142,18 @@ const CLINE_BUILTIN_TOOLS = {
|
|
|
138
142
|
nativeName: 'ls',
|
|
139
143
|
toolUseKind: 'readonly',
|
|
140
144
|
} as HarnessV1BuiltinTool,
|
|
145
|
+
skills: {
|
|
146
|
+
...tool({
|
|
147
|
+
description: 'Execute a configured skill by name.',
|
|
148
|
+
inputSchema: z.object({
|
|
149
|
+
skill: z.string(),
|
|
150
|
+
args: z.string().optional(),
|
|
151
|
+
}),
|
|
152
|
+
outputSchema: z.string(),
|
|
153
|
+
}),
|
|
154
|
+
nativeName: 'skills',
|
|
155
|
+
toolUseKind: 'readonly',
|
|
156
|
+
} as HarnessV1BuiltinTool,
|
|
141
157
|
} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;
|
|
142
158
|
|
|
143
159
|
export function createCline(
|
|
@@ -151,6 +167,7 @@ export function createCline(
|
|
|
151
167
|
supportsBuiltinToolFiltering: true,
|
|
152
168
|
lifecycleStateSchema: clineResumeStateSchema,
|
|
153
169
|
doStart: async startOpts => {
|
|
170
|
+
const modelId = startOpts.model ?? settings.modelId;
|
|
154
171
|
const authEnv = resolveClineEnv({ auth: settings.auth });
|
|
155
172
|
const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
|
|
156
173
|
const resumeData = lifecycleState?.data as
|
|
@@ -161,12 +178,13 @@ export function createCline(
|
|
|
161
178
|
sessionId: startOpts.sessionId,
|
|
162
179
|
sandboxSession: startOpts.sandboxSession,
|
|
163
180
|
sessionWorkDir: startOpts.sessionWorkDir,
|
|
164
|
-
skills: startOpts.skills ?? [],
|
|
165
181
|
settings: {
|
|
166
182
|
authEnv,
|
|
183
|
+
isAuthenticationEnvironmentOverride:
|
|
184
|
+
isHarnessAuthenticationEnvironment(settings.auth),
|
|
167
185
|
...(settings.mcpServers ? { mcpServers: settings.mcpServers } : {}),
|
|
168
186
|
...(settings.providerId ? { providerId: settings.providerId } : {}),
|
|
169
|
-
...(
|
|
187
|
+
...(modelId == null ? {} : { modelId }),
|
|
170
188
|
...(settings.apiKey ? { apiKey: settings.apiKey } : {}),
|
|
171
189
|
...(settings.baseUrl ? { baseUrl: settings.baseUrl } : {}),
|
|
172
190
|
...(settings.headers ? { headers: settings.headers } : {}),
|
package/src/cline-remote-ops.ts
CHANGED
|
@@ -14,7 +14,6 @@ export interface ClineRemoteOpsOptions {
|
|
|
14
14
|
readonly sandbox: Experimental_SandboxSession;
|
|
15
15
|
/** Absolute sandbox path of the session's working directory. */
|
|
16
16
|
readonly workDir: string;
|
|
17
|
-
readonly readableRoots?: ReadonlyArray<{ readonly sandboxDir: string }>;
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
export interface ClineRemoteOps {
|
|
@@ -50,9 +49,6 @@ export function createClineRemoteOps(
|
|
|
50
49
|
): ClineRemoteOps {
|
|
51
50
|
const { sandbox, workDir } = options;
|
|
52
51
|
const normalizedWorkDir = path.posix.normalize(workDir);
|
|
53
|
-
const readableRoots =
|
|
54
|
-
options.readableRoots?.map(root => path.posix.normalize(root.sandboxDir)) ??
|
|
55
|
-
[];
|
|
56
52
|
|
|
57
53
|
const isInsidePath = ({
|
|
58
54
|
parent,
|
|
@@ -78,19 +74,6 @@ export function createClineRemoteOps(
|
|
|
78
74
|
return normalized;
|
|
79
75
|
};
|
|
80
76
|
|
|
81
|
-
const assertReadablePath = (inputPath: string): string => {
|
|
82
|
-
const normalized = path.posix.normalize(inputPath);
|
|
83
|
-
if (
|
|
84
|
-
!isInsidePath({ parent: normalizedWorkDir, candidate: normalized }) &&
|
|
85
|
-
!readableRoots.some(parent =>
|
|
86
|
-
isInsidePath({ parent, candidate: normalized }),
|
|
87
|
-
)
|
|
88
|
-
) {
|
|
89
|
-
throw new Error(`Cline path escapes the readable roots: ${inputPath}`);
|
|
90
|
-
}
|
|
91
|
-
return normalized;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
77
|
const resolvePath = (inputPath: string): string => {
|
|
95
78
|
const resolved = path.posix.isAbsolute(inputPath)
|
|
96
79
|
? path.posix.normalize(inputPath)
|
|
@@ -98,13 +81,6 @@ export function createClineRemoteOps(
|
|
|
98
81
|
return assertWorkspacePath(resolved);
|
|
99
82
|
};
|
|
100
83
|
|
|
101
|
-
const resolveReadablePath = (inputPath: string): string => {
|
|
102
|
-
if (!path.posix.isAbsolute(inputPath)) {
|
|
103
|
-
return resolvePath(inputPath);
|
|
104
|
-
}
|
|
105
|
-
return assertReadablePath(inputPath);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
84
|
const runShell = async ({
|
|
109
85
|
command,
|
|
110
86
|
signal,
|
|
@@ -172,7 +148,7 @@ export function createClineRemoteOps(
|
|
|
172
148
|
inputPath: string;
|
|
173
149
|
missingMessage?: string;
|
|
174
150
|
}): Promise<string> =>
|
|
175
|
-
|
|
151
|
+
assertWorkspacePath(
|
|
176
152
|
await resolveExistingSandboxPath({
|
|
177
153
|
remotePath,
|
|
178
154
|
inputPath,
|
|
@@ -216,7 +192,7 @@ export function createClineRemoteOps(
|
|
|
216
192
|
};
|
|
217
193
|
|
|
218
194
|
const readFile = async (inputPath: string): Promise<string> => {
|
|
219
|
-
const remotePath =
|
|
195
|
+
const remotePath = resolvePath(inputPath);
|
|
220
196
|
const resolved = await resolveReadableSandboxPath({
|
|
221
197
|
remotePath,
|
|
222
198
|
inputPath,
|
|
@@ -305,7 +281,7 @@ export function createClineRemoteOps(
|
|
|
305
281
|
|
|
306
282
|
async grep(pattern, input = {}) {
|
|
307
283
|
const inputPath = input.path ?? '.';
|
|
308
|
-
const remotePath =
|
|
284
|
+
const remotePath = resolvePath(inputPath);
|
|
309
285
|
const target = await resolveReadableSandboxPath({
|
|
310
286
|
remotePath,
|
|
311
287
|
inputPath,
|
|
@@ -341,7 +317,7 @@ export function createClineRemoteOps(
|
|
|
341
317
|
},
|
|
342
318
|
|
|
343
319
|
async glob(pattern, inputPath = '.', limit = 1_000) {
|
|
344
|
-
const remotePath =
|
|
320
|
+
const remotePath = resolvePath(inputPath);
|
|
345
321
|
const target = await resolveReadableSandboxPath({
|
|
346
322
|
remotePath,
|
|
347
323
|
inputPath,
|
|
@@ -382,7 +358,7 @@ export function createClineRemoteOps(
|
|
|
382
358
|
},
|
|
383
359
|
|
|
384
360
|
async ls(inputPath = '.', limit = 500) {
|
|
385
|
-
const remotePath =
|
|
361
|
+
const remotePath = resolvePath(inputPath);
|
|
386
362
|
const target = await resolveReadableSandboxPath({
|
|
387
363
|
remotePath,
|
|
388
364
|
inputPath,
|
package/src/cline-session.ts
CHANGED
|
@@ -35,7 +35,10 @@ import {
|
|
|
35
35
|
resolveClinePrivateSessionDirectory,
|
|
36
36
|
safeClineHistoryFileName,
|
|
37
37
|
} from './cline-resume-state';
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
createClineSkillsRuntime,
|
|
40
|
+
type ClineSkillsRuntime,
|
|
41
|
+
} from './cline-skills';
|
|
39
42
|
import {
|
|
40
43
|
buildBuiltinAgentTools,
|
|
41
44
|
buildUserAgentTools,
|
|
@@ -82,6 +85,7 @@ const parkedClineSessions = new Map<string, HarnessV1Session>();
|
|
|
82
85
|
|
|
83
86
|
export interface ClineSessionSettings {
|
|
84
87
|
readonly authEnv: Record<string, string>;
|
|
88
|
+
readonly isAuthenticationEnvironmentOverride: boolean;
|
|
85
89
|
readonly mcpServers?: Record<string, unknown>;
|
|
86
90
|
readonly providerId?: string;
|
|
87
91
|
readonly modelId?: string;
|
|
@@ -96,7 +100,6 @@ export interface CreateClineSessionInput {
|
|
|
96
100
|
readonly sessionId: string;
|
|
97
101
|
readonly sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;
|
|
98
102
|
readonly sessionWorkDir: string;
|
|
99
|
-
readonly skills: ReadonlyArray<HarnessV1Skill>;
|
|
100
103
|
readonly settings: ClineSessionSettings;
|
|
101
104
|
readonly clientApp: string;
|
|
102
105
|
readonly isResume: boolean;
|
|
@@ -153,17 +156,12 @@ function clineBuiltinToolRequiresApproval(input: {
|
|
|
153
156
|
function buildSystemPrompt(input: {
|
|
154
157
|
sessionWorkDir: string;
|
|
155
158
|
sandboxDescription: string;
|
|
156
|
-
skillsSection?: string;
|
|
157
159
|
}): string {
|
|
158
|
-
|
|
160
|
+
return [
|
|
159
161
|
'You are Cline, an autonomous coding agent operating inside a sandboxed workspace.',
|
|
160
162
|
`## Workspace\n\nThe workspace root is \`${input.sessionWorkDir}\`. All relative file paths and shell commands resolve against it. Use the provided tools (read, write, edit, bash, grep, glob, ls) to inspect and modify the workspace.`,
|
|
161
163
|
`## Sandbox\n\n${input.sandboxDescription}`,
|
|
162
|
-
];
|
|
163
|
-
if (input.skillsSection) {
|
|
164
|
-
sections.push(input.skillsSection);
|
|
165
|
-
}
|
|
166
|
-
return sections.join('\n\n');
|
|
164
|
+
].join('\n\n');
|
|
167
165
|
}
|
|
168
166
|
|
|
169
167
|
function toClineBackendProviderBaseUrl(baseUrl: string): string {
|
|
@@ -209,7 +207,9 @@ function createClineAgentModel({
|
|
|
209
207
|
...(apiKey ? { apiKey } : {}),
|
|
210
208
|
...(baseUrl ? { baseUrl } : {}),
|
|
211
209
|
...(headers ? { headers } : {}),
|
|
212
|
-
...(isAiGateway
|
|
210
|
+
...(isAiGateway || settings.isAuthenticationEnvironmentOverride
|
|
211
|
+
? { apiKeyEnv: [] }
|
|
212
|
+
: {}),
|
|
213
213
|
},
|
|
214
214
|
],
|
|
215
215
|
});
|
|
@@ -268,32 +268,9 @@ export async function createClineSession(
|
|
|
268
268
|
input.builtinToolFiltering,
|
|
269
269
|
);
|
|
270
270
|
|
|
271
|
-
// Materialize harness-provided skills into sandbox HOME (not the workspace)
|
|
272
|
-
// and advertise them via a system prompt section.
|
|
273
|
-
let skillsSection: string | undefined;
|
|
274
|
-
let skillRootDir: string | undefined;
|
|
275
|
-
if (input.skills.length > 0) {
|
|
276
|
-
skillRootDir = await writeClineSkills({
|
|
277
|
-
sandbox: toolSafeSandboxSession,
|
|
278
|
-
sandboxHomeDir,
|
|
279
|
-
skills: input.skills,
|
|
280
|
-
...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),
|
|
281
|
-
});
|
|
282
|
-
if (skillRootDir) {
|
|
283
|
-
skillsSection = renderSkillsPromptSection(input.skills, skillRootDir);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
271
|
const ops = createClineRemoteOps({
|
|
288
272
|
sandbox: toolSafeSandboxSession,
|
|
289
273
|
workDir: input.sessionWorkDir,
|
|
290
|
-
...(skillRootDir ? { readableRoots: [{ sandboxDir: skillRootDir }] } : {}),
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
const baseSystemPrompt = buildSystemPrompt({
|
|
294
|
-
sessionWorkDir: input.sessionWorkDir,
|
|
295
|
-
sandboxDescription: toolSafeSandboxSession.description,
|
|
296
|
-
...(skillsSection ? { skillsSection } : {}),
|
|
297
274
|
});
|
|
298
275
|
|
|
299
276
|
// On resume: pull the persisted conversation history from the sandbox so
|
|
@@ -321,7 +298,7 @@ export async function createClineSession(
|
|
|
321
298
|
// Per-session mutable state we hold across prompts.
|
|
322
299
|
let agent: Agent | undefined;
|
|
323
300
|
let unsubscribe: (() => void) | undefined;
|
|
324
|
-
let
|
|
301
|
+
let lastAgentConfigurationSignature: string | undefined;
|
|
325
302
|
let agentHasRun = false;
|
|
326
303
|
let stopped = false;
|
|
327
304
|
/*
|
|
@@ -401,6 +378,7 @@ export async function createClineSession(
|
|
|
401
378
|
|
|
402
379
|
function rebuildAgent(rebuildInput: {
|
|
403
380
|
userTools: ReadonlyArray<HarnessV1ToolSpec>;
|
|
381
|
+
skillsRuntime: ClineSkillsRuntime;
|
|
404
382
|
instructions?: string;
|
|
405
383
|
responseFormat?: HarnessV1PromptTurnOptions['responseFormat'];
|
|
406
384
|
}): void {
|
|
@@ -417,9 +395,15 @@ export async function createClineSession(
|
|
|
417
395
|
}
|
|
418
396
|
: {}),
|
|
419
397
|
sessionId: input.sessionId,
|
|
420
|
-
systemPrompt:
|
|
421
|
-
|
|
422
|
-
|
|
398
|
+
systemPrompt: (() => {
|
|
399
|
+
const baseSystemPrompt = buildSystemPrompt({
|
|
400
|
+
sessionWorkDir: input.sessionWorkDir,
|
|
401
|
+
sandboxDescription: toolSafeSandboxSession.description,
|
|
402
|
+
});
|
|
403
|
+
return rebuildInput.instructions
|
|
404
|
+
? `${baseSystemPrompt}\n\n${rebuildInput.instructions}`
|
|
405
|
+
: baseSystemPrompt;
|
|
406
|
+
})(),
|
|
423
407
|
initialMessages: currentMessages,
|
|
424
408
|
toolExecution: 'parallel',
|
|
425
409
|
...(input.settings.maxIterations !== undefined
|
|
@@ -427,6 +411,10 @@ export async function createClineSession(
|
|
|
427
411
|
: {}),
|
|
428
412
|
tools: [
|
|
429
413
|
...buildBuiltinAgentTools({ ops, activeNames: activeBuiltinNames }),
|
|
414
|
+
...(rebuildInput.skillsRuntime.tool &&
|
|
415
|
+
activeBuiltinNames.includes('skills')
|
|
416
|
+
? [rebuildInput.skillsRuntime.tool]
|
|
417
|
+
: []),
|
|
430
418
|
...mcpRuntime.tools,
|
|
431
419
|
...buildUserAgentTools({
|
|
432
420
|
specs: rebuildInput.userTools,
|
|
@@ -569,19 +557,23 @@ export async function createClineSession(
|
|
|
569
557
|
* Shared by `doPromptTurn` (a fresh user prompt) and `doContinueTurn`
|
|
570
558
|
* (no prompt — the runtime continues its own thread after a rerun resume).
|
|
571
559
|
*/
|
|
572
|
-
function runTurn(turnOpts: {
|
|
560
|
+
async function runTurn(turnOpts: {
|
|
573
561
|
text: string | undefined;
|
|
562
|
+
skills: ReadonlyArray<HarnessV1Skill>;
|
|
574
563
|
tools: ReadonlyArray<HarnessV1ToolSpec>;
|
|
575
564
|
instructions?: string;
|
|
576
565
|
emit: (part: HarnessV1StreamPart) => void;
|
|
577
566
|
abortSignal?: AbortSignal;
|
|
578
567
|
responseFormat?: HarnessV1PromptTurnOptions['responseFormat'];
|
|
579
|
-
}): HarnessV1PromptControl {
|
|
568
|
+
}): Promise<HarnessV1PromptControl> {
|
|
580
569
|
if (stopped) {
|
|
581
570
|
throw new Error('Cline session has been stopped.');
|
|
582
571
|
}
|
|
583
572
|
|
|
584
573
|
const userTools = turnOpts.tools;
|
|
574
|
+
const skillsRuntime = createClineSkillsRuntime({
|
|
575
|
+
skills: turnOpts.skills,
|
|
576
|
+
});
|
|
585
577
|
if (
|
|
586
578
|
turnOpts.responseFormat?.type === 'json' &&
|
|
587
579
|
turnOpts.responseFormat.schema == null
|
|
@@ -604,25 +596,31 @@ export async function createClineSession(
|
|
|
604
596
|
}
|
|
605
597
|
|
|
606
598
|
const signature = JSON.stringify({
|
|
607
|
-
tools: userTools
|
|
599
|
+
tools: userTools,
|
|
608
600
|
responseFormat: turnOpts.responseFormat,
|
|
601
|
+
instructions: turnOpts.instructions,
|
|
602
|
+
skills: skillsRuntime.signature,
|
|
609
603
|
});
|
|
610
|
-
if (agent == null || signature !==
|
|
604
|
+
if (agent == null || signature !== lastAgentConfigurationSignature) {
|
|
611
605
|
currentMessages = agent?.snapshot().messages ?? currentMessages;
|
|
612
606
|
rebuildAgent({
|
|
613
607
|
userTools,
|
|
608
|
+
skillsRuntime,
|
|
614
609
|
responseFormat: turnOpts.responseFormat,
|
|
615
610
|
...(turnOpts.instructions
|
|
616
611
|
? { instructions: turnOpts.instructions }
|
|
617
612
|
: {}),
|
|
618
613
|
});
|
|
619
|
-
|
|
614
|
+
lastAgentConfigurationSignature = signature;
|
|
620
615
|
}
|
|
621
616
|
|
|
622
617
|
currentEmit = turnOpts.emit;
|
|
618
|
+
const userToolNames = new Set(userTools.map(tool => tool.name));
|
|
623
619
|
translatorState = createClineTranslatorState({
|
|
624
|
-
builtinToolNames: activeBuiltinNames
|
|
625
|
-
|
|
620
|
+
builtinToolNames: activeBuiltinNames.filter(
|
|
621
|
+
name => !userToolNames.has(name),
|
|
622
|
+
),
|
|
623
|
+
hostToolNames: userToolNames,
|
|
626
624
|
ignoredToolNames:
|
|
627
625
|
turnOpts.responseFormat?.type === 'json' ? ['structured_output'] : [],
|
|
628
626
|
mcpToolNames: mcpRuntime.toolNames,
|
|
@@ -806,6 +804,7 @@ export async function createClineSession(
|
|
|
806
804
|
): Promise<HarnessV1PromptControl> => {
|
|
807
805
|
return runTurn({
|
|
808
806
|
text: extractUserText(promptOpts.prompt),
|
|
807
|
+
skills: promptOpts.skills,
|
|
809
808
|
tools: promptOpts.tools ?? [],
|
|
810
809
|
...(promptOpts.instructions
|
|
811
810
|
? { instructions: promptOpts.instructions }
|
|
@@ -840,6 +839,7 @@ export async function createClineSession(
|
|
|
840
839
|
*/
|
|
841
840
|
return runTurn({
|
|
842
841
|
text: undefined,
|
|
842
|
+
skills: continueOpts.skills,
|
|
843
843
|
tools: continueOpts.tools ?? [],
|
|
844
844
|
...(continueOpts.instructions
|
|
845
845
|
? { instructions: continueOpts.instructions }
|