@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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @ai-sdk/harness-cline
|
|
2
2
|
|
|
3
|
+
## 1.0.20
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7608210: feat(harness): add `model` parameter to `HarnessAgent` instead of having each harness adapter support it on their own constructor functions
|
|
8
|
+
- f7bd978: chore(harness): update underlying adapter SDKs to their latest versions
|
|
9
|
+
- 14d4fc0: feat(harness): allow changing harness settings between turns via `prepareCall()` support on `HarnessAgent`
|
|
10
|
+
- 5021768: fix(harness-cline): use native `skills` tool instead of manual file-based workaround
|
|
11
|
+
- Updated dependencies [cc9f6ce]
|
|
12
|
+
- Updated dependencies [7608210]
|
|
13
|
+
- Updated dependencies [6f8a2d7]
|
|
14
|
+
- Updated dependencies [14d4fc0]
|
|
15
|
+
- Updated dependencies [90192f1]
|
|
16
|
+
- @ai-sdk/harness@1.0.93
|
|
17
|
+
- @ai-sdk/provider-utils@5.0.33
|
|
18
|
+
|
|
19
|
+
## 1.0.19
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- e0d7cfb: feat(harness): allow harness sessions to optionally authenticate from an isolated environment supplied through the `auth` option, and remove support for the formerly deprecated legacy auth options types
|
|
24
|
+
- Updated dependencies [e0d7cfb]
|
|
25
|
+
- @ai-sdk/harness@1.0.92
|
|
26
|
+
|
|
3
27
|
## 1.0.18
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -53,6 +53,6 @@ The adapter requires a `HarnessV1SandboxProvider`. Cline has no in-sandbox bridg
|
|
|
53
53
|
|
|
54
54
|
## Authentication
|
|
55
55
|
|
|
56
|
-
The default `auto` authentication mode uses `AI_GATEWAY_API_KEY` or `VERCEL_OIDC_TOKEN` when available and otherwise falls back to `CLINE_API_KEY`. Use `createCline({ auth: 'ai-gateway' })` or `createCline({ auth: 'direct' })` to select a mode explicitly
|
|
56
|
+
The default `auto` authentication mode uses `AI_GATEWAY_API_KEY` or `VERCEL_OIDC_TOKEN` when available and otherwise falls back to `CLINE_API_KEY`. Use `createCline({ auth: 'ai-gateway' })` or `createCline({ auth: 'direct' })` to select a mode explicitly, or pass an isolated authentication environment with `createCline({ auth: { CLINE_API_KEY: token } })`. `AI_GATEWAY_BASE_URL` and `CLINE_API_BASE_URL` configure their respective endpoints.
|
|
57
57
|
|
|
58
58
|
See the [Cline harness documentation](https://ai-sdk.dev/providers/ai-sdk-harnesses/cline) for model configuration, reasoning, tools, skills, MCP, and session lifecycle details.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as _ai_sdk_harness from '@ai-sdk/harness';
|
|
2
|
-
import { HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
2
|
+
import { HarnessV1Authentication, HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
3
3
|
|
|
4
|
-
type ClineAuthenticationMode =
|
|
5
|
-
type ClineAuthOptions = ClineAuthenticationMode;
|
|
4
|
+
type ClineAuthenticationMode = HarnessV1Authentication;
|
|
6
5
|
|
|
7
6
|
type ClineReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
8
7
|
|
|
@@ -13,7 +12,7 @@ type ClineReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xh
|
|
|
13
12
|
*/
|
|
14
13
|
type ClineHarnessSettings = {
|
|
15
14
|
/** Where Cline sources direct or AI Gateway credentials from. */
|
|
16
|
-
readonly auth?:
|
|
15
|
+
readonly auth?: ClineAuthenticationMode;
|
|
17
16
|
/**
|
|
18
17
|
* MCP server definitions keyed by server name. Each definition uses the
|
|
19
18
|
* underlying runtime's native MCP server configuration format.
|
|
@@ -27,11 +26,14 @@ type ClineHarnessSettings = {
|
|
|
27
26
|
/**
|
|
28
27
|
* Model id for the configured provider. When omitted, Cline selects the
|
|
29
28
|
* provider's default model.
|
|
29
|
+
*
|
|
30
|
+
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
30
31
|
*/
|
|
31
32
|
readonly modelId?: string;
|
|
32
33
|
/**
|
|
33
34
|
* Provider API key. When omitted, the Cline gateway falls back to the
|
|
34
35
|
* provider's environment variable (e.g. `ANTHROPIC_API_KEY`).
|
|
36
|
+
* A record-shaped authentication override disables that fallback.
|
|
35
37
|
*/
|
|
36
38
|
readonly apiKey?: string;
|
|
37
39
|
/** Custom provider endpoint. */
|
|
@@ -80,6 +82,7 @@ declare const CLINE_BUILTIN_TOOLS: {
|
|
|
80
82
|
limit?: number | undefined;
|
|
81
83
|
}, unknown>;
|
|
82
84
|
readonly ls: HarnessV1BuiltinTool;
|
|
85
|
+
readonly skills: HarnessV1BuiltinTool;
|
|
83
86
|
};
|
|
84
87
|
declare function createCline(settings?: ClineHarnessSettings): HarnessV1<typeof CLINE_BUILTIN_TOOLS>;
|
|
85
88
|
|
|
@@ -122,6 +125,7 @@ declare const cline: _ai_sdk_harness.HarnessV1<{
|
|
|
122
125
|
limit?: number | undefined;
|
|
123
126
|
}, unknown>;
|
|
124
127
|
readonly ls: _ai_sdk_harness.HarnessV1BuiltinTool;
|
|
128
|
+
readonly skills: _ai_sdk_harness.HarnessV1BuiltinTool;
|
|
125
129
|
}>;
|
|
126
130
|
|
|
127
|
-
export { type
|
|
131
|
+
export { type ClineAuthenticationMode, type ClineHarnessSettings, VERSION, cline, createCline };
|
package/dist/index.js
CHANGED
|
@@ -2,27 +2,38 @@
|
|
|
2
2
|
import {
|
|
3
3
|
commonTool
|
|
4
4
|
} from "@ai-sdk/harness";
|
|
5
|
+
import { isHarnessAuthenticationEnvironment as isHarnessAuthenticationEnvironment2 } from "@ai-sdk/harness/utils";
|
|
5
6
|
import { tool } from "@ai-sdk/provider-utils";
|
|
6
7
|
import { z as z2 } from "zod/v4";
|
|
7
8
|
|
|
8
9
|
// src/cline-auth.ts
|
|
9
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
getAiGatewayAuthFromEnv,
|
|
12
|
+
isHarnessAuthenticationEnvironment
|
|
13
|
+
} from "@ai-sdk/harness/utils";
|
|
10
14
|
function resolveClineEnv({
|
|
11
15
|
auth = "auto",
|
|
12
16
|
env = process.env
|
|
13
17
|
}) {
|
|
18
|
+
if (isHarnessAuthenticationEnvironment(auth)) {
|
|
19
|
+
const gatewayAuth2 = getAiGatewayAuthFromEnv({ env: auth });
|
|
20
|
+
return gatewayAuth2.apiKey ? toGatewayClineEnv(gatewayAuth2) : pickDirectClineEnv({ env: auth });
|
|
21
|
+
}
|
|
14
22
|
if (auth === "direct") {
|
|
15
23
|
return pickDirectClineEnv({ env });
|
|
16
24
|
}
|
|
17
25
|
const gatewayAuth = getAiGatewayAuthFromEnv({ env });
|
|
18
26
|
if (auth === "ai-gateway" || gatewayAuth.apiKey) {
|
|
19
|
-
return
|
|
20
|
-
...gatewayAuth.apiKey ? { AI_GATEWAY_API_KEY: gatewayAuth.apiKey } : {},
|
|
21
|
-
AI_GATEWAY_BASE_URL: gatewayAuth.baseUrl
|
|
22
|
-
};
|
|
27
|
+
return toGatewayClineEnv(gatewayAuth);
|
|
23
28
|
}
|
|
24
29
|
return pickDirectClineEnv({ env });
|
|
25
30
|
}
|
|
31
|
+
function toGatewayClineEnv(gatewayAuth) {
|
|
32
|
+
return {
|
|
33
|
+
...gatewayAuth.apiKey ? { AI_GATEWAY_API_KEY: gatewayAuth.apiKey } : {},
|
|
34
|
+
AI_GATEWAY_BASE_URL: gatewayAuth.baseUrl
|
|
35
|
+
};
|
|
36
|
+
}
|
|
26
37
|
function pickDirectClineEnv({
|
|
27
38
|
env
|
|
28
39
|
}) {
|
|
@@ -230,7 +241,6 @@ import { shellQuote } from "@ai-sdk/harness/utils";
|
|
|
230
241
|
function createClineRemoteOps(options) {
|
|
231
242
|
const { sandbox, workDir } = options;
|
|
232
243
|
const normalizedWorkDir = path2.posix.normalize(workDir);
|
|
233
|
-
const readableRoots = options.readableRoots?.map((root) => path2.posix.normalize(root.sandboxDir)) ?? [];
|
|
234
244
|
const isInsidePath = ({
|
|
235
245
|
parent,
|
|
236
246
|
candidate
|
|
@@ -245,25 +255,10 @@ function createClineRemoteOps(options) {
|
|
|
245
255
|
}
|
|
246
256
|
return normalized;
|
|
247
257
|
};
|
|
248
|
-
const assertReadablePath = (inputPath) => {
|
|
249
|
-
const normalized = path2.posix.normalize(inputPath);
|
|
250
|
-
if (!isInsidePath({ parent: normalizedWorkDir, candidate: normalized }) && !readableRoots.some(
|
|
251
|
-
(parent) => isInsidePath({ parent, candidate: normalized })
|
|
252
|
-
)) {
|
|
253
|
-
throw new Error(`Cline path escapes the readable roots: ${inputPath}`);
|
|
254
|
-
}
|
|
255
|
-
return normalized;
|
|
256
|
-
};
|
|
257
258
|
const resolvePath = (inputPath) => {
|
|
258
259
|
const resolved = path2.posix.isAbsolute(inputPath) ? path2.posix.normalize(inputPath) : path2.posix.normalize(path2.posix.join(normalizedWorkDir, inputPath));
|
|
259
260
|
return assertWorkspacePath(resolved);
|
|
260
261
|
};
|
|
261
|
-
const resolveReadablePath = (inputPath) => {
|
|
262
|
-
if (!path2.posix.isAbsolute(inputPath)) {
|
|
263
|
-
return resolvePath(inputPath);
|
|
264
|
-
}
|
|
265
|
-
return assertReadablePath(inputPath);
|
|
266
|
-
};
|
|
267
262
|
const runShell = async ({
|
|
268
263
|
command,
|
|
269
264
|
signal
|
|
@@ -308,7 +303,7 @@ function createClineRemoteOps(options) {
|
|
|
308
303
|
remotePath,
|
|
309
304
|
inputPath,
|
|
310
305
|
missingMessage
|
|
311
|
-
}) =>
|
|
306
|
+
}) => assertWorkspacePath(
|
|
312
307
|
await resolveExistingSandboxPath({
|
|
313
308
|
remotePath,
|
|
314
309
|
inputPath,
|
|
@@ -341,7 +336,7 @@ function createClineRemoteOps(options) {
|
|
|
341
336
|
return assertWorkspacePath(resolvedPath);
|
|
342
337
|
};
|
|
343
338
|
const readFile = async (inputPath) => {
|
|
344
|
-
const remotePath =
|
|
339
|
+
const remotePath = resolvePath(inputPath);
|
|
345
340
|
const resolved = await resolveReadableSandboxPath({
|
|
346
341
|
remotePath,
|
|
347
342
|
inputPath,
|
|
@@ -409,7 +404,7 @@ function createClineRemoteOps(options) {
|
|
|
409
404
|
},
|
|
410
405
|
async grep(pattern, input = {}) {
|
|
411
406
|
const inputPath = input.path ?? ".";
|
|
412
|
-
const remotePath =
|
|
407
|
+
const remotePath = resolvePath(inputPath);
|
|
413
408
|
const target = await resolveReadableSandboxPath({
|
|
414
409
|
remotePath,
|
|
415
410
|
inputPath
|
|
@@ -441,7 +436,7 @@ function createClineRemoteOps(options) {
|
|
|
441
436
|
return output || "No matches found";
|
|
442
437
|
},
|
|
443
438
|
async glob(pattern, inputPath = ".", limit = 1e3) {
|
|
444
|
-
const remotePath =
|
|
439
|
+
const remotePath = resolvePath(inputPath);
|
|
445
440
|
const target = await resolveReadableSandboxPath({
|
|
446
441
|
remotePath,
|
|
447
442
|
inputPath
|
|
@@ -472,7 +467,7 @@ function createClineRemoteOps(options) {
|
|
|
472
467
|
).slice(0, limit);
|
|
473
468
|
},
|
|
474
469
|
async ls(inputPath = ".", limit = 500) {
|
|
475
|
-
const remotePath =
|
|
470
|
+
const remotePath = resolvePath(inputPath);
|
|
476
471
|
const target = await resolveReadableSandboxPath({
|
|
477
472
|
remotePath,
|
|
478
473
|
inputPath
|
|
@@ -505,33 +500,123 @@ function createClineRemoteOps(options) {
|
|
|
505
500
|
|
|
506
501
|
// src/cline-skills.ts
|
|
507
502
|
import path3 from "path";
|
|
508
|
-
import {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
skills,
|
|
513
|
-
abortSignal
|
|
503
|
+
import { createDefaultTools } from "@cline/core";
|
|
504
|
+
var CLINE_SKILL_NAME_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
505
|
+
function createClineSkillsRuntime({
|
|
506
|
+
skills
|
|
514
507
|
}) {
|
|
515
|
-
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
508
|
+
const projectedSkills = projectClineSkills({ skills });
|
|
509
|
+
const signature = JSON.stringify(projectedSkills);
|
|
510
|
+
if (projectedSkills.length === 0) {
|
|
511
|
+
return { signature };
|
|
512
|
+
}
|
|
513
|
+
const executor = async (...executorArguments) => {
|
|
514
|
+
const [requestedSkill, args] = executorArguments;
|
|
515
|
+
const skill = projectedSkills.find(
|
|
516
|
+
(candidate) => candidate.id === normalizeSkillToken(requestedSkill)
|
|
517
|
+
);
|
|
518
|
+
if (skill == null) {
|
|
519
|
+
const availableSkills = projectedSkills.map((skill2) => skill2.name);
|
|
520
|
+
return availableSkills.length > 0 ? `Skill "${requestedSkill}" not found. Available skills: ${availableSkills.join(", ")}` : "No skills are currently available.";
|
|
521
|
+
}
|
|
522
|
+
return renderSkillInstructions({ skill, args });
|
|
523
|
+
};
|
|
524
|
+
executor.configuredSkills = projectedSkills.map((skill) => ({
|
|
525
|
+
id: skill.id,
|
|
526
|
+
name: skill.name,
|
|
527
|
+
description: skill.description,
|
|
528
|
+
disabled: false
|
|
529
|
+
}));
|
|
530
|
+
const tool2 = createDefaultTools({
|
|
531
|
+
executors: { skills: executor },
|
|
532
|
+
enableReadFiles: false,
|
|
533
|
+
enableSearch: false,
|
|
534
|
+
enableBash: false,
|
|
535
|
+
enableWebFetch: false,
|
|
536
|
+
enableApplyPatch: false,
|
|
537
|
+
enableEditor: false,
|
|
538
|
+
enableSkills: true,
|
|
539
|
+
enableAskQuestion: false,
|
|
540
|
+
enableSubmitAndExit: false
|
|
541
|
+
}).find((tool3) => tool3.name === "skills");
|
|
542
|
+
if (tool2 == null) {
|
|
543
|
+
throw new Error("Cline did not create its native skills tool.");
|
|
544
|
+
}
|
|
545
|
+
return { signature, tool: tool2 };
|
|
546
|
+
}
|
|
547
|
+
function projectClineSkills({
|
|
548
|
+
skills
|
|
549
|
+
}) {
|
|
550
|
+
const names = /* @__PURE__ */ new Set();
|
|
551
|
+
const ids = /* @__PURE__ */ new Set();
|
|
552
|
+
return skills.map((skill) => {
|
|
553
|
+
if (!CLINE_SKILL_NAME_PATTERN.test(skill.name) || skill.name === "." || skill.name === "..") {
|
|
554
|
+
throw new Error(`Invalid Cline skill name: ${skill.name}`);
|
|
555
|
+
}
|
|
556
|
+
if (names.has(skill.name)) {
|
|
557
|
+
throw new Error(`Duplicate Cline skill name: ${skill.name}`);
|
|
558
|
+
}
|
|
559
|
+
names.add(skill.name);
|
|
560
|
+
const id = normalizeSkillToken(skill.name);
|
|
561
|
+
if (ids.has(id)) {
|
|
562
|
+
throw new Error(`Duplicate Cline skill identifier: ${id}`);
|
|
563
|
+
}
|
|
564
|
+
ids.add(id);
|
|
565
|
+
return {
|
|
566
|
+
id,
|
|
567
|
+
name: skill.name,
|
|
568
|
+
description: skill.description,
|
|
569
|
+
content: skill.content,
|
|
570
|
+
files: (skill.files ?? []).map((file) => ({
|
|
571
|
+
path: normalizeSkillFilePath({
|
|
572
|
+
skillName: skill.name,
|
|
573
|
+
filePath: file.path
|
|
574
|
+
}),
|
|
575
|
+
content: file.content
|
|
576
|
+
})).sort(
|
|
577
|
+
(left, right) => left.path.localeCompare(right.path) || left.content.localeCompare(right.content)
|
|
578
|
+
)
|
|
579
|
+
};
|
|
580
|
+
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
581
|
+
}
|
|
582
|
+
function normalizeSkillToken(skill) {
|
|
583
|
+
return skill.trim().replace(/^\/+/, "").toLowerCase();
|
|
584
|
+
}
|
|
585
|
+
function normalizeSkillFilePath({
|
|
586
|
+
skillName,
|
|
587
|
+
filePath
|
|
588
|
+
}) {
|
|
589
|
+
const normalized = path3.posix.normalize(filePath);
|
|
590
|
+
if (normalized === "" || normalized === "." || normalized.startsWith("../") || normalized.includes("/../") || normalized.endsWith("/..") || path3.posix.isAbsolute(normalized)) {
|
|
591
|
+
throw new Error(
|
|
592
|
+
`Invalid Cline skill file path for ${skillName}: ${filePath}`
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
return normalized;
|
|
524
596
|
}
|
|
525
|
-
function
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
597
|
+
function renderSkillInstructions({
|
|
598
|
+
skill,
|
|
599
|
+
args
|
|
600
|
+
}) {
|
|
601
|
+
const trimmedArgs = args?.trim();
|
|
602
|
+
const argsTag = trimmedArgs ? `
|
|
603
|
+
<command-args>${trimmedArgs}</command-args>` : "";
|
|
604
|
+
const description = skill.description.trim() ? `Description: ${skill.description.trim()}
|
|
605
|
+
|
|
606
|
+
` : "";
|
|
607
|
+
const files = skill.files.length === 0 ? "" : `
|
|
608
|
+
|
|
609
|
+
<skill-files>
|
|
610
|
+
${skill.files.map(
|
|
611
|
+
(file) => `<skill-file path=${JSON.stringify(file.path)}>
|
|
612
|
+
${file.content}
|
|
613
|
+
</skill-file>`
|
|
614
|
+
).join("\n")}
|
|
615
|
+
</skill-files>`;
|
|
616
|
+
return `<command-name>${skill.name}</command-name>${argsTag}
|
|
617
|
+
<command-instructions>
|
|
618
|
+
${description}${skill.content}${files}
|
|
619
|
+
</command-instructions>`;
|
|
535
620
|
}
|
|
536
621
|
|
|
537
622
|
// src/cline-tools.ts
|
|
@@ -646,7 +731,8 @@ var CLINE_NATIVE_BUILTIN_NAMES = [
|
|
|
646
731
|
"bash",
|
|
647
732
|
"grep",
|
|
648
733
|
"glob",
|
|
649
|
-
"ls"
|
|
734
|
+
"ls",
|
|
735
|
+
"skills"
|
|
650
736
|
];
|
|
651
737
|
var CLINE_NATIVE_TOOL_KINDS = {
|
|
652
738
|
read: "readonly",
|
|
@@ -655,7 +741,8 @@ var CLINE_NATIVE_TOOL_KINDS = {
|
|
|
655
741
|
bash: "bash",
|
|
656
742
|
grep: "readonly",
|
|
657
743
|
glob: "readonly",
|
|
658
|
-
ls: "readonly"
|
|
744
|
+
ls: "readonly",
|
|
745
|
+
skills: "readonly"
|
|
659
746
|
};
|
|
660
747
|
function isClineBuiltinToolName(name) {
|
|
661
748
|
return CLINE_NATIVE_BUILTIN_NAMES.includes(name);
|
|
@@ -1099,7 +1186,7 @@ function clineBuiltinToolRequiresApproval(input) {
|
|
|
1099
1186
|
return input.kind === "edit" || input.kind === "bash";
|
|
1100
1187
|
}
|
|
1101
1188
|
function buildSystemPrompt(input) {
|
|
1102
|
-
|
|
1189
|
+
return [
|
|
1103
1190
|
"You are Cline, an autonomous coding agent operating inside a sandboxed workspace.",
|
|
1104
1191
|
`## Workspace
|
|
1105
1192
|
|
|
@@ -1107,11 +1194,7 @@ The workspace root is \`${input.sessionWorkDir}\`. All relative file paths and s
|
|
|
1107
1194
|
`## Sandbox
|
|
1108
1195
|
|
|
1109
1196
|
${input.sandboxDescription}`
|
|
1110
|
-
];
|
|
1111
|
-
if (input.skillsSection) {
|
|
1112
|
-
sections.push(input.skillsSection);
|
|
1113
|
-
}
|
|
1114
|
-
return sections.join("\n\n");
|
|
1197
|
+
].join("\n\n");
|
|
1115
1198
|
}
|
|
1116
1199
|
function toClineBackendProviderBaseUrl(baseUrl) {
|
|
1117
1200
|
return `${baseUrl.replace(/\/+$/, "")}/api/v1`;
|
|
@@ -1141,7 +1224,7 @@ function createClineAgentModel({
|
|
|
1141
1224
|
...apiKey ? { apiKey } : {},
|
|
1142
1225
|
...baseUrl ? { baseUrl } : {},
|
|
1143
1226
|
...headers ? { headers } : {},
|
|
1144
|
-
...isAiGateway ? { apiKeyEnv: [] } : {}
|
|
1227
|
+
...isAiGateway || settings.isAuthenticationEnvironmentOverride ? { apiKeyEnv: [] } : {}
|
|
1145
1228
|
}
|
|
1146
1229
|
]
|
|
1147
1230
|
});
|
|
@@ -1188,28 +1271,9 @@ async function createClineSession(input) {
|
|
|
1188
1271
|
const activeBuiltinNames = resolveActiveClineBuiltinNames(
|
|
1189
1272
|
input.builtinToolFiltering
|
|
1190
1273
|
);
|
|
1191
|
-
let skillsSection;
|
|
1192
|
-
let skillRootDir;
|
|
1193
|
-
if (input.skills.length > 0) {
|
|
1194
|
-
skillRootDir = await writeClineSkills({
|
|
1195
|
-
sandbox: toolSafeSandboxSession,
|
|
1196
|
-
sandboxHomeDir,
|
|
1197
|
-
skills: input.skills,
|
|
1198
|
-
...input.abortSignal ? { abortSignal: input.abortSignal } : {}
|
|
1199
|
-
});
|
|
1200
|
-
if (skillRootDir) {
|
|
1201
|
-
skillsSection = renderSkillsPromptSection(input.skills, skillRootDir);
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
1274
|
const ops = createClineRemoteOps({
|
|
1205
1275
|
sandbox: toolSafeSandboxSession,
|
|
1206
|
-
workDir: input.sessionWorkDir
|
|
1207
|
-
...skillRootDir ? { readableRoots: [{ sandboxDir: skillRootDir }] } : {}
|
|
1208
|
-
});
|
|
1209
|
-
const baseSystemPrompt = buildSystemPrompt({
|
|
1210
|
-
sessionWorkDir: input.sessionWorkDir,
|
|
1211
|
-
sandboxDescription: toolSafeSandboxSession.description,
|
|
1212
|
-
...skillsSection ? { skillsSection } : {}
|
|
1276
|
+
workDir: input.sessionWorkDir
|
|
1213
1277
|
});
|
|
1214
1278
|
let currentMessages = [];
|
|
1215
1279
|
if (input.isResume && input.resumeHistoryFileName) {
|
|
@@ -1232,7 +1296,7 @@ async function createClineSession(input) {
|
|
|
1232
1296
|
});
|
|
1233
1297
|
let agent;
|
|
1234
1298
|
let unsubscribe;
|
|
1235
|
-
let
|
|
1299
|
+
let lastAgentConfigurationSignature;
|
|
1236
1300
|
let agentHasRun = false;
|
|
1237
1301
|
let stopped = false;
|
|
1238
1302
|
let suspending = false;
|
|
@@ -1303,14 +1367,21 @@ async function createClineSession(input) {
|
|
|
1303
1367
|
}
|
|
1304
1368
|
} : {},
|
|
1305
1369
|
sessionId: input.sessionId,
|
|
1306
|
-
systemPrompt:
|
|
1370
|
+
systemPrompt: (() => {
|
|
1371
|
+
const baseSystemPrompt = buildSystemPrompt({
|
|
1372
|
+
sessionWorkDir: input.sessionWorkDir,
|
|
1373
|
+
sandboxDescription: toolSafeSandboxSession.description
|
|
1374
|
+
});
|
|
1375
|
+
return rebuildInput.instructions ? `${baseSystemPrompt}
|
|
1307
1376
|
|
|
1308
|
-
${rebuildInput.instructions}` : baseSystemPrompt
|
|
1377
|
+
${rebuildInput.instructions}` : baseSystemPrompt;
|
|
1378
|
+
})(),
|
|
1309
1379
|
initialMessages: currentMessages,
|
|
1310
1380
|
toolExecution: "parallel",
|
|
1311
1381
|
...input.settings.maxIterations !== void 0 ? { maxIterations: input.settings.maxIterations } : {},
|
|
1312
1382
|
tools: [
|
|
1313
1383
|
...buildBuiltinAgentTools({ ops, activeNames: activeBuiltinNames }),
|
|
1384
|
+
...rebuildInput.skillsRuntime.tool && activeBuiltinNames.includes("skills") ? [rebuildInput.skillsRuntime.tool] : [],
|
|
1314
1385
|
...mcpRuntime.tools,
|
|
1315
1386
|
...buildUserAgentTools({
|
|
1316
1387
|
specs: rebuildInput.userTools,
|
|
@@ -1427,11 +1498,14 @@ ${rebuildInput.instructions}` : baseSystemPrompt,
|
|
|
1427
1498
|
done: controlInput.done
|
|
1428
1499
|
};
|
|
1429
1500
|
}
|
|
1430
|
-
function runTurn(turnOpts) {
|
|
1501
|
+
async function runTurn(turnOpts) {
|
|
1431
1502
|
if (stopped) {
|
|
1432
1503
|
throw new Error("Cline session has been stopped.");
|
|
1433
1504
|
}
|
|
1434
1505
|
const userTools = turnOpts.tools;
|
|
1506
|
+
const skillsRuntime = createClineSkillsRuntime({
|
|
1507
|
+
skills: turnOpts.skills
|
|
1508
|
+
});
|
|
1435
1509
|
if (turnOpts.responseFormat?.type === "json" && turnOpts.responseFormat.schema == null) {
|
|
1436
1510
|
throw new HarnessCapabilityUnsupportedError2({
|
|
1437
1511
|
message: "Harness 'cline' requires a JSON schema for structured output.",
|
|
@@ -1445,22 +1519,28 @@ ${rebuildInput.instructions}` : baseSystemPrompt,
|
|
|
1445
1519
|
});
|
|
1446
1520
|
}
|
|
1447
1521
|
const signature = JSON.stringify({
|
|
1448
|
-
tools: userTools
|
|
1449
|
-
responseFormat: turnOpts.responseFormat
|
|
1522
|
+
tools: userTools,
|
|
1523
|
+
responseFormat: turnOpts.responseFormat,
|
|
1524
|
+
instructions: turnOpts.instructions,
|
|
1525
|
+
skills: skillsRuntime.signature
|
|
1450
1526
|
});
|
|
1451
|
-
if (agent == null || signature !==
|
|
1527
|
+
if (agent == null || signature !== lastAgentConfigurationSignature) {
|
|
1452
1528
|
currentMessages = agent?.snapshot().messages ?? currentMessages;
|
|
1453
1529
|
rebuildAgent({
|
|
1454
1530
|
userTools,
|
|
1531
|
+
skillsRuntime,
|
|
1455
1532
|
responseFormat: turnOpts.responseFormat,
|
|
1456
1533
|
...turnOpts.instructions ? { instructions: turnOpts.instructions } : {}
|
|
1457
1534
|
});
|
|
1458
|
-
|
|
1535
|
+
lastAgentConfigurationSignature = signature;
|
|
1459
1536
|
}
|
|
1460
1537
|
currentEmit = turnOpts.emit;
|
|
1538
|
+
const userToolNames = new Set(userTools.map((tool2) => tool2.name));
|
|
1461
1539
|
translatorState = createClineTranslatorState({
|
|
1462
|
-
builtinToolNames: activeBuiltinNames
|
|
1463
|
-
|
|
1540
|
+
builtinToolNames: activeBuiltinNames.filter(
|
|
1541
|
+
(name) => !userToolNames.has(name)
|
|
1542
|
+
),
|
|
1543
|
+
hostToolNames: userToolNames,
|
|
1464
1544
|
ignoredToolNames: turnOpts.responseFormat?.type === "json" ? ["structured_output"] : [],
|
|
1465
1545
|
mcpToolNames: mcpRuntime.toolNames
|
|
1466
1546
|
});
|
|
@@ -1599,6 +1679,7 @@ ${rebuildInput.instructions}` : baseSystemPrompt,
|
|
|
1599
1679
|
doPromptTurn: async (promptOpts) => {
|
|
1600
1680
|
return runTurn({
|
|
1601
1681
|
text: extractUserText(promptOpts.prompt),
|
|
1682
|
+
skills: promptOpts.skills,
|
|
1602
1683
|
tools: promptOpts.tools ?? [],
|
|
1603
1684
|
...promptOpts.instructions ? { instructions: promptOpts.instructions } : {},
|
|
1604
1685
|
emit: promptOpts.emit,
|
|
@@ -1616,6 +1697,7 @@ ${rebuildInput.instructions}` : baseSystemPrompt,
|
|
|
1616
1697
|
}
|
|
1617
1698
|
return runTurn({
|
|
1618
1699
|
text: void 0,
|
|
1700
|
+
skills: continueOpts.skills,
|
|
1619
1701
|
tools: continueOpts.tools ?? [],
|
|
1620
1702
|
...continueOpts.instructions ? { instructions: continueOpts.instructions } : {},
|
|
1621
1703
|
emit: continueOpts.emit,
|
|
@@ -1699,7 +1781,7 @@ ${rebuildInput.instructions}` : baseSystemPrompt,
|
|
|
1699
1781
|
}
|
|
1700
1782
|
|
|
1701
1783
|
// src/version.ts
|
|
1702
|
-
var VERSION = true ? "1.0.
|
|
1784
|
+
var VERSION = true ? "1.0.20" : "0.0.0-test";
|
|
1703
1785
|
|
|
1704
1786
|
// src/cline-harness.ts
|
|
1705
1787
|
var CLINE_CLIENT_APP = `ai-sdk/harness-cline/${VERSION}`;
|
|
@@ -1775,6 +1857,18 @@ var CLINE_BUILTIN_TOOLS = {
|
|
|
1775
1857
|
}),
|
|
1776
1858
|
nativeName: "ls",
|
|
1777
1859
|
toolUseKind: "readonly"
|
|
1860
|
+
},
|
|
1861
|
+
skills: {
|
|
1862
|
+
...tool({
|
|
1863
|
+
description: "Execute a configured skill by name.",
|
|
1864
|
+
inputSchema: z2.object({
|
|
1865
|
+
skill: z2.string(),
|
|
1866
|
+
args: z2.string().optional()
|
|
1867
|
+
}),
|
|
1868
|
+
outputSchema: z2.string()
|
|
1869
|
+
}),
|
|
1870
|
+
nativeName: "skills",
|
|
1871
|
+
toolUseKind: "readonly"
|
|
1778
1872
|
}
|
|
1779
1873
|
};
|
|
1780
1874
|
function createCline(settings = {}) {
|
|
@@ -1786,6 +1880,7 @@ function createCline(settings = {}) {
|
|
|
1786
1880
|
supportsBuiltinToolFiltering: true,
|
|
1787
1881
|
lifecycleStateSchema: clineResumeStateSchema,
|
|
1788
1882
|
doStart: async (startOpts) => {
|
|
1883
|
+
const modelId = startOpts.model ?? settings.modelId;
|
|
1789
1884
|
const authEnv = resolveClineEnv({ auth: settings.auth });
|
|
1790
1885
|
const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
|
|
1791
1886
|
const resumeData = lifecycleState?.data;
|
|
@@ -1793,12 +1888,12 @@ function createCline(settings = {}) {
|
|
|
1793
1888
|
sessionId: startOpts.sessionId,
|
|
1794
1889
|
sandboxSession: startOpts.sandboxSession,
|
|
1795
1890
|
sessionWorkDir: startOpts.sessionWorkDir,
|
|
1796
|
-
skills: startOpts.skills ?? [],
|
|
1797
1891
|
settings: {
|
|
1798
1892
|
authEnv,
|
|
1893
|
+
isAuthenticationEnvironmentOverride: isHarnessAuthenticationEnvironment2(settings.auth),
|
|
1799
1894
|
...settings.mcpServers ? { mcpServers: settings.mcpServers } : {},
|
|
1800
1895
|
...settings.providerId ? { providerId: settings.providerId } : {},
|
|
1801
|
-
...
|
|
1896
|
+
...modelId == null ? {} : { modelId },
|
|
1802
1897
|
...settings.apiKey ? { apiKey: settings.apiKey } : {},
|
|
1803
1898
|
...settings.baseUrl ? { baseUrl: settings.baseUrl } : {},
|
|
1804
1899
|
...settings.headers ? { headers: settings.headers } : {},
|