@cleanslate/sdk 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -5
- package/VENDOR.md +7 -8
- package/dist/agent/cleanSlateAgentExecutionPhase.d.ts.map +1 -1
- package/dist/agent/cleanSlateAgentExecutionPhase.js +7 -1
- package/dist/agent/cleanSlateAgentExecutionPhase.js.map +1 -1
- package/dist/agent/cleanSlateExecutionQuery.d.ts +1 -0
- package/dist/agent/cleanSlateExecutionQuery.d.ts.map +1 -1
- package/dist/agent/cleanSlateExecutionQuery.js +135 -89
- package/dist/agent/cleanSlateExecutionQuery.js.map +1 -1
- package/dist/agent/cleanSlateToolResultPromptSerializer.js +27 -5
- package/dist/agent/cleanSlateToolResultPromptSerializer.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/node/cleanSlateHostedAgentRuntime.d.ts +41 -0
- package/dist/node/cleanSlateHostedAgentRuntime.d.ts.map +1 -0
- package/dist/node/cleanSlateHostedAgentRuntime.js +525 -0
- package/dist/node/cleanSlateHostedAgentRuntime.js.map +1 -0
- package/dist/node/cleanSlateManagedAuth.d.ts +19 -0
- package/dist/node/cleanSlateManagedAuth.d.ts.map +1 -0
- package/dist/node/cleanSlateManagedAuth.js +123 -0
- package/dist/node/cleanSlateManagedAuth.js.map +1 -0
- package/dist/node/cleanSlateNodeAgentRuntime.d.ts +51 -1
- package/dist/node/cleanSlateNodeAgentRuntime.d.ts.map +1 -1
- package/dist/node/cleanSlateNodeAgentRuntime.js +188 -17
- package/dist/node/cleanSlateNodeAgentRuntime.js.map +1 -1
- package/dist/node/cleanSlateNodeBrowserAutomation.d.ts +12 -0
- package/dist/node/cleanSlateNodeBrowserAutomation.d.ts.map +1 -1
- package/dist/node/cleanSlateNodeBrowserAutomation.js +73 -14
- package/dist/node/cleanSlateNodeBrowserAutomation.js.map +1 -1
- package/dist/node/cleanSlateNodeCommandService.d.ts.map +1 -1
- package/dist/node/cleanSlateNodeCommandService.js +4 -0
- package/dist/node/cleanSlateNodeCommandService.js.map +1 -1
- package/dist/node/cleanSlateNodeMainService.d.ts +2 -1
- package/dist/node/cleanSlateNodeMainService.d.ts.map +1 -1
- package/dist/node/cleanSlateNodeMainService.js +1 -0
- package/dist/node/cleanSlateNodeMainService.js.map +1 -1
- package/dist/node/cleanSlateNodeToolContext.d.ts +2 -0
- package/dist/node/cleanSlateNodeToolContext.d.ts.map +1 -1
- package/dist/node/cleanSlateNodeToolContext.js +1 -1
- package/dist/node/cleanSlateNodeToolContext.js.map +1 -1
- package/dist/node/index.d.ts +6 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +3 -0
- package/dist/node/index.js.map +1 -1
- package/dist/protocol/cleanSlateAI.d.ts +63 -6
- package/dist/protocol/cleanSlateAI.d.ts.map +1 -1
- package/dist/protocol/cleanSlateAI.js +1 -0
- package/dist/protocol/cleanSlateAI.js.map +1 -1
- package/dist/protocol/cleanSlateManagedTokenCoordinator.d.ts +16 -0
- package/dist/protocol/cleanSlateManagedTokenCoordinator.d.ts.map +1 -0
- package/dist/protocol/cleanSlateManagedTokenCoordinator.js +66 -0
- package/dist/protocol/cleanSlateManagedTokenCoordinator.js.map +1 -0
- package/dist/protocol/cleanSlateService.d.ts.map +1 -1
- package/dist/protocol/cleanSlateService.js +3 -5
- package/dist/protocol/cleanSlateService.js.map +1 -1
- package/dist/services/cleanSlateAgentCoordinator.d.ts +81 -0
- package/dist/services/cleanSlateAgentCoordinator.d.ts.map +1 -0
- package/dist/services/cleanSlateAgentCoordinator.js +243 -0
- package/dist/services/cleanSlateAgentCoordinator.js.map +1 -0
- package/dist/services/cleanSlateConversationBranchService.d.ts +34 -0
- package/dist/services/cleanSlateConversationBranchService.d.ts.map +1 -0
- package/dist/services/cleanSlateConversationBranchService.js +70 -0
- package/dist/services/cleanSlateConversationBranchService.js.map +1 -0
- package/dist/services/cleanSlateTools.d.ts +2 -0
- package/dist/services/cleanSlateTools.d.ts.map +1 -1
- package/dist/services/cleanSlateTools.js +2 -0
- package/dist/services/cleanSlateTools.js.map +1 -1
- package/dist/tools/BrowserAutomationTools.d.ts.map +1 -1
- package/dist/tools/BrowserAutomationTools.js +6 -3
- package/dist/tools/BrowserAutomationTools.js.map +1 -1
- package/dist/tools/ExecuteCommandTool.js +2 -2
- package/dist/tools/ExecuteCommandTool.js.map +1 -1
- package/dist/tools/SpawnWorkerTool.d.ts +3 -0
- package/dist/tools/SpawnWorkerTool.d.ts.map +1 -1
- package/dist/tools/SpawnWorkerTool.js +101 -10
- package/dist/tools/SpawnWorkerTool.js.map +1 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +4 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/types.d.ts +3 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) CleanSlate. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
const DEFAULT_API_BASE_URL = 'https://api.thewariend.com/api';
|
|
7
|
+
function resolveApiBaseUrl(value) {
|
|
8
|
+
const baseUrl = (value?.trim() || process.env['CLEANSLATE_API_BASE_URL']?.trim() || DEFAULT_API_BASE_URL).replace(/\/+$/, '');
|
|
9
|
+
const parsed = new URL(baseUrl);
|
|
10
|
+
const localDevelopment = isLocalHostname(parsed.hostname);
|
|
11
|
+
if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && localDevelopment)) {
|
|
12
|
+
throw new Error('CleanSlate authentication requires HTTPS (HTTP is allowed only for local development).');
|
|
13
|
+
}
|
|
14
|
+
if (parsed.username || parsed.password || parsed.search || parsed.hash) {
|
|
15
|
+
throw new Error('CleanSlate authentication API URLs cannot contain credentials, query parameters, or fragments.');
|
|
16
|
+
}
|
|
17
|
+
return baseUrl;
|
|
18
|
+
}
|
|
19
|
+
function isLocalHostname(hostname) {
|
|
20
|
+
return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';
|
|
21
|
+
}
|
|
22
|
+
function seconds(value, fallback, minimum, maximum) {
|
|
23
|
+
return typeof value === 'number' && Number.isFinite(value)
|
|
24
|
+
? Math.min(maximum, Math.max(minimum, value))
|
|
25
|
+
: fallback;
|
|
26
|
+
}
|
|
27
|
+
async function responseError(response) {
|
|
28
|
+
const body = await response.json().catch(() => ({}));
|
|
29
|
+
const validation = body.errors ? Object.values(body.errors)[0]?.[0] : undefined;
|
|
30
|
+
return new Error(validation || body.message || body.error || `CleanSlate authentication failed (${response.status}).`);
|
|
31
|
+
}
|
|
32
|
+
async function loadEntitlements(baseUrl, token, fetcher, signal) {
|
|
33
|
+
const response = await fetcher(`${baseUrl}/cleanslate/entitlements`, {
|
|
34
|
+
headers: { Accept: 'application/json', Authorization: `Bearer ${token}`, 'Cache-Control': 'no-store' },
|
|
35
|
+
signal
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
throw await responseError(response);
|
|
39
|
+
}
|
|
40
|
+
const body = await response.json();
|
|
41
|
+
if (!body.data) {
|
|
42
|
+
throw new Error('CleanSlate authentication succeeded, but no managed-model entitlements were returned.');
|
|
43
|
+
}
|
|
44
|
+
return body.data;
|
|
45
|
+
}
|
|
46
|
+
function openSystemBrowser(url) {
|
|
47
|
+
const command = process.platform === 'darwin' ? '/usr/bin/open' : process.platform === 'win32' ? 'rundll32.exe' : 'xdg-open';
|
|
48
|
+
const args = process.platform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];
|
|
49
|
+
const result = spawnSync(command, args, { stdio: 'ignore' });
|
|
50
|
+
if (result.status !== 0) {
|
|
51
|
+
throw new Error(`Could not open the system browser. Open this URL manually: ${url}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function wait(milliseconds, signal) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
if (signal?.aborted) {
|
|
57
|
+
reject(new Error('CleanSlate sign-in was cancelled.'));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const finish = () => {
|
|
61
|
+
signal?.removeEventListener('abort', cancel);
|
|
62
|
+
resolve();
|
|
63
|
+
};
|
|
64
|
+
const timeout = setTimeout(finish, milliseconds);
|
|
65
|
+
const cancel = () => {
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
signal?.removeEventListener('abort', cancel);
|
|
68
|
+
reject(new Error('CleanSlate sign-in was cancelled.'));
|
|
69
|
+
};
|
|
70
|
+
signal?.addEventListener('abort', cancel, { once: true });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Open the browser-based device flow and return a token usable by provider `cleanslate`. */
|
|
74
|
+
export async function authenticateCleanSlateInBrowser(options = {}) {
|
|
75
|
+
const baseUrl = resolveApiBaseUrl(options.apiBaseUrl);
|
|
76
|
+
const fetcher = options.fetcher ?? fetch;
|
|
77
|
+
const startResponse = await fetcher(`${baseUrl}/auth/device`, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
80
|
+
body: JSON.stringify({
|
|
81
|
+
device_name: options.deviceName?.trim() || `CleanSlate SDK (${process.platform})`
|
|
82
|
+
}),
|
|
83
|
+
signal: options.signal
|
|
84
|
+
});
|
|
85
|
+
if (!startResponse.ok) {
|
|
86
|
+
throw await responseError(startResponse);
|
|
87
|
+
}
|
|
88
|
+
const authorization = await startResponse.json();
|
|
89
|
+
if (!authorization.device_code || !authorization.verification_uri_complete) {
|
|
90
|
+
throw new Error('The server did not return a valid CleanSlate device authorization.');
|
|
91
|
+
}
|
|
92
|
+
const verificationUrl = new URL(authorization.verification_uri_complete);
|
|
93
|
+
const localVerificationUrl = verificationUrl.protocol === 'http:' && isLocalHostname(verificationUrl.hostname);
|
|
94
|
+
if ((verificationUrl.protocol !== 'https:' && !localVerificationUrl) || verificationUrl.username || verificationUrl.password) {
|
|
95
|
+
throw new Error('CleanSlate returned an insecure device authorization URL.');
|
|
96
|
+
}
|
|
97
|
+
options.onReady?.(verificationUrl.href);
|
|
98
|
+
await (options.openBrowser ?? openSystemBrowser)(verificationUrl.href);
|
|
99
|
+
const deadline = Date.now() + seconds(authorization.expires_in, 600, 1, 3_600) * 1_000;
|
|
100
|
+
const interval = seconds(authorization.interval, 2, 1, 60) * 1_000;
|
|
101
|
+
const sleep = options.sleep ?? wait;
|
|
102
|
+
while (Date.now() < deadline) {
|
|
103
|
+
if (options.signal?.aborted) {
|
|
104
|
+
throw new Error('CleanSlate sign-in was cancelled.');
|
|
105
|
+
}
|
|
106
|
+
const tokenResponse = await fetcher(`${baseUrl}/auth/device/token`, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
109
|
+
body: JSON.stringify({ device_code: authorization.device_code }),
|
|
110
|
+
signal: options.signal
|
|
111
|
+
});
|
|
112
|
+
const tokenBody = await tokenResponse.json().catch(() => ({}));
|
|
113
|
+
if (tokenResponse.ok && tokenBody.token) {
|
|
114
|
+
return { token: tokenBody.token, entitlements: await loadEntitlements(baseUrl, tokenBody.token, fetcher, options.signal) };
|
|
115
|
+
}
|
|
116
|
+
if (tokenBody.error !== 'authorization_pending') {
|
|
117
|
+
throw new Error(tokenBody.error || `CleanSlate authentication failed (${tokenResponse.status}).`);
|
|
118
|
+
}
|
|
119
|
+
await sleep(interval, options.signal);
|
|
120
|
+
}
|
|
121
|
+
throw new Error('CleanSlate browser sign-in timed out.');
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=cleanSlateManagedAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanSlateManagedAuth.js","sourceRoot":"","sources":["../../src/node/cleanSlateManagedAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CleanSlateStreamPart } from '../agent/cleanSlateAgentTypes.js';
|
|
2
|
-
import { AIProvider, CleanSlateEmbeddingProvider, ICleanSlateConfiguration, ICleanSlateAgentRuntimeSnapshot, ICleanSlateLogger, ICleanSlatePendingAgentInteraction, IChatMessagePart } from '../protocol/cleanSlateAI.js';
|
|
2
|
+
import { AIProvider, CleanSlateEmbeddingProvider, ICleanSlateConfiguration, ICleanSlateAgentRuntimeSnapshot, ICleanSlateLogger, ICleanSlateMainService, ICleanSlateManagedEntitlements, ICleanSlatePendingAgentInteraction, IChatMessagePart } from '../protocol/cleanSlateAI.js';
|
|
3
|
+
import { CleanSlateManagedTokenCoordinator } from '../protocol/cleanSlateManagedTokenCoordinator.js';
|
|
3
4
|
import { ICleanSlateTaskSessionSnapshot } from '../services/cleanSlateTaskSessionService.js';
|
|
4
5
|
import { ICleanSlateThreadMessage } from '../services/cleanSlateThreadService.js';
|
|
5
6
|
import type { CleanSlateTool } from '../tools/types.js';
|
|
@@ -7,6 +8,8 @@ import type { ICleanSlateDomainProfile } from '../agent/cleanSlateDomainProfile.
|
|
|
7
8
|
import type { AgentDefinition } from '../composer/registry/agentSchema.js';
|
|
8
9
|
export interface ICleanSlateNodeAgentRuntimeOptions {
|
|
9
10
|
rootPath: string;
|
|
11
|
+
/** A desktop host can reuse its authenticated transport and runtime endpoints. */
|
|
12
|
+
mainService?: ICleanSlateMainService;
|
|
10
13
|
/** Private host directory for per-workspace state such as edit recovery history. */
|
|
11
14
|
workspaceStorageHome?: string;
|
|
12
15
|
configuration: ICleanSlateConfiguration;
|
|
@@ -20,6 +23,9 @@ export interface ICleanSlateNodeAgentRuntimeOptions {
|
|
|
20
23
|
instructions?: string | ((task: string) => string | Promise<string>);
|
|
21
24
|
/** Whether browser automation should run without a visible browser window. */
|
|
22
25
|
browserHeadless?: boolean;
|
|
26
|
+
browserAutomationService?: import('../host/browserAutomation.js').ICleanSlateBrowserAutomationService;
|
|
27
|
+
/** Child runtimes share the parent's desktop browser without owning its lifetime. */
|
|
28
|
+
disposeBrowserAutomationService?: boolean;
|
|
23
29
|
approveCommand?: (request: {
|
|
24
30
|
command: string;
|
|
25
31
|
cwd?: string;
|
|
@@ -29,7 +35,18 @@ export interface ICleanSlateNodeAgentRuntimeOptions {
|
|
|
29
35
|
type: string;
|
|
30
36
|
[key: string]: any;
|
|
31
37
|
}) => void;
|
|
38
|
+
/** Desktop hosts present artifacts in their own views instead of an external viewer. */
|
|
39
|
+
onArtifact?: (artifact: {
|
|
40
|
+
id: string;
|
|
41
|
+
type: string;
|
|
42
|
+
content: string;
|
|
43
|
+
metadata?: any;
|
|
44
|
+
}) => void;
|
|
32
45
|
onManagedTokenRefresh?: (token: string) => void | Promise<void>;
|
|
46
|
+
/** Shared authority for hosted conversations, workers and account settings. */
|
|
47
|
+
managedTokenCoordinator?: CleanSlateManagedTokenCoordinator;
|
|
48
|
+
/** Surface-specific recovery copy. CLI hosts default to the setup command. */
|
|
49
|
+
managedSessionExpiredMessage?: string;
|
|
33
50
|
fetcher?: typeof fetch;
|
|
34
51
|
logger?: Partial<ICleanSlateLogger>;
|
|
35
52
|
sessionId?: string;
|
|
@@ -43,6 +60,15 @@ export interface ICleanSlateNodeAgentRuntimeOptions {
|
|
|
43
60
|
}) => boolean | Promise<boolean>;
|
|
44
61
|
/** Multimodal parts explicitly attached by the host for a user turn. */
|
|
45
62
|
resolveAttachments?: (task: string) => IChatMessagePart[] | Promise<IChatMessagePart[]>;
|
|
63
|
+
/** Maximum child agents owned by this runtime at once. */
|
|
64
|
+
maxConcurrentAgents?: number;
|
|
65
|
+
/** Receives portable child-agent lifecycle events for a host UI or logger. */
|
|
66
|
+
onAgentEvent?: (event: {
|
|
67
|
+
type: string;
|
|
68
|
+
[key: string]: any;
|
|
69
|
+
}) => void;
|
|
70
|
+
/** @internal Prevents recursive worker trees. */
|
|
71
|
+
workerDepth?: number;
|
|
46
72
|
}
|
|
47
73
|
export interface ICleanSlateNodeAgentSessionSnapshot {
|
|
48
74
|
version: 1;
|
|
@@ -51,6 +77,12 @@ export interface ICleanSlateNodeAgentSessionSnapshot {
|
|
|
51
77
|
task?: ICleanSlateTaskSessionSnapshot;
|
|
52
78
|
threadHistory: ICleanSlateThreadMessage[];
|
|
53
79
|
}
|
|
80
|
+
export interface ICleanSlateNodeSideChat {
|
|
81
|
+
id: string;
|
|
82
|
+
title: string;
|
|
83
|
+
createdAt: number;
|
|
84
|
+
runtime: CleanSlateNodeAgentRuntime;
|
|
85
|
+
}
|
|
54
86
|
/**
|
|
55
87
|
* Wires CleanSlate's existing execution loop to the Node host and complete tool registry.
|
|
56
88
|
*/
|
|
@@ -59,29 +91,47 @@ export declare class CleanSlateNodeAgentRuntime {
|
|
|
59
91
|
private readonly rootPath;
|
|
60
92
|
private readonly mainService;
|
|
61
93
|
private readonly configService;
|
|
94
|
+
private readonly managedTokenCoordinator;
|
|
62
95
|
private readonly headlessRuntime;
|
|
63
96
|
private readonly queryRunner;
|
|
64
97
|
private readonly cleanSlateService;
|
|
65
98
|
private readonly agentSession;
|
|
66
99
|
private readonly threadService;
|
|
67
100
|
private readonly taskSessionService;
|
|
101
|
+
private readonly agentCoordinator;
|
|
102
|
+
private readonly sideChats;
|
|
68
103
|
private readonly sessionId;
|
|
69
104
|
private readonly contextService;
|
|
70
105
|
constructor(options: ICleanSlateNodeAgentRuntimeOptions);
|
|
71
106
|
run(task: string, signal?: AbortSignal): AsyncIterable<CleanSlateStreamPart>;
|
|
107
|
+
configureRun(configuration: ICleanSlateConfiguration, agentDefinition?: AgentDefinition): Promise<void>;
|
|
72
108
|
plan(task: string, signal?: AbortSignal): AsyncIterable<CleanSlateStreamPart>;
|
|
73
109
|
private runInPhase;
|
|
74
110
|
resumePendingQuestion(answer: string, signal?: AbortSignal): AsyncIterable<CleanSlateStreamPart>;
|
|
75
111
|
approvePlan(signal?: AbortSignal): AsyncIterable<CleanSlateStreamPart>;
|
|
76
112
|
getPendingQuestion(): ICleanSlatePendingAgentInteraction | undefined;
|
|
113
|
+
rejectPlan(): void;
|
|
77
114
|
getSessionSnapshot(): ICleanSlateNodeAgentSessionSnapshot;
|
|
78
115
|
restoreSessionSnapshot(snapshot: ICleanSlateNodeAgentSessionSnapshot | undefined): void;
|
|
79
116
|
clearConversation(): void;
|
|
117
|
+
/** Creates an independent conversational runtime attached to this session. */
|
|
118
|
+
createSideChat(options?: {
|
|
119
|
+
id?: string;
|
|
120
|
+
title?: string;
|
|
121
|
+
inheritContext?: boolean;
|
|
122
|
+
}): ICleanSlateNodeSideChat;
|
|
123
|
+
listSideChats(): Array<Omit<ICleanSlateNodeSideChat, 'runtime'>>;
|
|
124
|
+
getSideChat(id: string): ICleanSlateNodeSideChat | undefined;
|
|
125
|
+
closeSideChat(id: string): boolean;
|
|
80
126
|
getModels(): Promise<string[]>;
|
|
127
|
+
getManagedEntitlements(): Promise<ICleanSlateManagedEntitlements>;
|
|
81
128
|
private runMessages;
|
|
82
129
|
getAvailableToolCount(): number;
|
|
83
130
|
getResult(): import("./cleanSlateHeadlessRunner.js").ICleanSlateHeadlessRunResult;
|
|
84
131
|
dispose(): void;
|
|
132
|
+
listChildAgents(): import("../services/cleanSlateAgentCoordinator.js").ICleanSlateChildAgentSnapshot[];
|
|
133
|
+
cancelChildAgent(agentId: string): boolean;
|
|
134
|
+
private runChildAgent;
|
|
85
135
|
private buildPromptContext;
|
|
86
136
|
private workspaceIsEmpty;
|
|
87
137
|
private getToolDescriptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanSlateNodeAgentRuntime.d.ts","sourceRoot":"","sources":["../../src/node/cleanSlateNodeAgentRuntime.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAKxE,OAAO,EACN,UAAU,EACV,2BAA2B,EAC3B,wBAAwB,EAExB,+BAA+B,EAC/B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"cleanSlateNodeAgentRuntime.d.ts","sourceRoot":"","sources":["../../src/node/cleanSlateNodeAgentRuntime.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,38 +13,68 @@ import { CleanSlateQueryRunner } from '../agent/cleanSlateQueryRunner.js';
|
|
|
13
13
|
import { Event } from '../core/event.js';
|
|
14
14
|
import { getCleanSlateContextDefaults } from '../protocol/cleanSlateModelCapabilities.js';
|
|
15
15
|
import { CleanSlateService } from '../protocol/cleanSlateService.js';
|
|
16
|
+
import { CleanSlateManagedTokenCoordinator } from '../protocol/cleanSlateManagedTokenCoordinator.js';
|
|
16
17
|
import { CleanSlateTaskSessionService } from '../services/cleanSlateTaskSessionService.js';
|
|
17
18
|
import { CleanSlateTaskKind, CleanSlateWorkspaceShape } from '../services/cleanSlateTaskState.js';
|
|
18
19
|
import { CleanSlateThreadService } from '../services/cleanSlateThreadService.js';
|
|
20
|
+
import { CleanSlateAgentCoordinator, formatCleanSlateChildAgentNotification } from '../services/cleanSlateAgentCoordinator.js';
|
|
19
21
|
import { ALL_TOOLS } from '../tools/registry.js';
|
|
20
22
|
import { CleanSlateHeadlessRuntime } from './cleanSlateHeadlessRunner.js';
|
|
21
23
|
import { NodeCleanSlateMainService } from './cleanSlateNodeMainService.js';
|
|
22
24
|
class NodeConfigurationService {
|
|
23
|
-
constructor(configuration, mainService, onManagedTokenRefresh, fetcher = fetch) {
|
|
25
|
+
constructor(configuration, mainService, onManagedTokenRefresh, managedSessionExpiredMessage = 'Your CleanSlate session expired. Run cleanslate --setup to sign in again.', fetcher = fetch, managedTokenCoordinator) {
|
|
24
26
|
this.configuration = configuration;
|
|
25
27
|
this.mainService = mainService;
|
|
26
28
|
this.onManagedTokenRefresh = onManagedTokenRefresh;
|
|
29
|
+
this.managedSessionExpiredMessage = managedSessionExpiredMessage;
|
|
27
30
|
this.fetcher = fetcher;
|
|
28
31
|
this.onDidChangeConfiguration = Event.None;
|
|
32
|
+
this.managedTokenCoordinator = managedTokenCoordinator ?? new CleanSlateManagedTokenCoordinator(token => this.rotateManagedToken(token));
|
|
29
33
|
}
|
|
30
34
|
getConfiguration() {
|
|
35
|
+
const token = this.configuration.providers?.cleanslate?.apiKey;
|
|
36
|
+
const resolved = token ? this.managedTokenCoordinator.resolve(token) : token;
|
|
37
|
+
if (resolved !== token) {
|
|
38
|
+
this.configuration = {
|
|
39
|
+
...this.configuration,
|
|
40
|
+
providers: {
|
|
41
|
+
...this.configuration.providers,
|
|
42
|
+
cleanslate: { ...this.configuration.providers?.cleanslate, apiKey: resolved }
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
31
46
|
return this.configuration;
|
|
32
47
|
}
|
|
33
48
|
getResolvedConfiguration() {
|
|
34
|
-
return Promise.resolve(this.
|
|
49
|
+
return Promise.resolve(this.getConfiguration());
|
|
35
50
|
}
|
|
36
51
|
updateConfiguration(config) {
|
|
37
|
-
|
|
52
|
+
const incomingManagedToken = config.providers?.cleanslate?.apiKey;
|
|
53
|
+
this.configuration = {
|
|
54
|
+
...this.configuration,
|
|
55
|
+
...config,
|
|
56
|
+
providers: config.providers ? {
|
|
57
|
+
...config.providers,
|
|
58
|
+
cleanslate: config.providers.cleanslate ? {
|
|
59
|
+
...config.providers.cleanslate,
|
|
60
|
+
apiKey: incomingManagedToken ? this.managedTokenCoordinator.resolve(incomingManagedToken) : incomingManagedToken
|
|
61
|
+
} : config.providers.cleanslate
|
|
62
|
+
} : this.configuration.providers
|
|
63
|
+
};
|
|
38
64
|
return Promise.resolve();
|
|
39
65
|
}
|
|
40
66
|
async refreshManagedToken(rejectedToken) {
|
|
41
|
-
const current = this.
|
|
67
|
+
const current = this.getConfiguration().providers?.cleanslate?.apiKey;
|
|
42
68
|
if (!current) {
|
|
43
69
|
throw new Error('Sign in to CleanSlate again.');
|
|
44
70
|
}
|
|
45
71
|
if (rejectedToken && current !== rejectedToken) {
|
|
46
72
|
return current;
|
|
47
73
|
}
|
|
74
|
+
const response = await this.managedTokenCoordinator.refresh(current);
|
|
75
|
+
return response.token;
|
|
76
|
+
}
|
|
77
|
+
async rotateManagedToken(current) {
|
|
48
78
|
const runtimeConfig = await this.mainService.getRuntimeConfig();
|
|
49
79
|
const response = await this.fetcher(`${runtimeConfig.apiBaseUrl}/auth/refresh`, {
|
|
50
80
|
method: 'POST',
|
|
@@ -52,24 +82,21 @@ class NodeConfigurationService {
|
|
|
52
82
|
});
|
|
53
83
|
const body = await this.readJson(response);
|
|
54
84
|
if (response.status === 401) {
|
|
55
|
-
throw new Error(
|
|
85
|
+
throw new Error(this.managedSessionExpiredMessage);
|
|
56
86
|
}
|
|
57
87
|
if (!response.ok || typeof body?.token !== 'string' || !body.token) {
|
|
58
88
|
throw new Error(body?.message || `Unable to refresh the CleanSlate session (${response.status}).`);
|
|
59
89
|
}
|
|
60
90
|
const token = body.token;
|
|
61
|
-
this.configuration = {
|
|
62
|
-
...this.configuration,
|
|
63
|
-
providers: {
|
|
64
|
-
...this.configuration.providers,
|
|
65
|
-
cleanslate: { ...this.configuration.providers?.cleanslate, apiKey: token }
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
91
|
await this.onManagedTokenRefresh?.(token);
|
|
69
|
-
return
|
|
92
|
+
return {
|
|
93
|
+
token,
|
|
94
|
+
expires_at: typeof body.expires_at === 'string' ? body.expires_at : undefined,
|
|
95
|
+
expires_in: typeof body.expires_in === 'number' || typeof body.expires_in === 'string' ? body.expires_in : undefined
|
|
96
|
+
};
|
|
70
97
|
}
|
|
71
98
|
async getManagedEntitlements() {
|
|
72
|
-
let token = this.
|
|
99
|
+
let token = this.getConfiguration().providers?.cleanslate?.apiKey;
|
|
73
100
|
if (!token) {
|
|
74
101
|
throw new Error('Sign in to CleanSlate to view your managed models.');
|
|
75
102
|
}
|
|
@@ -128,21 +155,38 @@ export class CleanSlateNodeAgentRuntime {
|
|
|
128
155
|
this.agentSession = new CleanSlateAgentSession();
|
|
129
156
|
this.threadService = new CleanSlateThreadService();
|
|
130
157
|
this.taskSessionService = new CleanSlateTaskSessionService();
|
|
158
|
+
this.sideChats = new Map();
|
|
131
159
|
this.contextService = {
|
|
132
160
|
_serviceBrand: undefined,
|
|
133
161
|
getContext: async () => ({ activeFile: undefined, openFiles: [] })
|
|
134
162
|
};
|
|
135
163
|
this.rootPath = path.resolve(options.rootPath);
|
|
136
164
|
this.sessionId = options.sessionId?.trim() || `cli-${process.pid}-${Date.now()}`;
|
|
137
|
-
this.mainService = new NodeCleanSlateMainService(this.rootPath);
|
|
138
|
-
this.configService = new NodeConfigurationService(options.configuration, this.mainService, options.onManagedTokenRefresh, options.fetcher);
|
|
165
|
+
this.mainService = options.mainService ?? new NodeCleanSlateMainService(this.rootPath);
|
|
166
|
+
this.configService = new NodeConfigurationService(options.configuration, this.mainService, options.onManagedTokenRefresh, options.managedSessionExpiredMessage, options.fetcher, options.managedTokenCoordinator);
|
|
167
|
+
this.managedTokenCoordinator = this.configService.managedTokenCoordinator;
|
|
139
168
|
const cleanSlateService = new CleanSlateService(this.configService, this.mainService, createLogger(options.logger));
|
|
140
169
|
this.cleanSlateService = cleanSlateService;
|
|
170
|
+
this.agentCoordinator = new CleanSlateAgentCoordinator((request, context) => this.runChildAgent(request, context.id, context.signal, context.emitStreamPart), { maxConcurrentAgents: options.maxConcurrentAgents });
|
|
171
|
+
this.agentCoordinator.onDidChangeAgent(event => {
|
|
172
|
+
options.onAgentEvent?.({
|
|
173
|
+
type: 'child_agent',
|
|
174
|
+
eventType: event.type,
|
|
175
|
+
agent: event.agent,
|
|
176
|
+
delta: event.delta,
|
|
177
|
+
streamPart: event.streamPart
|
|
178
|
+
});
|
|
179
|
+
if (event.agent.parentAgentId === this.sessionId
|
|
180
|
+
&& (event.agent.status === 'completed' || event.agent.status === 'failed' || event.agent.status === 'cancelled')) {
|
|
181
|
+
this.agentSession.appendMessage({ role: 'system', content: formatCleanSlateChildAgentNotification(event.agent) });
|
|
182
|
+
}
|
|
183
|
+
});
|
|
141
184
|
this.headlessRuntime = new CleanSlateHeadlessRuntime({
|
|
142
185
|
rootPath: this.rootPath,
|
|
143
186
|
workspaceStorageHome: options.workspaceStorageHome,
|
|
144
187
|
configuration: options.configuration,
|
|
145
188
|
browserHeadless: options.browserHeadless,
|
|
189
|
+
browserAutomationService: options.browserAutomationService,
|
|
146
190
|
fetcher: options.fetcher,
|
|
147
191
|
tools: options.tools ?? ALL_TOOLS,
|
|
148
192
|
cleanSlateService,
|
|
@@ -152,8 +196,15 @@ export class CleanSlateNodeAgentRuntime {
|
|
|
152
196
|
onProgress: options.onProgress
|
|
153
197
|
});
|
|
154
198
|
const toolContext = this.headlessRuntime.getToolContext();
|
|
199
|
+
// Tools (including spawn_worker) must use the same owner as model calls.
|
|
200
|
+
toolContext.sessionId = this.sessionId;
|
|
201
|
+
if (options.onArtifact) {
|
|
202
|
+
toolContext.artifactPresentationHost = { openArtifact: async () => { } };
|
|
203
|
+
toolContext.artifactService.onDidArtifactChange(options.onArtifact);
|
|
204
|
+
}
|
|
155
205
|
toolContext.cleanSlateMainService = this.mainService;
|
|
156
206
|
toolContext.contextService = this.contextService;
|
|
207
|
+
toolContext.agentCoordinator = this.agentCoordinator;
|
|
157
208
|
const parsingSupport = new CleanSlateAgentParsingSupport(this.configService);
|
|
158
209
|
const executionSupport = new CleanSlateAgentExecutionSupport(toolContext.workspaceContextService, toolContext.markerService, this.contextService);
|
|
159
210
|
this.queryRunner = new CleanSlateQueryRunner({
|
|
@@ -179,6 +230,11 @@ export class CleanSlateNodeAgentRuntime {
|
|
|
179
230
|
async *run(task, signal) {
|
|
180
231
|
yield* this.runInPhase(task, AgentPhase.EXECUTION, signal);
|
|
181
232
|
}
|
|
233
|
+
async configureRun(configuration, agentDefinition) {
|
|
234
|
+
this.options.agentDefinition = agentDefinition;
|
|
235
|
+
await this.configService.updateConfiguration(configuration);
|
|
236
|
+
this.options.configuration = this.configService.getConfiguration();
|
|
237
|
+
}
|
|
182
238
|
async *plan(task, signal) {
|
|
183
239
|
yield* this.runInPhase(task, AgentPhase.PLANNING, signal);
|
|
184
240
|
}
|
|
@@ -236,6 +292,10 @@ export class CleanSlateNodeAgentRuntime {
|
|
|
236
292
|
getPendingQuestion() {
|
|
237
293
|
return this.agentSession.getSnapshot()?.pendingInteraction;
|
|
238
294
|
}
|
|
295
|
+
rejectPlan() {
|
|
296
|
+
this.taskSessionService.setAwaitingApproval(false);
|
|
297
|
+
this.taskSessionService.setPhase(AgentPhase.PLANNING);
|
|
298
|
+
}
|
|
239
299
|
getSessionSnapshot() {
|
|
240
300
|
return {
|
|
241
301
|
version: 1,
|
|
@@ -258,9 +318,61 @@ export class CleanSlateNodeAgentRuntime {
|
|
|
258
318
|
this.taskSessionService.reset();
|
|
259
319
|
this.threadService.clearHistory();
|
|
260
320
|
}
|
|
321
|
+
/** Creates an independent conversational runtime attached to this session. */
|
|
322
|
+
createSideChat(options = {}) {
|
|
323
|
+
const id = options.id?.trim() || `${this.sessionId}-side-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
324
|
+
if (this.sideChats.has(id)) {
|
|
325
|
+
throw new Error(`Side chat already exists: ${id}`);
|
|
326
|
+
}
|
|
327
|
+
const inheritedHistory = options.inheritContext === false
|
|
328
|
+
? ''
|
|
329
|
+
: this.threadService.getActiveTaskHistory()
|
|
330
|
+
.filter(message => !message.isInternalState && (message.role === 'user' || message.role === 'assistant'))
|
|
331
|
+
.slice(-8)
|
|
332
|
+
.map(message => `${message.role}: ${message.content}`)
|
|
333
|
+
.join('\n\n');
|
|
334
|
+
const parentAdditionalContext = this.options.additionalContext;
|
|
335
|
+
const runtime = new CleanSlateNodeAgentRuntime({
|
|
336
|
+
...this.options,
|
|
337
|
+
configuration: this.configService.getConfiguration(),
|
|
338
|
+
managedTokenCoordinator: this.managedTokenCoordinator,
|
|
339
|
+
sessionId: id,
|
|
340
|
+
disposeBrowserAutomationService: !this.options.browserAutomationService,
|
|
341
|
+
additionalContext: async (task) => {
|
|
342
|
+
const base = typeof parentAdditionalContext === 'function'
|
|
343
|
+
? await parentAdditionalContext(task)
|
|
344
|
+
: parentAdditionalContext;
|
|
345
|
+
return [
|
|
346
|
+
base?.trim(),
|
|
347
|
+
inheritedHistory ? `Parent conversation context (read-only):\n${inheritedHistory}` : ''
|
|
348
|
+
].filter(Boolean).join('\n\n');
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
const sideChat = { id, title: options.title?.trim() || 'Side chat', createdAt: Date.now(), runtime };
|
|
352
|
+
this.sideChats.set(id, sideChat);
|
|
353
|
+
return sideChat;
|
|
354
|
+
}
|
|
355
|
+
listSideChats() {
|
|
356
|
+
return Array.from(this.sideChats.values()).map(({ id, title, createdAt }) => ({ id, title, createdAt }));
|
|
357
|
+
}
|
|
358
|
+
getSideChat(id) {
|
|
359
|
+
return this.sideChats.get(id);
|
|
360
|
+
}
|
|
361
|
+
closeSideChat(id) {
|
|
362
|
+
const sideChat = this.sideChats.get(id);
|
|
363
|
+
if (!sideChat) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
sideChat.runtime.dispose();
|
|
367
|
+
this.sideChats.delete(id);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
261
370
|
getModels() {
|
|
262
371
|
return this.cleanSlateService.getModels();
|
|
263
372
|
}
|
|
373
|
+
getManagedEntitlements() {
|
|
374
|
+
return this.configService.getManagedEntitlements();
|
|
375
|
+
}
|
|
264
376
|
async *runMessages(messages, objective, phase, signal) {
|
|
265
377
|
const parsingSupport = new CleanSlateAgentParsingSupport(this.configService);
|
|
266
378
|
const budget = new CleanSlateExecutionBudget(parsingSupport.getExecutionLoopSettings().maxTurns);
|
|
@@ -285,10 +397,69 @@ export class CleanSlateNodeAgentRuntime {
|
|
|
285
397
|
return this.headlessRuntime.getResult();
|
|
286
398
|
}
|
|
287
399
|
dispose() {
|
|
400
|
+
for (const sideChat of this.sideChats.values()) {
|
|
401
|
+
sideChat.runtime.dispose();
|
|
402
|
+
}
|
|
403
|
+
this.sideChats.clear();
|
|
288
404
|
const context = this.headlessRuntime.getToolContext();
|
|
289
405
|
context.commandExecutionService.dispose?.();
|
|
290
|
-
|
|
406
|
+
if (this.options.disposeBrowserAutomationService !== false) {
|
|
407
|
+
void context.browserAutomationService.dispose?.();
|
|
408
|
+
}
|
|
291
409
|
void context.mcpClientService.dispose?.();
|
|
410
|
+
if (!this.options.managedTokenCoordinator) {
|
|
411
|
+
this.managedTokenCoordinator.clear();
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
listChildAgents() {
|
|
415
|
+
return this.agentCoordinator.listAgents(this.sessionId);
|
|
416
|
+
}
|
|
417
|
+
cancelChildAgent(agentId) {
|
|
418
|
+
return this.agentCoordinator.cancelAgent(agentId);
|
|
419
|
+
}
|
|
420
|
+
async runChildAgent(request, agentId, signal, emitStreamPart) {
|
|
421
|
+
const workerDepth = this.options.workerDepth ?? 0;
|
|
422
|
+
if (workerDepth >= 1) {
|
|
423
|
+
throw new Error('Nested child agents are disabled. Return the work to the parent agent instead.');
|
|
424
|
+
}
|
|
425
|
+
const child = new CleanSlateNodeAgentRuntime({
|
|
426
|
+
...this.options,
|
|
427
|
+
configuration: this.configService.getConfiguration(),
|
|
428
|
+
managedTokenCoordinator: this.managedTokenCoordinator,
|
|
429
|
+
sessionId: agentId,
|
|
430
|
+
workerDepth: workerDepth + 1,
|
|
431
|
+
disposeBrowserAutomationService: !this.options.browserAutomationService,
|
|
432
|
+
// A child receives the same capabilities, but not delegation authority.
|
|
433
|
+
tools: (this.options.tools ?? ALL_TOOLS).filter(tool => tool.name !== 'spawn_worker'
|
|
434
|
+
&& tool.name !== 'wait_worker'
|
|
435
|
+
&& tool.name !== 'list_workers'
|
|
436
|
+
&& tool.name !== 'cancel_worker'),
|
|
437
|
+
instructions: async (task) => {
|
|
438
|
+
const base = typeof this.options.instructions === 'function'
|
|
439
|
+
? await this.options.instructions(task)
|
|
440
|
+
: this.options.instructions;
|
|
441
|
+
return [
|
|
442
|
+
base?.trim(),
|
|
443
|
+
`You are a ${request.kind ?? 'worker'} child agent. Complete only this bounded assignment and return a concise, evidence-backed result to the parent.`,
|
|
444
|
+
`Assignment label: ${request.description}`
|
|
445
|
+
].filter(Boolean).join('\n\n');
|
|
446
|
+
},
|
|
447
|
+
onProgress: event => this.options.onProgress?.({ ...event, agentId }),
|
|
448
|
+
onAgentEvent: event => this.options.onAgentEvent?.(event)
|
|
449
|
+
});
|
|
450
|
+
let output = '';
|
|
451
|
+
try {
|
|
452
|
+
for await (const part of child.run(request.prompt, signal)) {
|
|
453
|
+
emitStreamPart(part);
|
|
454
|
+
if ((part.type === 'chat_text' || part.type === 'text') && part.content) {
|
|
455
|
+
output += part.content;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return output.trim();
|
|
459
|
+
}
|
|
460
|
+
finally {
|
|
461
|
+
child.dispose();
|
|
462
|
+
}
|
|
292
463
|
}
|
|
293
464
|
async buildPromptContext(task = '') {
|
|
294
465
|
const instructions = typeof this.options.instructions === 'function'
|