@camerontaylor/paseo-client 0.11.1-fork.1 → 0.11.2-fork.1

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.
@@ -39,7 +39,10 @@ export declare const DEFAULT_CLIENT_CAPABILITIES: {
39
39
  timeline_notifications: true;
40
40
  plugin_timeline_items: true;
41
41
  workspace_setup_blocked: true;
42
+ durable_agent_queue: true;
43
+ durable_voice_input_v1: true;
42
44
  explicit_event_subscriptions: true;
45
+ companion_stream_port_v1: true;
43
46
  };
44
47
  /** Calling releases demand; ready waits for membership, or local attachment on broadcast hosts. */
45
48
  export type TimelineSubscription = (() => void) & {
@@ -112,6 +112,10 @@ export const DEFAULT_CLIENT_CAPABILITIES = {
112
112
  [CLIENT_CAPS.timelineNotifications]: true,
113
113
  [CLIENT_CAPS.pluginTimelineItems]: true,
114
114
  [CLIENT_CAPS.workspaceSetupBlocked]: true,
115
+ [CLIENT_CAPS.durableAgentQueue]: true,
116
+ [CLIENT_CAPS.durableVoiceInputV1]: true,
115
117
  [CLIENT_CAPS.explicitEventSubscriptions]: true,
118
+ // COMPAT(companionStreamPortV1): added in v0.11.0-beta.3-fork, remove after 2027-04-01.
119
+ [CLIENT_CAPS.companionStreamPortV1]: true,
116
120
  };
117
121
  //# sourceMappingURL=index.js.map
@@ -1,11 +1,11 @@
1
1
  import { type TimelineMessage } from "./timeline-subscription/index.js";
2
2
  import { type OwnedSubscription, type TimelineSubscription } from "./connection/index.js";
3
- import type { CreationSnapshot } from "@camerontaylor/paseo-protocol/messages";
3
+ import type { AgentQueueSnapshot, CreationSnapshot } from "@camerontaylor/paseo-protocol/messages";
4
4
  import type { z } from "zod";
5
5
  import type { SessionEventSubscription } from "@camerontaylor/paseo-protocol/messages";
6
6
  import type { ClientCapability } from "@camerontaylor/paseo-protocol/client-capabilities";
7
7
  import type { AgentAttentionNotificationPayload } from "@camerontaylor/paseo-protocol/agent-attention-notification";
8
- import { AgentRefreshedStatusPayloadSchema, CheckoutRenameBranchResponseSchema, CheckoutBaseRefSetResponseSchema, RenameTerminalResponseSchema, RestartRequestedStatusPayloadSchema, ShutdownRequestedStatusPayloadSchema, DaemonUpdateResponseSchema, type ActiveTurnBehavior, type ServerInfoStatusPayload } from "@camerontaylor/paseo-protocol/messages";
8
+ import { AgentRefreshedStatusPayloadSchema, CheckoutRenameBranchResponseSchema, CheckoutBaseRefSetResponseSchema, RenameTerminalResponseSchema, RestartRequestedStatusPayloadSchema, ShutdownRequestedStatusPayloadSchema, DaemonUpdateResponseSchema, type ActiveTurnBehavior, type AgentAttachmentWire, type QueuedAgentDeliveryIntent, type QueuedComposerAttachment, type ServerInfoStatusPayload } from "@camerontaylor/paseo-protocol/messages";
9
9
  import type { AgentStreamEventPayload, AgentSnapshotPayload, ProjectPlacementPayload, AgentPermissionResolvedMessage, CreateAgentRequestMessage, CreatePaseoWorktreeRequest, FileDownloadTokenResponse, FileUploadResponse, FileExplorerResponse, FileVersion, FileWriteResult, FetchAgentTimelineResponseMessage, AgentForkContextResponseMessage, GitSetupOptions, CheckoutStatusResponse, CheckoutCommit, ParsedDiffFile, CheckoutCommitResponse, CheckoutMergeResponse, CheckoutMergeFromBaseResponse, CheckoutPullResponse, CheckoutPushResponse, CheckoutRefreshResponse, CheckoutPrCreateResponse, CheckoutPrMergeResponse, CheckoutPrMergeMethod, CheckoutForgeSetAutoMergeResponse, CheckoutGithubSetAutoMergeResponse, CheckoutForgeGetCheckDetailsResponse, CheckoutGithubGetCheckDetailsResponse, CheckoutPrStatusResponse, PullRequestTimelineResponse, CheckoutSwitchBranchResponse, StashSaveResponse, StashPopResponse, StashListResponse, ValidateBranchResponse, BranchSuggestionsResponse, ForgeSearchResponse, ForgeSearchRequest, GitHubSearchResponse, GitHubSearchRequest, DirectorySuggestionsResponse, PaseoWorktreeListResponse, PaseoWorktreeArchiveResponse, ProjectIconSource, ProjectIconResponse, ProjectIconGetResponse, ProjectAddResponse, ProjectCreateDirectoryResponse, OpenProjectResponseMessage, WorkspaceGithubSearchRepositoriesResponse, ProjectGithubCloneProtocol, ProjectGithubCloneResponse, ArchiveWorkspaceResponseMessage, WorkspaceSetupStatusResponseMessage, ListCommandsResponse, ListProviderFeaturesResponseMessage, ListProviderModelsResponseMessage, ListProviderModesResponseMessage, ListAvailableProvidersResponse, GetProvidersSnapshotResponseMessage, RefreshProvidersSnapshotResponseMessage, ProviderDiagnosticResponseMessage, ProviderUsageListResponseMessage, UsageReportEntry, DaemonGetStatusResponse, DaemonGetPairingOfferResponse, DaemonConfigReloadResponse, DiagnosticsResponse, AgentRewindResponseMessage, ListTerminalsResponse, CreateTerminalResponse, SubscribeTerminalResponse, SubscribeTerminalRequest, CloseItemsResponse, KillTerminalResponse, CaptureTerminalResponse, TerminalInput, SessionInboundMessage, SessionOutboundMessage, SendAgentMessageRequest, PaseoConfigRaw, PaseoConfigRevision, WorkspaceCreateRequest, WorkspaceRecoveryState, PluginListItem, PluginLogEntry, PluginSourceStatusItem, PluginSourceUpdateItem, PluginUpdateSelection, PluginUpdateProposal, PluginUpdatePreview, PluginUpdateResult, AgentSkillSelection, AgentSkillsStatus, AgentSkillsSaveResult } from "@camerontaylor/paseo-protocol/messages";
10
10
  import type { AgentPermissionRequest, AgentPermissionResponse, AgentPersistenceHandle, AgentProviderNotice, AgentProvider, AgentSessionConfig } from "@camerontaylor/paseo-protocol/agent-types";
11
11
  import type { AgentConfigApply, MutableDaemonConfig, MutableDaemonConfigPatch } from "@camerontaylor/paseo-protocol/messages";
@@ -592,6 +592,11 @@ export declare class DaemonConnectionError extends Error {
592
592
  constructor(message: string, code?: "DAEMON_CONNECTION_LOST" | "DAEMON_REQUEST_TIMEOUT");
593
593
  }
594
594
  export declare function supportsUsageReports(features: ServerInfoStatusPayload["features"]): boolean;
595
+ /** Identifies the voice attachment a voice message belongs to. */
596
+ export interface VoiceTransport {
597
+ attachmentId: string;
598
+ generation: string;
599
+ }
595
600
  export declare class DaemonClient {
596
601
  private config;
597
602
  private readonly providerSnapshotUpdates;
@@ -833,6 +838,26 @@ export declare class DaemonClient {
833
838
  name?: string;
834
839
  labels?: Record<string, string>;
835
840
  }): Promise<void>;
841
+ updateCompanionEntry(input: {
842
+ agentId: string;
843
+ entryId?: string;
844
+ action: "update_status" | "add_pin" | "remove_pin" | "add_q_and_a";
845
+ status?: "open" | "reviewed" | "done";
846
+ text?: string;
847
+ answerText?: string;
848
+ sourceId?: string;
849
+ }): Promise<void>;
850
+ /**
851
+ * Backfills an agent's artifact feed from files already on disk. Needed for
852
+ * agents whose work predates the artifact feed, whose feeds are otherwise
853
+ * permanently empty.
854
+ */
855
+ scanAgentArtifacts(agentId: string, options?: {
856
+ limit?: number;
857
+ }): Promise<{
858
+ addedOrUpdated: number;
859
+ total: number;
860
+ }>;
836
861
  renameProject(projectId: string, customName: string | null, requestId?: string): Promise<{
837
862
  customName: string | null;
838
863
  }>;
@@ -885,6 +910,53 @@ export declare class DaemonClient {
885
910
  buildAgentForkContext(agentId: string, options?: AgentForkContextOptions): Promise<AgentForkContextPayload>;
886
911
  sendAgentMessage(agentId: string, text: string, options?: SendMessageOptions): Promise<void>;
887
912
  sendMessage(agentId: string, text: string, options?: SendMessageOptions): Promise<void>;
913
+ /**
914
+ * Admits a prompt into the durable queue with an explicit delivery intent.
915
+ * `itemId` comes from the caller so an optimistic local row and the stored
916
+ * item share an id, which makes a reconnect retry of the same enqueue a
917
+ * daemon-side no-op instead of a duplicate.
918
+ */
919
+ enqueueAgentMessage(input: {
920
+ agentId: string;
921
+ itemId: string;
922
+ text: string;
923
+ intent: QueuedAgentDeliveryIntent;
924
+ images?: Array<{
925
+ data: string;
926
+ mimeType: string;
927
+ }>;
928
+ attachments?: AgentAttachmentWire[];
929
+ composerAttachments?: QueuedComposerAttachment[];
930
+ }): Promise<AgentQueueSnapshot>;
931
+ updateQueuedAgentMessage(input: {
932
+ agentId: string;
933
+ itemId: string;
934
+ text: string;
935
+ expectedRevision: number;
936
+ images?: Array<{
937
+ data: string;
938
+ mimeType: string;
939
+ }>;
940
+ attachments?: AgentAttachmentWire[];
941
+ composerAttachments?: QueuedComposerAttachment[];
942
+ }): Promise<AgentQueueSnapshot>;
943
+ reorderQueuedAgentMessages(agentId: string, itemIds: string[], expectedRevision: number): Promise<AgentQueueSnapshot>;
944
+ deleteQueuedAgentMessage(agentId: string, itemId: string, expectedRevision: number): Promise<AgentQueueSnapshot>;
945
+ retryQueuedAgentMessage(agentId: string, itemId: string, expectedRevision: number): Promise<AgentQueueSnapshot>;
946
+ sendQueuedAgentMessageNow(agentId: string, itemId: string, expectedRevision: number): Promise<AgentQueueSnapshot>;
947
+ listQueuedAgentMessages(agentId: string): Promise<AgentQueueSnapshot>;
948
+ /**
949
+ * Fetches the image bytes of one queued item. A device that did not queue the
950
+ * item has no local copy, so pulling it back into the composer would
951
+ * otherwise drop the images.
952
+ */
953
+ getQueuedAgentMessageImages(agentId: string, itemId: string): Promise<Array<{
954
+ id: string;
955
+ mimeType: string;
956
+ fileName?: string | null;
957
+ data: string;
958
+ }>>;
959
+ private requireAgentQueuePayload;
888
960
  rewindAgent(agentId: string, messageId: string, mode: "conversation" | "files" | "both"): Promise<AgentRewindResponseMessage["payload"]>;
889
961
  cancelAgent(agentId: string): Promise<void>;
890
962
  setAgentMode(agentId: string, modeId: string): Promise<AgentProviderNotice | null>;
@@ -904,8 +976,23 @@ export declare class DaemonClient {
904
976
  }): Promise<RestartRequestedStatusPayload>;
905
977
  shutdownServer(options?: ShutdownServerOptions): Promise<ShutdownRequestedStatusPayload>;
906
978
  updateDaemon(requestId?: string): Promise<DaemonUpdateResponse["payload"]>;
907
- setVoiceMode(enabled: boolean, agentId?: string): Promise<SetVoiceModePayload>;
908
- sendVoiceAudioChunk(audio: string, format: string, isLast?: boolean): Promise<void>;
979
+ setVoiceMode(enabled: boolean, agentId?: string, input?: {
980
+ /** Voice attachment identity; the host binds its transport generation to it. */
981
+ attachmentId?: string;
982
+ /** Supplied when an existing attachment reclaims itself after a reconnect. */
983
+ generation?: string;
984
+ }): Promise<SetVoiceModePayload>;
985
+ /** Reads this attachment's delivery receipts so the panel can show truthful state. */
986
+ readVoiceInputReceipts(input: {
987
+ agentId: string;
988
+ attachmentId: string;
989
+ generation: string;
990
+ after?: string;
991
+ limit?: number;
992
+ }): Promise<Extract<SessionOutboundMessage, {
993
+ type: "voice.input.receipts.read.response";
994
+ }>["payload"]>;
995
+ sendVoiceAudioChunk(audio: string, format: string, isLast?: boolean, transport?: VoiceTransport): Promise<void>;
909
996
  startDictationStream(dictationId: string, format: string): Promise<void>;
910
997
  sendDictationStreamChunk(dictationId: string, seq: number, audio: string, format: string): void;
911
998
  finishDictationStream(dictationId: string, finalSeq: number): Promise<{
@@ -913,8 +1000,8 @@ export declare class DaemonClient {
913
1000
  text: string;
914
1001
  }>;
915
1002
  cancelDictationStream(dictationId: string): void;
916
- abortRequest(): Promise<void>;
917
- audioPlayed(id: string): Promise<void>;
1003
+ abortRequest(transport?: VoiceTransport): Promise<void>;
1004
+ audioPlayed(id: string, error?: string, transport?: VoiceTransport): Promise<void>;
918
1005
  getCheckoutStatus(cwd: string, options?: {
919
1006
  requestId?: string;
920
1007
  }): Promise<CheckoutStatusPayload>;
@@ -1770,6 +1770,41 @@ export class DaemonClient {
1770
1770
  throw new Error(payload.error ?? "updateAgent rejected");
1771
1771
  }
1772
1772
  }
1773
+ async updateCompanionEntry(input) {
1774
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1775
+ message: {
1776
+ type: "agent.companion.update_entry.request",
1777
+ agentId: input.agentId,
1778
+ entryId: input.entryId,
1779
+ action: input.action,
1780
+ status: input.status,
1781
+ text: input.text,
1782
+ answerText: input.answerText,
1783
+ sourceId: input.sourceId,
1784
+ },
1785
+ });
1786
+ if (!payload.accepted) {
1787
+ throw new Error(payload.error ?? "updateCompanionEntry rejected");
1788
+ }
1789
+ }
1790
+ /**
1791
+ * Backfills an agent's artifact feed from files already on disk. Needed for
1792
+ * agents whose work predates the artifact feed, whose feeds are otherwise
1793
+ * permanently empty.
1794
+ */
1795
+ async scanAgentArtifacts(agentId, options) {
1796
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1797
+ message: {
1798
+ type: "agent.artifacts.scan.request",
1799
+ agentId,
1800
+ ...(options?.limit !== undefined ? { limit: options.limit } : {}),
1801
+ },
1802
+ });
1803
+ if (!payload.accepted) {
1804
+ throw new Error(payload.error ?? "scanAgentArtifacts rejected");
1805
+ }
1806
+ return { addedOrUpdated: payload.addedOrUpdated, total: payload.total };
1807
+ }
1773
1808
  async renameProject(projectId, customName, requestId) {
1774
1809
  const payload = await this.sendCorrelatedSessionRequest({
1775
1810
  requestId,
@@ -2210,6 +2245,96 @@ export class DaemonClient {
2210
2245
  async sendMessage(agentId, text, options) {
2211
2246
  await this.sendAgentMessage(agentId, text, options);
2212
2247
  }
2248
+ // ==========================================================================
2249
+ // Durable agent message queue — see docs/queue-mirroring.md.
2250
+ // Gated on server_info.features.durableAgentQueueV1; callers must check the
2251
+ // flag before reaching any of these. Mutations are revision-checked: a stale
2252
+ // expectedRevision is rejected with the `queue_revision_conflict` code
2253
+ // instead of overwriting another device's edit.
2254
+ // ==========================================================================
2255
+ /**
2256
+ * Admits a prompt into the durable queue with an explicit delivery intent.
2257
+ * `itemId` comes from the caller so an optimistic local row and the stored
2258
+ * item share an id, which makes a reconnect retry of the same enqueue a
2259
+ * daemon-side no-op instead of a duplicate.
2260
+ */
2261
+ async enqueueAgentMessage(input) {
2262
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2263
+ message: {
2264
+ type: "agent.queue.enqueue.request",
2265
+ agentId: input.agentId,
2266
+ itemId: input.itemId,
2267
+ text: input.text,
2268
+ intent: input.intent,
2269
+ ...(input.images?.length ? { images: input.images } : {}),
2270
+ ...(input.attachments?.length ? { attachments: input.attachments } : {}),
2271
+ ...(input.composerAttachments?.length
2272
+ ? { composerAttachments: input.composerAttachments }
2273
+ : {}),
2274
+ },
2275
+ }));
2276
+ }
2277
+ async updateQueuedAgentMessage(input) {
2278
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2279
+ message: {
2280
+ type: "agent.queue.update.request",
2281
+ agentId: input.agentId,
2282
+ itemId: input.itemId,
2283
+ text: input.text,
2284
+ expectedRevision: input.expectedRevision,
2285
+ ...(input.images?.length ? { images: input.images } : {}),
2286
+ ...(input.attachments?.length ? { attachments: input.attachments } : {}),
2287
+ ...(input.composerAttachments?.length
2288
+ ? { composerAttachments: input.composerAttachments }
2289
+ : {}),
2290
+ },
2291
+ }));
2292
+ }
2293
+ async reorderQueuedAgentMessages(agentId, itemIds, expectedRevision) {
2294
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2295
+ message: { type: "agent.queue.reorder.request", agentId, itemIds, expectedRevision },
2296
+ }));
2297
+ }
2298
+ async deleteQueuedAgentMessage(agentId, itemId, expectedRevision) {
2299
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2300
+ message: { type: "agent.queue.delete.request", agentId, itemId, expectedRevision },
2301
+ }));
2302
+ }
2303
+ async retryQueuedAgentMessage(agentId, itemId, expectedRevision) {
2304
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2305
+ message: { type: "agent.queue.retry.request", agentId, itemId, expectedRevision },
2306
+ }));
2307
+ }
2308
+ async sendQueuedAgentMessageNow(agentId, itemId, expectedRevision) {
2309
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2310
+ message: { type: "agent.queue.send_now.request", agentId, itemId, expectedRevision },
2311
+ }));
2312
+ }
2313
+ async listQueuedAgentMessages(agentId) {
2314
+ return this.requireAgentQueuePayload(await this.sendNamespacedCorrelatedSessionRequest({
2315
+ message: { type: "agent.queue.list.request", agentId },
2316
+ }));
2317
+ }
2318
+ /**
2319
+ * Fetches the image bytes of one queued item. A device that did not queue the
2320
+ * item has no local copy, so pulling it back into the composer would
2321
+ * otherwise drop the images.
2322
+ */
2323
+ async getQueuedAgentMessageImages(agentId, itemId) {
2324
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
2325
+ message: { type: "agent.queue.get_item_images.request", agentId, itemId },
2326
+ });
2327
+ if (payload.error) {
2328
+ throw new Error(payload.error);
2329
+ }
2330
+ return payload.images;
2331
+ }
2332
+ requireAgentQueuePayload(payload) {
2333
+ if (!payload.queue) {
2334
+ throw new Error(payload.error ?? "Agent queue request rejected");
2335
+ }
2336
+ return payload.queue;
2337
+ }
2213
2338
  async rewindAgent(agentId, messageId, mode) {
2214
2339
  const requestId = this.createRequestId();
2215
2340
  const message = SessionInboundMessageSchema.parse({
@@ -2483,12 +2608,14 @@ export class DaemonClient {
2483
2608
  // ============================================================================
2484
2609
  // Audio / Voice
2485
2610
  // ============================================================================
2486
- async setVoiceMode(enabled, agentId) {
2611
+ async setVoiceMode(enabled, agentId, input) {
2487
2612
  const requestId = this.createRequestId();
2488
2613
  const message = SessionInboundMessageSchema.parse({
2489
2614
  type: "set_voice_mode",
2490
2615
  enabled,
2491
2616
  ...(agentId ? { agentId } : {}),
2617
+ ...(input?.attachmentId ? { attachmentId: input.attachmentId } : {}),
2618
+ ...(input?.generation ? { generation: input.generation } : {}),
2492
2619
  requestId,
2493
2620
  });
2494
2621
  const response = await this.sendRequest({
@@ -2512,8 +2639,28 @@ export class DaemonClient {
2512
2639
  }
2513
2640
  return response;
2514
2641
  }
2515
- async sendVoiceAudioChunk(audio, format, isLast = false) {
2516
- this.sendSessionMessage({ type: "voice_audio_chunk", audio, format, isLast });
2642
+ /** Reads this attachment's delivery receipts so the panel can show truthful state. */
2643
+ async readVoiceInputReceipts(input) {
2644
+ const requestId = this.createRequestId();
2645
+ const response = await this.sendRequest({
2646
+ requestId,
2647
+ message: { type: "voice.input.receipts.read.request", requestId, ...input },
2648
+ select: (msg) => msg.type === "voice.input.receipts.read.response" && msg.payload.requestId === requestId
2649
+ ? msg.payload
2650
+ : null,
2651
+ });
2652
+ if (response.error)
2653
+ throw new Error(response.error);
2654
+ return response;
2655
+ }
2656
+ async sendVoiceAudioChunk(audio, format, isLast = false, transport) {
2657
+ this.sendSessionMessage({
2658
+ type: "voice_audio_chunk",
2659
+ audio,
2660
+ format,
2661
+ isLast,
2662
+ ...transport,
2663
+ });
2517
2664
  }
2518
2665
  async startDictationStream(dictationId, format) {
2519
2666
  const ack = this.waitForWithCancel((msg) => {
@@ -2674,11 +2821,16 @@ export class DaemonClient {
2674
2821
  cancelDictationStream(dictationId) {
2675
2822
  this.sendSessionMessageStrict({ type: "dictation_stream_cancel", dictationId });
2676
2823
  }
2677
- async abortRequest() {
2678
- this.sendSessionMessage({ type: "abort_request" });
2824
+ async abortRequest(transport) {
2825
+ this.sendSessionMessage({ type: "abort_request", ...transport });
2679
2826
  }
2680
- async audioPlayed(id) {
2681
- this.sendSessionMessage({ type: "audio_played", id });
2827
+ async audioPlayed(id, error, transport) {
2828
+ this.sendSessionMessageStrict({
2829
+ type: "audio_played",
2830
+ id,
2831
+ ...(error !== undefined ? { error } : {}),
2832
+ ...transport,
2833
+ });
2682
2834
  }
2683
2835
  // ============================================================================
2684
2836
  // Git Operations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camerontaylor/paseo-client",
3
- "version": "0.11.1-fork.1",
3
+ "version": "0.11.2-fork.1",
4
4
  "description": "Paseo client SDK package",
5
5
  "files": [
6
6
  "dist",
@@ -39,8 +39,8 @@
39
39
  "test": "vitest run"
40
40
  },
41
41
  "dependencies": {
42
- "@camerontaylor/paseo-protocol": "0.11.1-fork.1",
43
- "@camerontaylor/paseo-relay": "0.11.1-fork.1",
42
+ "@camerontaylor/paseo-protocol": "0.11.2-fork.1",
43
+ "@camerontaylor/paseo-relay": "0.11.2-fork.1",
44
44
  "zod": "^4.4.3"
45
45
  },
46
46
  "devDependencies": {