@getpaseo/client 0.1.97-beta.3 → 0.1.98
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/dist/daemon-client.d.ts +28 -12
- package/dist/daemon-client.js +146 -27
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/package.json +4 -4
package/dist/daemon-client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
2
|
import { AgentRefreshedStatusPayloadSchema, CheckoutRenameBranchResponseSchema, RenameTerminalResponseSchema, RestartRequestedStatusPayloadSchema, ShutdownRequestedStatusPayloadSchema, type ServerInfoStatusPayload } from "@getpaseo/protocol/messages";
|
|
3
|
-
import type { AgentStreamEventPayload, AgentSnapshotPayload, ProjectPlacementPayload, AgentPermissionResolvedMessage, CreateAgentRequestMessage, CreatePaseoWorktreeRequest, FileDownloadTokenResponse, FileUploadResponse, FileExplorerResponse, FetchAgentTimelineResponseMessage, GitSetupOptions, CheckoutStatusResponse, CheckoutCommitResponse, CheckoutMergeResponse, CheckoutMergeFromBaseResponse, CheckoutPullResponse, CheckoutPushResponse, CheckoutRefreshResponse, CheckoutPrCreateResponse, CheckoutPrMergeResponse, CheckoutPrMergeMethod, CheckoutGithubSetAutoMergeResponse, CheckoutGithubGetCheckDetailsResponse, CheckoutPrStatusResponse, PullRequestTimelineResponse, CheckoutSwitchBranchResponse, StashSaveResponse, StashPopResponse, StashListResponse, ValidateBranchResponse, BranchSuggestionsResponse, GitHubSearchResponse, GitHubSearchRequest, DirectorySuggestionsResponse, PaseoWorktreeListResponse, PaseoWorktreeArchiveResponse, ProjectIconResponse, OpenProjectResponseMessage, ArchiveWorkspaceResponseMessage, WorkspaceSetupStatusResponseMessage, ListCommandsResponse, ListProviderFeaturesResponseMessage, ListProviderModelsResponseMessage, ListProviderModesResponseMessage, ListAvailableProvidersResponse, GetProvidersSnapshotResponseMessage, RefreshProvidersSnapshotResponseMessage, ProviderDiagnosticResponseMessage, DaemonGetStatusResponse, DaemonGetPairingOfferResponse, AgentRewindResponseMessage, ListTerminalsResponse, CreateTerminalResponse, SubscribeTerminalResponse, SubscribeTerminalRequest, CloseItemsResponse, KillTerminalResponse, CaptureTerminalResponse, TerminalInput, SessionInboundMessage, SessionOutboundMessage, SendAgentMessageRequest, PaseoConfigRaw, PaseoConfigRevision, WorkspaceCreateRequest } from "@getpaseo/protocol/messages";
|
|
4
|
-
import type { AgentPermissionRequest, AgentPermissionResponse, AgentPersistenceHandle, AgentProvider, AgentSessionConfig } from "@getpaseo/protocol/agent-types";
|
|
3
|
+
import type { AgentStreamEventPayload, AgentSnapshotPayload, ProjectPlacementPayload, AgentPermissionResolvedMessage, CreateAgentRequestMessage, CreatePaseoWorktreeRequest, FileDownloadTokenResponse, FileUploadResponse, FileExplorerResponse, FetchAgentTimelineResponseMessage, GitSetupOptions, CheckoutStatusResponse, CheckoutCommitResponse, CheckoutMergeResponse, CheckoutMergeFromBaseResponse, CheckoutPullResponse, CheckoutPushResponse, CheckoutRefreshResponse, CheckoutPrCreateResponse, CheckoutPrMergeResponse, CheckoutPrMergeMethod, CheckoutGithubSetAutoMergeResponse, CheckoutGithubGetCheckDetailsResponse, CheckoutPrStatusResponse, PullRequestTimelineResponse, CheckoutSwitchBranchResponse, StashSaveResponse, StashPopResponse, StashListResponse, ValidateBranchResponse, BranchSuggestionsResponse, GitHubSearchResponse, GitHubSearchRequest, DirectorySuggestionsResponse, PaseoWorktreeListResponse, PaseoWorktreeArchiveResponse, ProjectIconResponse, ProjectAddResponse, OpenProjectResponseMessage, ArchiveWorkspaceResponseMessage, WorkspaceSetupStatusResponseMessage, ListCommandsResponse, ListProviderFeaturesResponseMessage, ListProviderModelsResponseMessage, ListProviderModesResponseMessage, ListAvailableProvidersResponse, GetProvidersSnapshotResponseMessage, RefreshProvidersSnapshotResponseMessage, ProviderDiagnosticResponseMessage, ProviderUsageListResponseMessage, DaemonGetStatusResponse, DaemonGetPairingOfferResponse, AgentRewindResponseMessage, ListTerminalsResponse, CreateTerminalResponse, SubscribeTerminalResponse, SubscribeTerminalRequest, CloseItemsResponse, KillTerminalResponse, CaptureTerminalResponse, TerminalInput, SessionInboundMessage, SessionOutboundMessage, SendAgentMessageRequest, PaseoConfigRaw, PaseoConfigRevision, WorkspaceCreateRequest } from "@getpaseo/protocol/messages";
|
|
4
|
+
import type { AgentPermissionRequest, AgentPermissionResponse, AgentPersistenceHandle, AgentProviderNotice, AgentProvider, AgentSessionConfig } from "@getpaseo/protocol/agent-types";
|
|
5
5
|
import type { MutableDaemonConfig, MutableDaemonConfigPatch } from "@getpaseo/protocol/messages";
|
|
6
6
|
import { type DaemonTransportFactory, type WebSocketFactory } from "./daemon-client-transport.js";
|
|
7
7
|
import { type TerminalStreamEvent } from "./terminal-stream-router.js";
|
|
@@ -205,6 +205,7 @@ type ListAvailableProvidersPayload = ListAvailableProvidersResponse["payload"];
|
|
|
205
205
|
type GetProvidersSnapshotPayload = GetProvidersSnapshotResponseMessage["payload"];
|
|
206
206
|
type RefreshProvidersSnapshotPayload = RefreshProvidersSnapshotResponseMessage["payload"];
|
|
207
207
|
type ProviderDiagnosticPayload = ProviderDiagnosticResponseMessage["payload"];
|
|
208
|
+
type ProviderUsageListPayload = ProviderUsageListResponseMessage["payload"];
|
|
208
209
|
type DaemonStatusPayload = DaemonGetStatusResponse["payload"];
|
|
209
210
|
type DaemonPairingOfferPayload = DaemonGetPairingOfferResponse["payload"];
|
|
210
211
|
type ReadProjectConfigPayload = Extract<SessionOutboundMessage, {
|
|
@@ -497,6 +498,7 @@ export interface RenameTerminalInput {
|
|
|
497
498
|
requestId?: string;
|
|
498
499
|
}
|
|
499
500
|
type OpenProjectPayload = OpenProjectResponseMessage["payload"];
|
|
501
|
+
type ProjectAddPayload = ProjectAddResponse["payload"];
|
|
500
502
|
type ArchiveWorkspacePayload = ArchiveWorkspaceResponseMessage["payload"];
|
|
501
503
|
type WorkspaceSetupStatusPayload = WorkspaceSetupStatusResponseMessage["payload"];
|
|
502
504
|
export interface FetchAgentResult {
|
|
@@ -544,7 +546,9 @@ export declare class DaemonClient {
|
|
|
544
546
|
private lastServerInfoMessage;
|
|
545
547
|
private runtimeMetricsInterval;
|
|
546
548
|
private runtimeMetrics;
|
|
547
|
-
private
|
|
549
|
+
private pingProbe;
|
|
550
|
+
private livenessHeartbeatTimer;
|
|
551
|
+
private lastLivenessRttMs;
|
|
548
552
|
private consecutiveLivenessFailures;
|
|
549
553
|
constructor(config: DaemonClientConfig);
|
|
550
554
|
connect(): Promise<void>;
|
|
@@ -558,6 +562,7 @@ export declare class DaemonClient {
|
|
|
558
562
|
get isConnected(): boolean;
|
|
559
563
|
get isConnecting(): boolean;
|
|
560
564
|
get lastError(): string | null;
|
|
565
|
+
getLastLivenessRttMs(): number | null;
|
|
561
566
|
subscribe(handler: DaemonEventHandler): () => void;
|
|
562
567
|
subscribeRawMessages(handler: (message: SessionOutboundMessage) => void): () => void;
|
|
563
568
|
on<TType extends SessionOutboundMessage["type"]>(type: TType, handler: (message: Extract<SessionOutboundMessage, {
|
|
@@ -612,16 +617,20 @@ export declare class DaemonClient {
|
|
|
612
617
|
serverSentAt: number;
|
|
613
618
|
rttMs: number;
|
|
614
619
|
}>;
|
|
615
|
-
|
|
620
|
+
measureLatency(params?: {
|
|
616
621
|
timeoutMs?: number;
|
|
617
|
-
}): Promise<
|
|
618
|
-
|
|
619
|
-
|
|
622
|
+
}): Promise<number>;
|
|
623
|
+
private livenessPing;
|
|
624
|
+
private sendPingAwaitRtt;
|
|
625
|
+
private startLivenessHeartbeat;
|
|
626
|
+
private stopLivenessHeartbeat;
|
|
627
|
+
private scheduleNextLivenessHeartbeat;
|
|
620
628
|
fetchAgents(options?: FetchAgentsOptions): Promise<FetchAgentsPayload>;
|
|
621
629
|
fetchAgentHistory(options?: FetchAgentHistoryOptions): Promise<FetchAgentHistoryPayload>;
|
|
622
630
|
fetchRecentProviderSessions(options?: FetchRecentProviderSessionsOptions): Promise<FetchRecentProviderSessionsPayload>;
|
|
623
631
|
fetchWorkspaces(options?: FetchWorkspacesOptions): Promise<FetchWorkspacesPayload>;
|
|
624
632
|
openProject(cwd: string, requestId?: string): Promise<OpenProjectPayload>;
|
|
633
|
+
addProject(cwd: string, requestId?: string): Promise<ProjectAddPayload>;
|
|
625
634
|
startWorkspaceScript(workspaceId: string, scriptName: string, requestId?: string): Promise<Extract<SessionOutboundMessage, {
|
|
626
635
|
type: "start_workspace_script_response";
|
|
627
636
|
}>["payload"]>;
|
|
@@ -635,6 +644,7 @@ export declare class DaemonClient {
|
|
|
635
644
|
archiveAgent(agentId: string): Promise<{
|
|
636
645
|
archivedAt: string;
|
|
637
646
|
}>;
|
|
647
|
+
detachAgent(agentId: string): Promise<void>;
|
|
638
648
|
updateAgent(agentId: string, updates: {
|
|
639
649
|
name?: string;
|
|
640
650
|
labels?: Record<string, string>;
|
|
@@ -642,6 +652,9 @@ export declare class DaemonClient {
|
|
|
642
652
|
renameProject(projectId: string, customName: string | null, requestId?: string): Promise<{
|
|
643
653
|
customName: string | null;
|
|
644
654
|
}>;
|
|
655
|
+
removeProject(projectId: string, requestId?: string): Promise<{
|
|
656
|
+
removedWorkspaceIds: string[];
|
|
657
|
+
}>;
|
|
645
658
|
setWorkspaceTitle(workspaceId: string, title: string | null, requestId?: string): Promise<{
|
|
646
659
|
title: string | null;
|
|
647
660
|
}>;
|
|
@@ -653,10 +666,10 @@ export declare class DaemonClient {
|
|
|
653
666
|
sendMessage(agentId: string, text: string, options?: SendMessageOptions): Promise<void>;
|
|
654
667
|
rewindAgent(agentId: string, messageId: string, mode: "conversation" | "files" | "both"): Promise<AgentRewindResponseMessage["payload"]>;
|
|
655
668
|
cancelAgent(agentId: string): Promise<void>;
|
|
656
|
-
setAgentMode(agentId: string, modeId: string): Promise<
|
|
669
|
+
setAgentMode(agentId: string, modeId: string): Promise<AgentProviderNotice | null>;
|
|
657
670
|
setAgentModel(agentId: string, modelId: string | null): Promise<void>;
|
|
658
671
|
setAgentFeature(agentId: string, featureId: string, value: unknown): Promise<void>;
|
|
659
|
-
setAgentThinkingOption(agentId: string, thinkingOptionId: string | null): Promise<
|
|
672
|
+
setAgentThinkingOption(agentId: string, thinkingOptionId: string | null): Promise<AgentProviderNotice | null>;
|
|
660
673
|
restartServer(reason?: string, requestId?: string): Promise<RestartRequestedStatusPayload>;
|
|
661
674
|
shutdownServer(requestId?: string): Promise<ShutdownRequestedStatusPayload>;
|
|
662
675
|
setVoiceMode(enabled: boolean, agentId?: string): Promise<SetVoiceModePayload>;
|
|
@@ -825,6 +838,9 @@ export declare class DaemonClient {
|
|
|
825
838
|
getProviderDiagnostic(provider: AgentProvider, options?: {
|
|
826
839
|
requestId?: string;
|
|
827
840
|
}): Promise<ProviderDiagnosticPayload>;
|
|
841
|
+
listProviderUsage(options?: {
|
|
842
|
+
requestId?: string;
|
|
843
|
+
}): Promise<ProviderUsageListPayload>;
|
|
828
844
|
listCommands(agentId: string, requestId?: string): Promise<ListCommandsPayload>;
|
|
829
845
|
listCommands(agentId: string, options?: ListCommandsOptions): Promise<ListCommandsPayload>;
|
|
830
846
|
respondToPermission(agentId: string, requestId: string, response: AgentPermissionResponse): Promise<void>;
|
|
@@ -904,9 +920,9 @@ export declare class DaemonClient {
|
|
|
904
920
|
private scheduleReconnect;
|
|
905
921
|
private emitDisconnectedStateForReconnect;
|
|
906
922
|
private armReconnectTimer;
|
|
907
|
-
private
|
|
908
|
-
private
|
|
909
|
-
private
|
|
923
|
+
private resolvePingProbe;
|
|
924
|
+
private clearPingProbe;
|
|
925
|
+
private rejectPingProbe;
|
|
910
926
|
private recordLivenessFailure;
|
|
911
927
|
private handleSessionMessage;
|
|
912
928
|
private resolveWaiters;
|
package/dist/daemon-client.js
CHANGED
|
@@ -35,10 +35,25 @@ class DaemonRpcError extends Error {
|
|
|
35
35
|
this.code = params.code;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
class PingTimeoutError extends Error {
|
|
39
|
+
constructor(timeoutMs) {
|
|
40
|
+
super(`Ping timed out (${timeoutMs}ms)`);
|
|
41
|
+
this.timeoutMs = timeoutMs;
|
|
42
|
+
this.name = "PingTimeoutError";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function toTimeoutError(error, label, timeoutMs) {
|
|
46
|
+
if (error instanceof PingTimeoutError) {
|
|
47
|
+
return new Error(`${label} timed out (${timeoutMs}ms)`);
|
|
48
|
+
}
|
|
49
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
50
|
+
}
|
|
38
51
|
const DEFAULT_RECONNECT_BASE_DELAY_MS = 1500;
|
|
39
52
|
const DEFAULT_RECONNECT_MAX_DELAY_MS = 30000;
|
|
40
53
|
const DEFAULT_CONNECT_TIMEOUT_MS = 15000;
|
|
41
54
|
const DEFAULT_LIVENESS_TIMEOUT_MS = 5000;
|
|
55
|
+
const LIVENESS_HEARTBEAT_INTERVAL_MS = 10000;
|
|
56
|
+
const LIVENESS_HEARTBEAT_TIMEOUT_MS = 15000;
|
|
42
57
|
const LIVENESS_FAILURE_RECONNECT_THRESHOLD = 2;
|
|
43
58
|
/** Default timeout for waiting for connection before sending queued messages */
|
|
44
59
|
const DEFAULT_SEND_QUEUE_TIMEOUT_MS = 10000;
|
|
@@ -161,7 +176,9 @@ export class DaemonClient {
|
|
|
161
176
|
this.lastServerInfoMessage = null;
|
|
162
177
|
this.runtimeMetricsInterval = null;
|
|
163
178
|
this.runtimeMetrics = null;
|
|
164
|
-
this.
|
|
179
|
+
this.pingProbe = null;
|
|
180
|
+
this.livenessHeartbeatTimer = null;
|
|
181
|
+
this.lastLivenessRttMs = null;
|
|
165
182
|
this.consecutiveLivenessFailures = 0;
|
|
166
183
|
this.logger = config.logger ?? consoleLogger;
|
|
167
184
|
this.logConnectionPath = isRelayClientWebSocketUrl(this.config.url) ? "relay" : "direct";
|
|
@@ -397,7 +414,7 @@ export class DaemonClient {
|
|
|
397
414
|
this.disposeTransport(1000, "Client closed");
|
|
398
415
|
this.clearWaiters(new Error("Daemon client closed"));
|
|
399
416
|
this.rejectPendingSendQueue(new Error("Daemon client closed"));
|
|
400
|
-
this.
|
|
417
|
+
this.rejectPingProbe(new Error("Daemon client closed"));
|
|
401
418
|
this.terminalStreams.clearSlots();
|
|
402
419
|
this.lastServerInfoMessage = null;
|
|
403
420
|
if (this.runtimeMetricsInterval) {
|
|
@@ -440,6 +457,9 @@ export class DaemonClient {
|
|
|
440
457
|
get lastError() {
|
|
441
458
|
return this.lastErrorValue;
|
|
442
459
|
}
|
|
460
|
+
getLastLivenessRttMs() {
|
|
461
|
+
return this.lastLivenessRttMs;
|
|
462
|
+
}
|
|
443
463
|
// ============================================================================
|
|
444
464
|
// Message Subscription
|
|
445
465
|
// ============================================================================
|
|
@@ -765,15 +785,32 @@ export class DaemonClient {
|
|
|
765
785
|
rttMs: Date.now() - clientSentAt,
|
|
766
786
|
};
|
|
767
787
|
}
|
|
768
|
-
|
|
788
|
+
measureLatency(params) {
|
|
789
|
+
const timeoutMs = Math.max(1, params?.timeoutMs ?? DEFAULT_LIVENESS_TIMEOUT_MS);
|
|
790
|
+
return this.sendPingAwaitRtt({ timeoutMs, drivesLivenessFailure: false }).catch((error) => {
|
|
791
|
+
throw toTimeoutError(error, "Latency measurement", timeoutMs);
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
async livenessPing(params) {
|
|
795
|
+
const timeoutMs = Math.max(1, params?.timeoutMs ?? DEFAULT_LIVENESS_TIMEOUT_MS);
|
|
796
|
+
try {
|
|
797
|
+
const rttMs = await this.sendPingAwaitRtt({ timeoutMs, drivesLivenessFailure: true });
|
|
798
|
+
this.lastLivenessRttMs = rttMs;
|
|
799
|
+
return rttMs;
|
|
800
|
+
}
|
|
801
|
+
catch (error) {
|
|
802
|
+
throw toTimeoutError(error, "Liveness check", timeoutMs);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
sendPingAwaitRtt(params) {
|
|
769
806
|
if (this.connectionState.status !== "connected" || !this.transport) {
|
|
770
807
|
return Promise.reject(new Error(`Transport not connected (status: ${this.connectionState.status})`));
|
|
771
808
|
}
|
|
772
|
-
if (this.
|
|
773
|
-
return this.
|
|
809
|
+
if (this.pingProbe) {
|
|
810
|
+
return this.pingProbe.promise;
|
|
774
811
|
}
|
|
775
812
|
const startedAt = perfNow();
|
|
776
|
-
const timeoutMs =
|
|
813
|
+
const timeoutMs = params.timeoutMs;
|
|
777
814
|
let resolveProbe = null;
|
|
778
815
|
let rejectProbe = null;
|
|
779
816
|
const promise = new Promise((resolve, reject) => {
|
|
@@ -785,28 +822,58 @@ export class DaemonClient {
|
|
|
785
822
|
resolve: (value) => resolveProbe?.(value),
|
|
786
823
|
reject: (error) => rejectProbe?.(error),
|
|
787
824
|
timeoutHandle: setTimeout(() => {
|
|
788
|
-
if (this.
|
|
825
|
+
if (this.pingProbe !== probe) {
|
|
789
826
|
return;
|
|
790
827
|
}
|
|
791
|
-
this.
|
|
792
|
-
const error = new
|
|
828
|
+
this.pingProbe = null;
|
|
829
|
+
const error = new PingTimeoutError(timeoutMs);
|
|
793
830
|
probe.reject(error);
|
|
794
|
-
|
|
831
|
+
if (probe.drivesLivenessFailure) {
|
|
832
|
+
this.recordLivenessFailure(toTimeoutError(error, "Liveness check", timeoutMs));
|
|
833
|
+
}
|
|
795
834
|
}, timeoutMs),
|
|
796
835
|
startedAt,
|
|
836
|
+
drivesLivenessFailure: params.drivesLivenessFailure,
|
|
797
837
|
};
|
|
798
|
-
this.
|
|
838
|
+
this.pingProbe = probe;
|
|
799
839
|
try {
|
|
800
840
|
this.transport.send(JSON.stringify({ type: "ping" }));
|
|
801
841
|
}
|
|
802
842
|
catch (error) {
|
|
803
|
-
this.
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
|
|
843
|
+
this.clearPingProbe();
|
|
844
|
+
const sendError = error instanceof Error ? error : new Error(String(error));
|
|
845
|
+
if (probe.drivesLivenessFailure) {
|
|
846
|
+
this.recordLivenessFailure(sendError);
|
|
847
|
+
}
|
|
848
|
+
return Promise.reject(sendError);
|
|
807
849
|
}
|
|
808
850
|
return promise;
|
|
809
851
|
}
|
|
852
|
+
startLivenessHeartbeat() {
|
|
853
|
+
this.stopLivenessHeartbeat();
|
|
854
|
+
this.lastLivenessRttMs = null;
|
|
855
|
+
this.scheduleNextLivenessHeartbeat();
|
|
856
|
+
}
|
|
857
|
+
stopLivenessHeartbeat() {
|
|
858
|
+
if (!this.livenessHeartbeatTimer) {
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
clearTimeout(this.livenessHeartbeatTimer);
|
|
862
|
+
this.livenessHeartbeatTimer = null;
|
|
863
|
+
}
|
|
864
|
+
scheduleNextLivenessHeartbeat() {
|
|
865
|
+
if (this.connectionState.status !== "connected" || this.livenessHeartbeatTimer) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
this.livenessHeartbeatTimer = setTimeout(() => {
|
|
869
|
+
this.livenessHeartbeatTimer = null;
|
|
870
|
+
this.livenessPing({ timeoutMs: LIVENESS_HEARTBEAT_TIMEOUT_MS })
|
|
871
|
+
.catch(() => { })
|
|
872
|
+
.finally(() => {
|
|
873
|
+
this.scheduleNextLivenessHeartbeat();
|
|
874
|
+
});
|
|
875
|
+
}, LIVENESS_HEARTBEAT_INTERVAL_MS);
|
|
876
|
+
}
|
|
810
877
|
// ============================================================================
|
|
811
878
|
// Agent RPCs (requestId-correlated)
|
|
812
879
|
// ============================================================================
|
|
@@ -925,6 +992,17 @@ export class DaemonClient {
|
|
|
925
992
|
timeout: 10000,
|
|
926
993
|
});
|
|
927
994
|
}
|
|
995
|
+
async addProject(cwd, requestId) {
|
|
996
|
+
return this.sendCorrelatedSessionRequest({
|
|
997
|
+
requestId,
|
|
998
|
+
message: {
|
|
999
|
+
type: "project.add.request",
|
|
1000
|
+
cwd,
|
|
1001
|
+
},
|
|
1002
|
+
responseType: "project.add.response",
|
|
1003
|
+
timeout: 10000,
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
928
1006
|
async startWorkspaceScript(workspaceId, scriptName, requestId) {
|
|
929
1007
|
return this.sendCorrelatedSessionRequest({
|
|
930
1008
|
requestId,
|
|
@@ -1117,6 +1195,18 @@ export class DaemonClient {
|
|
|
1117
1195
|
});
|
|
1118
1196
|
return { archivedAt: result.archivedAt };
|
|
1119
1197
|
}
|
|
1198
|
+
async detachAgent(agentId) {
|
|
1199
|
+
const payload = await this.sendNamespacedCorrelatedSessionRequest({
|
|
1200
|
+
message: {
|
|
1201
|
+
type: "agent.detach.request",
|
|
1202
|
+
agentId,
|
|
1203
|
+
},
|
|
1204
|
+
timeout: 10000,
|
|
1205
|
+
});
|
|
1206
|
+
if (!payload.accepted) {
|
|
1207
|
+
throw new Error(payload.error ?? "detachAgent rejected");
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1120
1210
|
async updateAgent(agentId, updates) {
|
|
1121
1211
|
const requestId = this.createRequestId();
|
|
1122
1212
|
const message = SessionInboundMessageSchema.parse({
|
|
@@ -1163,6 +1253,20 @@ export class DaemonClient {
|
|
|
1163
1253
|
}
|
|
1164
1254
|
return { customName: payload.customName };
|
|
1165
1255
|
}
|
|
1256
|
+
async removeProject(projectId, requestId) {
|
|
1257
|
+
const payload = await this.sendNamespacedCorrelatedSessionRequest({
|
|
1258
|
+
requestId,
|
|
1259
|
+
message: {
|
|
1260
|
+
type: "project.remove.request",
|
|
1261
|
+
projectId,
|
|
1262
|
+
},
|
|
1263
|
+
timeout: 10000,
|
|
1264
|
+
});
|
|
1265
|
+
if (!payload.accepted) {
|
|
1266
|
+
throw new Error(payload.error ?? "removeProject rejected");
|
|
1267
|
+
}
|
|
1268
|
+
return { removedWorkspaceIds: payload.removedWorkspaceIds };
|
|
1269
|
+
}
|
|
1166
1270
|
async setWorkspaceTitle(workspaceId, title, requestId) {
|
|
1167
1271
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
1168
1272
|
requestId,
|
|
@@ -1411,6 +1515,7 @@ export class DaemonClient {
|
|
|
1411
1515
|
if (!payload.accepted) {
|
|
1412
1516
|
throw new Error(payload.error ?? "setAgentMode rejected");
|
|
1413
1517
|
}
|
|
1518
|
+
return payload.notice ?? null;
|
|
1414
1519
|
}
|
|
1415
1520
|
async setAgentModel(agentId, modelId) {
|
|
1416
1521
|
const requestId = this.createRequestId();
|
|
@@ -1493,6 +1598,7 @@ export class DaemonClient {
|
|
|
1493
1598
|
if (!payload.accepted) {
|
|
1494
1599
|
throw new Error(payload.error ?? "setAgentThinkingOption rejected");
|
|
1495
1600
|
}
|
|
1601
|
+
return payload.notice ?? null;
|
|
1496
1602
|
}
|
|
1497
1603
|
async restartServer(reason, requestId) {
|
|
1498
1604
|
const resolvedRequestId = this.createRequestId(requestId);
|
|
@@ -2472,6 +2578,15 @@ export class DaemonClient {
|
|
|
2472
2578
|
timeout: 30000,
|
|
2473
2579
|
});
|
|
2474
2580
|
}
|
|
2581
|
+
async listProviderUsage(options) {
|
|
2582
|
+
return this.sendNamespacedCorrelatedSessionRequest({
|
|
2583
|
+
requestId: options?.requestId,
|
|
2584
|
+
message: {
|
|
2585
|
+
type: "provider.usage.list.request",
|
|
2586
|
+
},
|
|
2587
|
+
timeout: 30000,
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2475
2590
|
async listCommands(agentId, requestIdOrOptions) {
|
|
2476
2591
|
const requestId = typeof requestIdOrOptions === "string" ? requestIdOrOptions : requestIdOrOptions?.requestId;
|
|
2477
2592
|
const draftConfig = typeof requestIdOrOptions === "string" ? undefined : requestIdOrOptions?.draftConfig;
|
|
@@ -3134,6 +3249,7 @@ export class DaemonClient {
|
|
|
3134
3249
|
}
|
|
3135
3250
|
}
|
|
3136
3251
|
disposeTransport(code = 1001, reason = "Reconnecting") {
|
|
3252
|
+
this.stopLivenessHeartbeat();
|
|
3137
3253
|
this.cleanupTransport();
|
|
3138
3254
|
if (this.transport) {
|
|
3139
3255
|
try {
|
|
@@ -3217,7 +3333,7 @@ export class DaemonClient {
|
|
|
3217
3333
|
}
|
|
3218
3334
|
this.consecutiveLivenessFailures = 0;
|
|
3219
3335
|
if (parsed.data.type === "pong") {
|
|
3220
|
-
this.
|
|
3336
|
+
this.resolvePingProbe();
|
|
3221
3337
|
this.runtimeMetrics?.recordMessage("pong", bytes, perfNow() - startMs);
|
|
3222
3338
|
return;
|
|
3223
3339
|
}
|
|
@@ -3231,6 +3347,7 @@ export class DaemonClient {
|
|
|
3231
3347
|
tryHandleBinaryFrame(rawBytes) {
|
|
3232
3348
|
const fileFrame = decodeFileTransferFrame(rawBytes);
|
|
3233
3349
|
if (fileFrame) {
|
|
3350
|
+
this.consecutiveLivenessFailures = 0;
|
|
3234
3351
|
this.handleFileTransferFrame(fileFrame);
|
|
3235
3352
|
this.runtimeMetrics?.recordBinaryFrame("other", rawBytes.byteLength, 0);
|
|
3236
3353
|
return true;
|
|
@@ -3239,6 +3356,7 @@ export class DaemonClient {
|
|
|
3239
3356
|
if (!frame) {
|
|
3240
3357
|
return false;
|
|
3241
3358
|
}
|
|
3359
|
+
this.consecutiveLivenessFailures = 0;
|
|
3242
3360
|
const binaryStartMs = perfNow();
|
|
3243
3361
|
this.terminalStreams.handleFrame(frame);
|
|
3244
3362
|
let frameKind = "other";
|
|
@@ -3344,7 +3462,7 @@ export class DaemonClient {
|
|
|
3344
3462
|
// and responses from the previous connection will never arrive.
|
|
3345
3463
|
this.clearWaiters(new Error(reason ?? "Connection lost"));
|
|
3346
3464
|
this.rejectPendingSendQueue(new Error(reason ?? "Connection lost"));
|
|
3347
|
-
this.
|
|
3465
|
+
this.rejectPingProbe(new Error(reason ?? "Connection lost"));
|
|
3348
3466
|
this.terminalStreams.clearSlots();
|
|
3349
3467
|
this.lastServerInfoMessage = null;
|
|
3350
3468
|
if (wasDisposed) {
|
|
@@ -3382,29 +3500,29 @@ export class DaemonClient {
|
|
|
3382
3500
|
this.attemptConnect();
|
|
3383
3501
|
}, delay);
|
|
3384
3502
|
}
|
|
3385
|
-
|
|
3386
|
-
const probe = this.
|
|
3503
|
+
resolvePingProbe() {
|
|
3504
|
+
const probe = this.pingProbe;
|
|
3387
3505
|
if (!probe) {
|
|
3388
3506
|
return;
|
|
3389
3507
|
}
|
|
3390
|
-
this.
|
|
3508
|
+
this.pingProbe = null;
|
|
3391
3509
|
clearTimeout(probe.timeoutHandle);
|
|
3392
|
-
probe.resolve(
|
|
3510
|
+
probe.resolve(perfNow() - probe.startedAt);
|
|
3393
3511
|
}
|
|
3394
|
-
|
|
3395
|
-
const probe = this.
|
|
3512
|
+
clearPingProbe() {
|
|
3513
|
+
const probe = this.pingProbe;
|
|
3396
3514
|
if (!probe) {
|
|
3397
3515
|
return;
|
|
3398
3516
|
}
|
|
3399
|
-
this.
|
|
3517
|
+
this.pingProbe = null;
|
|
3400
3518
|
clearTimeout(probe.timeoutHandle);
|
|
3401
3519
|
}
|
|
3402
|
-
|
|
3403
|
-
const probe = this.
|
|
3520
|
+
rejectPingProbe(error) {
|
|
3521
|
+
const probe = this.pingProbe;
|
|
3404
3522
|
if (!probe) {
|
|
3405
3523
|
return;
|
|
3406
3524
|
}
|
|
3407
|
-
this.
|
|
3525
|
+
this.pingProbe = null;
|
|
3408
3526
|
clearTimeout(probe.timeoutHandle);
|
|
3409
3527
|
probe.reject(error);
|
|
3410
3528
|
}
|
|
@@ -3431,6 +3549,7 @@ export class DaemonClient {
|
|
|
3431
3549
|
this.resetConnectTimeout();
|
|
3432
3550
|
this.reconnectAttempt = 0;
|
|
3433
3551
|
this.updateConnectionState({ status: "connected" }, { event: "HELLO_SERVER_INFO" });
|
|
3552
|
+
this.startLivenessHeartbeat();
|
|
3434
3553
|
this.resubscribeCheckoutDiffSubscriptions();
|
|
3435
3554
|
this.resubscribeTerminalDirectorySubscriptions();
|
|
3436
3555
|
this.flushPendingSendQueue();
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -129,6 +129,9 @@ function createAgentHandleFactory(daemonClient) {
|
|
|
129
129
|
}
|
|
130
130
|
return result;
|
|
131
131
|
},
|
|
132
|
+
detach: async () => {
|
|
133
|
+
await daemonClient.detachAgent(id);
|
|
134
|
+
},
|
|
132
135
|
subscribe: (handler) => daemonClient.on("agent_update", (message) => {
|
|
133
136
|
const update = message.payload;
|
|
134
137
|
if (update.kind === "upsert" && update.agent.id === id) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.98",
|
|
4
4
|
"description": "Paseo client SDK package",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"test": "vitest run"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@getpaseo/protocol": "0.1.
|
|
39
|
-
"@getpaseo/relay": "0.1.
|
|
40
|
-
"zod": "^
|
|
38
|
+
"@getpaseo/protocol": "0.1.98",
|
|
39
|
+
"@getpaseo/relay": "0.1.98",
|
|
40
|
+
"zod": "^4.4.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^20.9.0",
|