@hyperdrive.bot/paseo-client 0.2.5
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 +12 -0
- package/dist/compat/normalize-provider-models.d.ts +11 -0
- package/dist/compat/normalize-provider-models.js +42 -0
- package/dist/daemon-client-relay-e2ee-transport.d.ts +8 -0
- package/dist/daemon-client-relay-e2ee-transport.js +161 -0
- package/dist/daemon-client-runtime-metrics.d.ts +39 -0
- package/dist/daemon-client-runtime-metrics.js +173 -0
- package/dist/daemon-client-transport-types.d.ts +36 -0
- package/dist/daemon-client-transport-types.js +2 -0
- package/dist/daemon-client-transport-utils.d.ts +9 -0
- package/dist/daemon-client-transport-utils.js +121 -0
- package/dist/daemon-client-transport.d.ts +5 -0
- package/dist/daemon-client-transport.js +4 -0
- package/dist/daemon-client-websocket-transport.d.ts +8 -0
- package/dist/daemon-client-websocket-transport.js +120 -0
- package/dist/daemon-client.d.ts +1153 -0
- package/dist/daemon-client.js +4594 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +177 -0
- package/dist/terminal-stream-router.d.ts +28 -0
- package/dist/terminal-stream-router.js +108 -0
- package/package.json +47 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import type { AgentSnapshotPayload, CreateAgentRequestMessage, FetchWorkspacesRequestMessage, FetchWorkspacesResponseMessage, GetProvidersSnapshotResponseMessage, ListAvailableProvidersResponse, ListProviderFeaturesRequestMessage, ListProviderFeaturesResponseMessage, ListProviderModelsResponseMessage, ListProviderModesResponseMessage, MutableDaemonConfig, MutableDaemonConfigPatch, ProviderDiagnosticResponseMessage, ProjectPlacementPayload, RefreshProvidersSnapshotResponseMessage, SendAgentMessageRequest, SessionOutboundMessage, WorkspaceDescriptorPayload } from "@hyperdrive.bot/paseo-protocol/messages";
|
|
2
|
+
import { DaemonClient } from "./daemon-client.js";
|
|
3
|
+
import type { FetchAgentTimelineCursor, FetchAgentTimelineDirection, FetchAgentTimelinePayload, FetchAgentTimelineProjection } from "./daemon-client.js";
|
|
4
|
+
export { DaemonClient };
|
|
5
|
+
export { UploadCancelledError, UploadCapExceededError, UploadFailedError, } from "./daemon-client.js";
|
|
6
|
+
export type { DaemonClientConfig, DaemonEvent, BrowserAutomationExecuteRequestMessage, BrowserAutomationExecuteResponseMessage, WebSocketFactory, WebSocketLike, } from "./daemon-client.js";
|
|
7
|
+
export type ConnectionState = {
|
|
8
|
+
status: "idle";
|
|
9
|
+
} | {
|
|
10
|
+
status: "connecting";
|
|
11
|
+
attempt: number;
|
|
12
|
+
} | {
|
|
13
|
+
status: "connected";
|
|
14
|
+
} | {
|
|
15
|
+
status: "disconnected";
|
|
16
|
+
reason?: string;
|
|
17
|
+
} | {
|
|
18
|
+
status: "disposed";
|
|
19
|
+
};
|
|
20
|
+
export interface PaseoLogger {
|
|
21
|
+
debug(obj: object, msg?: string): void;
|
|
22
|
+
info(obj: object, msg?: string): void;
|
|
23
|
+
warn(obj: object, msg?: string): void;
|
|
24
|
+
error(obj: object, msg?: string): void;
|
|
25
|
+
}
|
|
26
|
+
export interface PaseoClientConfig {
|
|
27
|
+
url: string;
|
|
28
|
+
clientId?: string;
|
|
29
|
+
appVersion?: string;
|
|
30
|
+
runtimeGeneration?: number | null;
|
|
31
|
+
password?: string;
|
|
32
|
+
authHeader?: string;
|
|
33
|
+
suppressSendErrors?: boolean;
|
|
34
|
+
logger?: PaseoLogger;
|
|
35
|
+
connectTimeoutMs?: number;
|
|
36
|
+
e2ee?: {
|
|
37
|
+
enabled?: boolean;
|
|
38
|
+
daemonPublicKeyB64?: string;
|
|
39
|
+
};
|
|
40
|
+
reconnect?: {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
baseDelayMs?: number;
|
|
43
|
+
maxDelayMs?: number;
|
|
44
|
+
};
|
|
45
|
+
runtimeMetricsIntervalMs?: number;
|
|
46
|
+
runtimeMetricsWindowMs?: number;
|
|
47
|
+
}
|
|
48
|
+
export type PaseoWorkspace = WorkspaceDescriptorPayload;
|
|
49
|
+
export type PaseoAgent = AgentSnapshotPayload;
|
|
50
|
+
export type PaseoWorkspaceListOptions = Omit<FetchWorkspacesRequestMessage, "type" | "requestId"> & {
|
|
51
|
+
requestId?: string;
|
|
52
|
+
};
|
|
53
|
+
export interface PaseoWorkspaceListResult {
|
|
54
|
+
requestId: string;
|
|
55
|
+
subscriptionId?: string | null;
|
|
56
|
+
entries: PaseoWorkspace[];
|
|
57
|
+
pageInfo: FetchWorkspacesResponseMessage["payload"]["pageInfo"];
|
|
58
|
+
}
|
|
59
|
+
export interface PaseoWorkspaceOpenOptions {
|
|
60
|
+
cwd: string;
|
|
61
|
+
requestId?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface PaseoWorkspaceOpenResult {
|
|
64
|
+
requestId: string;
|
|
65
|
+
workspace: PaseoWorkspaceHandle | null;
|
|
66
|
+
error: string | null;
|
|
67
|
+
}
|
|
68
|
+
export interface PaseoWorkspaceArchiveResult {
|
|
69
|
+
requestId: string;
|
|
70
|
+
workspaceId: string;
|
|
71
|
+
archivedAt: string | null;
|
|
72
|
+
error: string | null;
|
|
73
|
+
}
|
|
74
|
+
export type PaseoWorkspaceUpdate = Extract<SessionOutboundMessage, {
|
|
75
|
+
type: "workspace_update";
|
|
76
|
+
}>["payload"];
|
|
77
|
+
export type PaseoWorkspaceUpdateHandler = (update: PaseoWorkspaceUpdate) => void;
|
|
78
|
+
/**
|
|
79
|
+
* A handle is a stable typed reference to a daemon resource. Its identity is the
|
|
80
|
+
* daemon id, and `latest()` only returns the most recent snapshot this handle has
|
|
81
|
+
* seen through construction, `refetch()`, or this handle's local subscription.
|
|
82
|
+
*/
|
|
83
|
+
export interface PaseoWorkspaceHandle {
|
|
84
|
+
readonly id: string;
|
|
85
|
+
latest(): PaseoWorkspace | null;
|
|
86
|
+
/**
|
|
87
|
+
* Fetches a fresh workspace snapshot through the existing workspace list RPC,
|
|
88
|
+
* exact-matches this handle id from the result, and updates `latest()`.
|
|
89
|
+
*/
|
|
90
|
+
refetch(options?: {
|
|
91
|
+
requestId?: string;
|
|
92
|
+
}): Promise<PaseoWorkspace | null>;
|
|
93
|
+
archive(requestId?: string): Promise<PaseoWorkspaceArchiveResult>;
|
|
94
|
+
/**
|
|
95
|
+
* Subscribes to already-emitted daemon workspace_update events for this id.
|
|
96
|
+
* This returns a local unsubscribe function; it does not own app cache state or
|
|
97
|
+
* send a daemon unsubscribe RPC. Call `workspaces.list({ subscribe: {} })` when
|
|
98
|
+
* the daemon should start streaming workspace directory updates.
|
|
99
|
+
*/
|
|
100
|
+
subscribe(handler: (update: PaseoWorkspaceUpdate) => void): () => void;
|
|
101
|
+
}
|
|
102
|
+
export interface PaseoWorkspaceActions {
|
|
103
|
+
list(options?: PaseoWorkspaceListOptions): Promise<PaseoWorkspaceListResult>;
|
|
104
|
+
ref(workspace: string | PaseoWorkspace): PaseoWorkspaceHandle;
|
|
105
|
+
open(input: string | PaseoWorkspaceOpenOptions, requestId?: string): Promise<PaseoWorkspaceOpenResult>;
|
|
106
|
+
create(input: string | PaseoWorkspaceOpenOptions, requestId?: string): Promise<PaseoWorkspaceOpenResult>;
|
|
107
|
+
archive(workspace: string | PaseoWorkspaceHandle, requestId?: string): Promise<PaseoWorkspaceArchiveResult>;
|
|
108
|
+
/**
|
|
109
|
+
* Local event subscription over the low-level driver's workspace_update stream.
|
|
110
|
+
* The returned function only removes this SDK listener.
|
|
111
|
+
*/
|
|
112
|
+
subscribe(handler: PaseoWorkspaceUpdateHandler): () => void;
|
|
113
|
+
}
|
|
114
|
+
type PaseoAgentSessionConfig = CreateAgentRequestMessage["config"];
|
|
115
|
+
type PaseoAgentProvider = PaseoAgentSessionConfig["provider"];
|
|
116
|
+
type PaseoAgentConfigOverrides = Partial<Omit<PaseoAgentSessionConfig, "provider" | "cwd">>;
|
|
117
|
+
export interface PaseoAgentCreateOptions extends PaseoAgentConfigOverrides {
|
|
118
|
+
config?: PaseoAgentSessionConfig;
|
|
119
|
+
provider?: CreateAgentRequestMessage["config"]["provider"];
|
|
120
|
+
cwd?: string;
|
|
121
|
+
workspaceId?: string;
|
|
122
|
+
initialPrompt?: string;
|
|
123
|
+
clientMessageId?: string;
|
|
124
|
+
outputSchema?: Record<string, unknown>;
|
|
125
|
+
images?: CreateAgentRequestMessage["images"];
|
|
126
|
+
attachments?: CreateAgentRequestMessage["attachments"];
|
|
127
|
+
git?: CreateAgentRequestMessage["git"];
|
|
128
|
+
worktreeName?: string;
|
|
129
|
+
requestId?: string;
|
|
130
|
+
labels?: Record<string, string>;
|
|
131
|
+
}
|
|
132
|
+
export interface PaseoAgentRefetchResult {
|
|
133
|
+
agent: PaseoAgent;
|
|
134
|
+
project: ProjectPlacementPayload | null;
|
|
135
|
+
}
|
|
136
|
+
export interface PaseoAgentTimelineRefetchOptions {
|
|
137
|
+
direction?: FetchAgentTimelineDirection;
|
|
138
|
+
cursor?: FetchAgentTimelineCursor;
|
|
139
|
+
limit?: number;
|
|
140
|
+
projection?: FetchAgentTimelineProjection;
|
|
141
|
+
requestId?: string;
|
|
142
|
+
}
|
|
143
|
+
export interface PaseoAgentSendOptions {
|
|
144
|
+
messageId?: string;
|
|
145
|
+
images?: Array<{
|
|
146
|
+
data: string;
|
|
147
|
+
mimeType: string;
|
|
148
|
+
}>;
|
|
149
|
+
attachments?: SendAgentMessageRequest["attachments"];
|
|
150
|
+
}
|
|
151
|
+
export type PaseoAgentUpdate = Extract<SessionOutboundMessage, {
|
|
152
|
+
type: "agent_update";
|
|
153
|
+
}>["payload"];
|
|
154
|
+
export type PaseoAgentStream = Extract<SessionOutboundMessage, {
|
|
155
|
+
type: "agent_stream";
|
|
156
|
+
}>["payload"];
|
|
157
|
+
export type PaseoAgentUpdateHandler = (update: PaseoAgentUpdate) => void;
|
|
158
|
+
export interface PaseoAgentTimelineHandle {
|
|
159
|
+
/**
|
|
160
|
+
* Fetches a fresh timeline page through the existing daemon RPC. If the daemon
|
|
161
|
+
* includes an agent snapshot in the response, the parent handle's `latest()`
|
|
162
|
+
* is updated to that snapshot.
|
|
163
|
+
*/
|
|
164
|
+
refetch(options?: PaseoAgentTimelineRefetchOptions): Promise<FetchAgentTimelinePayload>;
|
|
165
|
+
/**
|
|
166
|
+
* Local listener for agent_stream events matching this handle id. It does not
|
|
167
|
+
* retain timeline entries or own application cache state.
|
|
168
|
+
*/
|
|
169
|
+
subscribe(handler: (event: PaseoAgentStream) => void): () => void;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Agent handles follow the same identity/snapshot rule as workspace handles:
|
|
173
|
+
* `id` is stable, while `latest()` is only the newest snapshot observed by this
|
|
174
|
+
* handle through construction, `refetch()`, timeline refetch, archive, or local
|
|
175
|
+
* agent_update subscription.
|
|
176
|
+
*/
|
|
177
|
+
export interface PaseoAgentHandle {
|
|
178
|
+
readonly id: string;
|
|
179
|
+
readonly timeline: PaseoAgentTimelineHandle;
|
|
180
|
+
latest(): PaseoAgent | null;
|
|
181
|
+
refetch(requestId?: string): Promise<PaseoAgentRefetchResult | null>;
|
|
182
|
+
send(text: string, options?: PaseoAgentSendOptions): Promise<void>;
|
|
183
|
+
archive(): Promise<{
|
|
184
|
+
archivedAt: string;
|
|
185
|
+
}>;
|
|
186
|
+
detach(): Promise<void>;
|
|
187
|
+
subscribe(handler: (update: PaseoAgentUpdate) => void): () => void;
|
|
188
|
+
}
|
|
189
|
+
export interface PaseoAgentActions {
|
|
190
|
+
ref(agent: string | PaseoAgent): PaseoAgentHandle;
|
|
191
|
+
create(options: PaseoAgentCreateOptions): Promise<PaseoAgentHandle>;
|
|
192
|
+
/**
|
|
193
|
+
* Local event subscription over the low-level driver's agent_update stream.
|
|
194
|
+
* The returned function only removes this SDK listener.
|
|
195
|
+
*/
|
|
196
|
+
subscribe(handler: PaseoAgentUpdateHandler): () => void;
|
|
197
|
+
}
|
|
198
|
+
export interface PaseoProviderConfig extends PaseoProviderConfigInput {
|
|
199
|
+
provider: PaseoAgentProvider;
|
|
200
|
+
}
|
|
201
|
+
export type PaseoProviderFeatureValues = Record<string, unknown>;
|
|
202
|
+
export interface PaseoProviderConfigInput {
|
|
203
|
+
model?: string;
|
|
204
|
+
modeId?: string;
|
|
205
|
+
thinkingOptionId?: string;
|
|
206
|
+
featureValues?: PaseoProviderFeatureValues;
|
|
207
|
+
}
|
|
208
|
+
export type PaseoProviderModelsResult = ListProviderModelsResponseMessage["payload"];
|
|
209
|
+
export type PaseoProviderModesResult = ListProviderModesResponseMessage["payload"];
|
|
210
|
+
export type PaseoProviderFeaturesInput = ListProviderFeaturesRequestMessage["draftConfig"];
|
|
211
|
+
export type PaseoProviderFeaturesResult = ListProviderFeaturesResponseMessage["payload"];
|
|
212
|
+
export type PaseoProviderAvailabilityResult = ListAvailableProvidersResponse["payload"];
|
|
213
|
+
export type PaseoProviderSnapshotResult = GetProvidersSnapshotResponseMessage["payload"];
|
|
214
|
+
export type PaseoProviderSnapshotUpdate = Extract<SessionOutboundMessage, {
|
|
215
|
+
type: "providers_snapshot_update";
|
|
216
|
+
}>["payload"];
|
|
217
|
+
export type PaseoProviderRefreshResult = RefreshProvidersSnapshotResponseMessage["payload"];
|
|
218
|
+
export type PaseoProviderDiagnosticResult = ProviderDiagnosticResponseMessage["payload"];
|
|
219
|
+
export interface PaseoProviderListOptions {
|
|
220
|
+
cwd?: string;
|
|
221
|
+
requestId?: string;
|
|
222
|
+
}
|
|
223
|
+
export interface PaseoProviderRefreshOptions {
|
|
224
|
+
cwd?: string;
|
|
225
|
+
providers?: PaseoAgentProvider[];
|
|
226
|
+
requestId?: string;
|
|
227
|
+
}
|
|
228
|
+
export interface PaseoProviderActions {
|
|
229
|
+
codex(input?: PaseoProviderConfigInput): PaseoProviderConfig;
|
|
230
|
+
claude(input?: PaseoProviderConfigInput): PaseoProviderConfig;
|
|
231
|
+
opencode(input?: PaseoProviderConfigInput): PaseoProviderConfig;
|
|
232
|
+
copilot(input?: PaseoProviderConfigInput): PaseoProviderConfig;
|
|
233
|
+
config(provider: PaseoAgentProvider, input?: PaseoProviderConfigInput): PaseoProviderConfig;
|
|
234
|
+
listModels(provider: PaseoAgentProvider, options?: PaseoProviderListOptions): Promise<PaseoProviderModelsResult>;
|
|
235
|
+
listModes(provider: PaseoAgentProvider, options?: PaseoProviderListOptions): Promise<PaseoProviderModesResult>;
|
|
236
|
+
listFeatures(draftConfig: PaseoProviderFeaturesInput, options?: {
|
|
237
|
+
requestId?: string;
|
|
238
|
+
}): Promise<PaseoProviderFeaturesResult>;
|
|
239
|
+
listAvailable(options?: {
|
|
240
|
+
requestId?: string;
|
|
241
|
+
}): Promise<PaseoProviderAvailabilityResult>;
|
|
242
|
+
snapshot(options?: PaseoProviderListOptions): Promise<PaseoProviderSnapshotResult>;
|
|
243
|
+
refresh(options?: PaseoProviderRefreshOptions): Promise<PaseoProviderRefreshResult>;
|
|
244
|
+
diagnostic(provider: PaseoAgentProvider, options?: {
|
|
245
|
+
requestId?: string;
|
|
246
|
+
}): Promise<PaseoProviderDiagnosticResult>;
|
|
247
|
+
subscribe(handler: (update: PaseoProviderSnapshotUpdate) => void): () => void;
|
|
248
|
+
}
|
|
249
|
+
export interface PaseoConfigActions {
|
|
250
|
+
/**
|
|
251
|
+
* Reads daemon config through the existing config RPC. Provider profiles,
|
|
252
|
+
* custom provider entries, keys/env, custom binaries, and provider enablement
|
|
253
|
+
* are currently config-file-shaped daemon state, so the SDK exposes this raw
|
|
254
|
+
* typed surface instead of pretending there are higher-level provider-settings
|
|
255
|
+
* RPCs.
|
|
256
|
+
*/
|
|
257
|
+
get(requestId?: string): Promise<{
|
|
258
|
+
requestId: string;
|
|
259
|
+
config: MutableDaemonConfig;
|
|
260
|
+
}>;
|
|
261
|
+
/**
|
|
262
|
+
* Patches daemon config through the existing config RPC. The daemon validates
|
|
263
|
+
* and persists supported fields; unsupported provider/settings workflows remain
|
|
264
|
+
* daemon gaps until first-class RPCs exist.
|
|
265
|
+
*/
|
|
266
|
+
patch(config: MutableDaemonConfigPatch, requestId?: string): Promise<{
|
|
267
|
+
requestId: string;
|
|
268
|
+
config: MutableDaemonConfig;
|
|
269
|
+
}>;
|
|
270
|
+
}
|
|
271
|
+
export interface PaseoClient {
|
|
272
|
+
readonly workspaces: PaseoWorkspaceActions;
|
|
273
|
+
readonly agents: PaseoAgentActions;
|
|
274
|
+
readonly providers: PaseoProviderActions;
|
|
275
|
+
readonly config: PaseoConfigActions;
|
|
276
|
+
connect(): Promise<void>;
|
|
277
|
+
close(): Promise<void>;
|
|
278
|
+
ensureConnected(): void;
|
|
279
|
+
getConnectionState(): ConnectionState;
|
|
280
|
+
}
|
|
281
|
+
export declare function createPaseoClient(config: PaseoClientConfig): PaseoClient;
|
|
282
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { DaemonClient } from "./daemon-client.js";
|
|
2
|
+
export { DaemonClient };
|
|
3
|
+
export { UploadCancelledError, UploadCapExceededError, UploadFailedError, } from "./daemon-client.js";
|
|
4
|
+
export function createPaseoClient(config) {
|
|
5
|
+
const daemonClient = new DaemonClient({
|
|
6
|
+
...config,
|
|
7
|
+
clientId: config.clientId ?? createGeneratedClientId(),
|
|
8
|
+
clientType: "cli",
|
|
9
|
+
});
|
|
10
|
+
const createWorkspaceHandle = createWorkspaceHandleFactory(daemonClient);
|
|
11
|
+
const createAgentHandle = createAgentHandleFactory(daemonClient);
|
|
12
|
+
return {
|
|
13
|
+
workspaces: {
|
|
14
|
+
list: (options) => daemonClient.fetchWorkspaces(options),
|
|
15
|
+
ref: (workspace) => createWorkspaceHandle(workspace),
|
|
16
|
+
open: (input, requestId) => openWorkspace(daemonClient, createWorkspaceHandle, input, requestId),
|
|
17
|
+
create: (input, requestId) => openWorkspace(daemonClient, createWorkspaceHandle, input, requestId),
|
|
18
|
+
archive: (workspace, requestId) => daemonClient.archiveWorkspace(resolveWorkspaceId(workspace), requestId),
|
|
19
|
+
subscribe: (handler) => daemonClient.on("workspace_update", (message) => {
|
|
20
|
+
handler(message.payload);
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
23
|
+
agents: {
|
|
24
|
+
ref: (agent) => createAgentHandle(agent),
|
|
25
|
+
create: async (options) => {
|
|
26
|
+
const agent = await daemonClient.createAgent(options);
|
|
27
|
+
return createAgentHandle(agent);
|
|
28
|
+
},
|
|
29
|
+
subscribe: (handler) => daemonClient.on("agent_update", (message) => {
|
|
30
|
+
handler(message.payload);
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
providers: {
|
|
34
|
+
codex: (input) => providerConfig("codex", input),
|
|
35
|
+
claude: (input) => providerConfig("claude", input),
|
|
36
|
+
opencode: (input) => providerConfig("opencode", input),
|
|
37
|
+
copilot: (input) => providerConfig("copilot", input),
|
|
38
|
+
config: (provider, input) => providerConfig(provider, input),
|
|
39
|
+
listModels: (provider, options) => daemonClient.listProviderModels(provider, options),
|
|
40
|
+
listModes: (provider, options) => daemonClient.listProviderModes(provider, options),
|
|
41
|
+
listFeatures: (draftConfig, options) => daemonClient.listProviderFeatures(draftConfig, options),
|
|
42
|
+
listAvailable: (options) => daemonClient.listAvailableProviders(options),
|
|
43
|
+
snapshot: (options) => daemonClient.getProvidersSnapshot(options),
|
|
44
|
+
refresh: (options) => daemonClient.refreshProvidersSnapshot(options),
|
|
45
|
+
diagnostic: (provider, options) => daemonClient.getProviderDiagnostic(provider, options),
|
|
46
|
+
subscribe: (handler) => daemonClient.on("providers_snapshot_update", (message) => {
|
|
47
|
+
handler(message.payload);
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
config: {
|
|
51
|
+
get: (requestId) => daemonClient.getDaemonConfig(requestId),
|
|
52
|
+
patch: (patch, requestId) => daemonClient.patchDaemonConfig(patch, requestId),
|
|
53
|
+
},
|
|
54
|
+
connect: () => daemonClient.connect(),
|
|
55
|
+
close: () => daemonClient.close(),
|
|
56
|
+
ensureConnected: () => daemonClient.ensureConnected(),
|
|
57
|
+
getConnectionState: () => daemonClient.getConnectionState(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createWorkspaceHandleFactory(daemonClient) {
|
|
61
|
+
return (workspace) => {
|
|
62
|
+
const id = typeof workspace === "string" ? workspace : workspace.id;
|
|
63
|
+
let latest = typeof workspace === "string" ? null : workspace;
|
|
64
|
+
return {
|
|
65
|
+
id,
|
|
66
|
+
latest: () => latest,
|
|
67
|
+
refetch: async (options) => {
|
|
68
|
+
// Best-effort: fetches one page and matches by id client-side, so a workspace beyond
|
|
69
|
+
// the first page won't be found. TODO: add a "get workspace by id" lookup and resolve
|
|
70
|
+
// by exact id instead of paging.
|
|
71
|
+
const result = await daemonClient.fetchWorkspaces({
|
|
72
|
+
requestId: options?.requestId,
|
|
73
|
+
page: { limit: 25 },
|
|
74
|
+
});
|
|
75
|
+
latest = result.entries.find((entry) => entry.id === id) ?? null;
|
|
76
|
+
return latest;
|
|
77
|
+
},
|
|
78
|
+
archive: async (requestId) => {
|
|
79
|
+
const result = await daemonClient.archiveWorkspace(id, requestId);
|
|
80
|
+
if (latest) {
|
|
81
|
+
latest = { ...latest, archivingAt: result.archivedAt };
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
},
|
|
85
|
+
subscribe: (handler) => daemonClient.on("workspace_update", (message) => {
|
|
86
|
+
const update = message.payload;
|
|
87
|
+
if (update.kind === "upsert" && update.workspace.id === id) {
|
|
88
|
+
latest = update.workspace;
|
|
89
|
+
handler(update);
|
|
90
|
+
}
|
|
91
|
+
if (update.kind === "remove" && update.id === id) {
|
|
92
|
+
latest = null;
|
|
93
|
+
handler(update);
|
|
94
|
+
}
|
|
95
|
+
}),
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function createAgentHandleFactory(daemonClient) {
|
|
100
|
+
return (agent) => {
|
|
101
|
+
const id = typeof agent === "string" ? agent : agent.id;
|
|
102
|
+
let latest = typeof agent === "string" ? null : agent;
|
|
103
|
+
const handle = {
|
|
104
|
+
id,
|
|
105
|
+
timeline: {
|
|
106
|
+
refetch: async (options) => {
|
|
107
|
+
const result = await daemonClient.fetchAgentTimeline(id, options);
|
|
108
|
+
if (result.agent) {
|
|
109
|
+
latest = result.agent;
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
},
|
|
113
|
+
subscribe: (handler) => daemonClient.on("agent_stream", (message) => {
|
|
114
|
+
if (message.payload.agentId === id) {
|
|
115
|
+
handler(message.payload);
|
|
116
|
+
}
|
|
117
|
+
}),
|
|
118
|
+
},
|
|
119
|
+
latest: () => latest,
|
|
120
|
+
refetch: async (requestId) => {
|
|
121
|
+
const result = await daemonClient.fetchAgent({ agentId: id, requestId });
|
|
122
|
+
latest = result?.agent ?? null;
|
|
123
|
+
return result;
|
|
124
|
+
},
|
|
125
|
+
send: (text, options) => daemonClient.sendAgentMessage(id, text, options),
|
|
126
|
+
archive: async () => {
|
|
127
|
+
const result = await daemonClient.archiveAgent(id);
|
|
128
|
+
if (latest) {
|
|
129
|
+
latest = { ...latest, archivedAt: result.archivedAt };
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
},
|
|
133
|
+
detach: async () => {
|
|
134
|
+
await daemonClient.detachAgent(id);
|
|
135
|
+
},
|
|
136
|
+
subscribe: (handler) => daemonClient.on("agent_update", (message) => {
|
|
137
|
+
const update = message.payload;
|
|
138
|
+
if (update.kind === "upsert" && update.agent.id === id) {
|
|
139
|
+
latest = update.agent;
|
|
140
|
+
handler(update);
|
|
141
|
+
}
|
|
142
|
+
if (update.kind === "remove" && update.agentId === id) {
|
|
143
|
+
latest = null;
|
|
144
|
+
handler(update);
|
|
145
|
+
}
|
|
146
|
+
}),
|
|
147
|
+
};
|
|
148
|
+
return handle;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async function openWorkspace(daemonClient, createWorkspaceHandle, input, requestId) {
|
|
152
|
+
const options = typeof input === "string" ? { cwd: input, requestId } : input;
|
|
153
|
+
const result = await daemonClient.openProject(options.cwd, options.requestId);
|
|
154
|
+
return {
|
|
155
|
+
...result,
|
|
156
|
+
workspace: result.workspace ? createWorkspaceHandle(result.workspace) : null,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function resolveWorkspaceId(workspace) {
|
|
160
|
+
return typeof workspace === "string" ? workspace : workspace.id;
|
|
161
|
+
}
|
|
162
|
+
function providerConfig(provider, input = {}) {
|
|
163
|
+
return {
|
|
164
|
+
provider,
|
|
165
|
+
...(input.model !== undefined ? { model: input.model } : {}),
|
|
166
|
+
...(input.modeId !== undefined ? { modeId: input.modeId } : {}),
|
|
167
|
+
...(input.thinkingOptionId !== undefined ? { thinkingOptionId: input.thinkingOptionId } : {}),
|
|
168
|
+
...(input.featureValues !== undefined ? { featureValues: input.featureValues } : {}),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function createGeneratedClientId() {
|
|
172
|
+
const randomId = typeof globalThis.crypto?.randomUUID === "function"
|
|
173
|
+
? globalThis.crypto.randomUUID()
|
|
174
|
+
: Math.random().toString(36).slice(2);
|
|
175
|
+
return `paseo-sdk-${randomId}`;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type TerminalStreamFrame } from "@hyperdrive.bot/paseo-protocol/binary-frames/index";
|
|
2
|
+
import type { TerminalInput, TerminalState } from "@hyperdrive.bot/paseo-protocol/messages";
|
|
3
|
+
export type TerminalStreamEvent = {
|
|
4
|
+
terminalId: string;
|
|
5
|
+
type: "output";
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
} | {
|
|
8
|
+
terminalId: string;
|
|
9
|
+
type: "snapshot";
|
|
10
|
+
state: TerminalState;
|
|
11
|
+
} | {
|
|
12
|
+
terminalId: string;
|
|
13
|
+
type: "restore";
|
|
14
|
+
data: Uint8Array;
|
|
15
|
+
};
|
|
16
|
+
export declare class TerminalStreamRouter {
|
|
17
|
+
private readonly terminalSlots;
|
|
18
|
+
private readonly slotTerminals;
|
|
19
|
+
private readonly listeners;
|
|
20
|
+
onEvent(handler: (event: TerminalStreamEvent) => void): () => void;
|
|
21
|
+
setSlot(terminalId: string, slot: number): void;
|
|
22
|
+
removeTerminal(terminalId: string): void;
|
|
23
|
+
clearSlots(): void;
|
|
24
|
+
encodeInput(terminalId: string, message: TerminalInput["message"]): Uint8Array | null;
|
|
25
|
+
handleFrame(frame: TerminalStreamFrame): void;
|
|
26
|
+
private emit;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=terminal-stream-router.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { decodeTerminalSnapshotPayload, encodeTerminalResizePayload, encodeTerminalStreamFrame, TerminalStreamOpcode, } from "@hyperdrive.bot/paseo-protocol/binary-frames/index";
|
|
2
|
+
export class TerminalStreamRouter {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.terminalSlots = new Map();
|
|
5
|
+
this.slotTerminals = new Map();
|
|
6
|
+
this.listeners = new Set();
|
|
7
|
+
}
|
|
8
|
+
onEvent(handler) {
|
|
9
|
+
this.listeners.add(handler);
|
|
10
|
+
return () => {
|
|
11
|
+
this.listeners.delete(handler);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
setSlot(terminalId, slot) {
|
|
15
|
+
const existingTerminalId = this.slotTerminals.get(slot);
|
|
16
|
+
if (existingTerminalId && existingTerminalId !== terminalId) {
|
|
17
|
+
this.terminalSlots.delete(existingTerminalId);
|
|
18
|
+
}
|
|
19
|
+
const existingSlot = this.terminalSlots.get(terminalId);
|
|
20
|
+
if (typeof existingSlot === "number" && existingSlot !== slot) {
|
|
21
|
+
this.slotTerminals.delete(existingSlot);
|
|
22
|
+
}
|
|
23
|
+
this.terminalSlots.set(terminalId, slot);
|
|
24
|
+
this.slotTerminals.set(slot, terminalId);
|
|
25
|
+
}
|
|
26
|
+
removeTerminal(terminalId) {
|
|
27
|
+
const slot = this.terminalSlots.get(terminalId);
|
|
28
|
+
if (typeof slot !== "number") {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.terminalSlots.delete(terminalId);
|
|
32
|
+
if (this.slotTerminals.get(slot) === terminalId) {
|
|
33
|
+
this.slotTerminals.delete(slot);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
clearSlots() {
|
|
37
|
+
this.terminalSlots.clear();
|
|
38
|
+
this.slotTerminals.clear();
|
|
39
|
+
}
|
|
40
|
+
encodeInput(terminalId, message) {
|
|
41
|
+
const slot = this.terminalSlots.get(terminalId);
|
|
42
|
+
if (typeof slot !== "number") {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (message.type === "input") {
|
|
46
|
+
return encodeTerminalStreamFrame({
|
|
47
|
+
opcode: TerminalStreamOpcode.Input,
|
|
48
|
+
slot,
|
|
49
|
+
payload: message.data,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (message.type === "resize") {
|
|
53
|
+
return encodeTerminalStreamFrame({
|
|
54
|
+
opcode: TerminalStreamOpcode.Resize,
|
|
55
|
+
slot,
|
|
56
|
+
payload: encodeTerminalResizePayload({
|
|
57
|
+
rows: message.rows,
|
|
58
|
+
cols: message.cols,
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
handleFrame(frame) {
|
|
65
|
+
const terminalId = this.slotTerminals.get(frame.slot);
|
|
66
|
+
if (!terminalId) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (frame.opcode === TerminalStreamOpcode.Output) {
|
|
70
|
+
this.emit({
|
|
71
|
+
terminalId,
|
|
72
|
+
type: "output",
|
|
73
|
+
data: frame.payload,
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (frame.opcode === TerminalStreamOpcode.Restore) {
|
|
78
|
+
this.emit({
|
|
79
|
+
terminalId,
|
|
80
|
+
type: "restore",
|
|
81
|
+
data: frame.payload,
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (frame.opcode === TerminalStreamOpcode.Snapshot) {
|
|
86
|
+
const state = decodeTerminalSnapshotPayload(frame.payload);
|
|
87
|
+
if (!state) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.emit({
|
|
91
|
+
terminalId,
|
|
92
|
+
type: "snapshot",
|
|
93
|
+
state,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
emit(event) {
|
|
98
|
+
for (const listener of this.listeners) {
|
|
99
|
+
try {
|
|
100
|
+
listener(event);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// no-op
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=terminal-stream-router.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hyperdrive.bot/paseo-client",
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "Paseo client SDK package",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"!dist/**/*.map",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./internal/daemon-client": {
|
|
17
|
+
"types": "./dist/daemon-client.d.ts",
|
|
18
|
+
"default": "./dist/daemon-client.js"
|
|
19
|
+
},
|
|
20
|
+
"./internal/daemon-client-transport-types": {
|
|
21
|
+
"types": "./dist/daemon-client-transport-types.d.ts",
|
|
22
|
+
"default": "./dist/daemon-client-transport-types.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"clean": "node ../../scripts/clean-package-dist.mjs",
|
|
30
|
+
"build": "npm run build --workspace=@hyperdrive.bot/paseo-protocol && tsc -p tsconfig.json --incremental false",
|
|
31
|
+
"build:clean": "npm run clean && npm run build",
|
|
32
|
+
"prepack": "npm run build:clean",
|
|
33
|
+
"typecheck": "tsgo --noEmit",
|
|
34
|
+
"typecheck:examples": "tsgo -p tsconfig.examples.json --noEmit",
|
|
35
|
+
"test": "vitest run"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@hyperdrive.bot/paseo-protocol": "0.2.5",
|
|
39
|
+
"@hyperdrive.bot/paseo-relay": "0.2.5",
|
|
40
|
+
"zod": "^4.4.3"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20.9.0",
|
|
44
|
+
"typescript": "^5.2.2",
|
|
45
|
+
"vitest": "^4.1.6"
|
|
46
|
+
}
|
|
47
|
+
}
|