@harness-gw/sdk 0.5.1 → 0.6.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.
- package/README.md +2 -2
- package/dist/chunks/index.js +5 -3
- package/dist/client/acp-workspace-client-sessions.d.ts +6 -1
- package/dist/client/index.js +184 -83
- package/dist/client/log.d.ts +11 -0
- package/dist/client/types.d.ts +11 -1
- package/dist/client/workspace.d.ts +9 -0
- package/dist/protocol/acp.d.ts +10 -0
- package/dist/protocol/sdk.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ You need a running harness. Hermes is the primary one; see
|
|
|
63
63
|
docker run --rm \
|
|
64
64
|
-v "$PWD/config.yaml:/run/harness-gw/config.yaml:ro" \
|
|
65
65
|
-v "$PWD/hermes-token:/run/secrets/hermes-token:ro" \
|
|
66
|
-
ghcr.io/almogbaku/harness-gw:0.
|
|
66
|
+
ghcr.io/almogbaku/harness-gw:0.6.1 \
|
|
67
67
|
config check --config /run/harness-gw/config.yaml
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -73,7 +73,7 @@ You need a running harness. Hermes is the primary one; see
|
|
|
73
73
|
docker run --rm -p 127.0.0.1:4100:4100 \
|
|
74
74
|
-v "$PWD/config.yaml:/run/harness-gw/config.yaml:ro" \
|
|
75
75
|
-v "$PWD/hermes-token:/run/secrets/hermes-token:ro" \
|
|
76
|
-
ghcr.io/almogbaku/harness-gw:0.
|
|
76
|
+
ghcr.io/almogbaku/harness-gw:0.6.1 \
|
|
77
77
|
serve --config /run/harness-gw/config.yaml
|
|
78
78
|
```
|
|
79
79
|
|
package/dist/chunks/index.js
CHANGED
|
@@ -208,7 +208,7 @@ var SessionMessagePartSchema = z.discriminatedUnion("type", [
|
|
|
208
208
|
}),
|
|
209
209
|
z.strictObject({
|
|
210
210
|
type: z.literal("image"),
|
|
211
|
-
image: z.string().min(1).max(
|
|
211
|
+
image: z.string().min(1).max(35000000),
|
|
212
212
|
filename: z.string().min(1).max(4096).optional()
|
|
213
213
|
}),
|
|
214
214
|
z.strictObject({
|
|
@@ -727,8 +727,10 @@ var HGW_JSONRPC_ERRORS2 = {
|
|
|
727
727
|
revisionConflict: -31012,
|
|
728
728
|
temporarilyUnavailable: -31013,
|
|
729
729
|
uncertainMutation: -31014,
|
|
730
|
-
unsupported: -31015
|
|
730
|
+
unsupported: -31015,
|
|
731
|
+
requestTooLarge: -31016
|
|
731
732
|
};
|
|
733
|
+
var HGW_MAX_FRAME_BYTES2 = 1100000;
|
|
732
734
|
var IdentifierSchema2 = z2.string().min(1).max(256).refine((value) => [...value].every((character) => {
|
|
733
735
|
const code = character.charCodeAt(0);
|
|
734
736
|
return code >= 32 && code !== 127;
|
|
@@ -1180,4 +1182,4 @@ var MCP_APP_SANDBOX_CSP2 = [
|
|
|
1180
1182
|
"frame-ancestors 'self'"
|
|
1181
1183
|
].join("; ");
|
|
1182
1184
|
|
|
1183
|
-
export { SESSION_CATALOG_MAX_WINDOW2, RuntimeAuthStateSchema2, OperationCapabilitySchema2, RuntimeInfoSchema2, AgentAvatarSchema2, AgentCatalogEntrySchema2, AgentCatalogResponseSchema2, AgentUpdateFields2, writesAgentField2, AgentUpdateRequestSchema2, AgentUpdateResponseSchema2, SessionStatusSchema2, SessionPlatformSchema2, SessionSchema2, newestSessionFirst2, SessionCatalogResponseSchema2, StopReason2, ToolKind2, ToolLocationSchema2, DiffOperation2, DiffChangeSchema2, ToolDiffSchema2, SessionMessageErrorStatusSchema2, SessionMessageSchema2, SessionPlanActivityMessageSchema2, SessionHistoryResponseSchema2, SessionCreateRequestSchema2, SessionCreateResponseSchema2, SessionPatchRequestSchema2, TurnStopResponseSchema2, TurnSteerRequestSchema2, TurnSteerResponseSchema2, SlashCommandSchema2, MAX_SLASH_COMMANDS2, INTERACTION_PROTOCOL2, SessionWorkspaceCapabilitiesResponseSchema2, GuestRuntimeCapabilitiesResponseSchema2, SessionModelsResponseSchema2, SessionModelUpdateRequestSchema2, SessionModelUpdateResponseSchema2, SessionContextResponseSchema2, ArtifactDescriptorSchema2, SessionTodosResponseSchema2, SessionActivityResponseSchema2, SessionAttachmentStageRequestSchema2, SessionAttachmentStageResponseSchema2, SessionAudioResponseSchema2, SessionTranscriptionRequestSchema2, SessionTranscriptionResponseSchema2, SessionSpeechRequestSchema2, ErrorResponseSchema2, ACP_PROTOCOL_VERSION2, HGW_API_PREFIX2, HGW_ACP_PATH2, HGW_ACP_AGENTS_PATH2, hgwAcpAgentPath2, HGW_META_KEY2, HGW_EXTENSION_VERSION2, HGW_AUTH_METHOD_INVITE2, HGW_ATTACHMENT_URI_SCHEME2, HGW_ARTIFACT_URI_SCHEME2, HGW_METHODS2, HGW_STOP_REASONS2, HGW_PERMISSION_KIND_SESSION2, HGW_PLAN_ID2, HGW_JSONRPC_ERRORS2, IdentifierSchema2, HgwExtensionsSchema2, HgwClientCapabilitiesMetaSchema2, HgwInitializeMetaSchema2, HgwLoginMetaSchema2, HgwSessionNewMetaSchema2, HgwSessionListMetaSchema2, HgwSessionSearchMetaSchema2, HgwSessionSearchResponseSchema2, HgwSessionInfoMetaSchema2, HgwSessionResumeMetaSchema2, HGW_REPLAY_BEFORE2, HgwReplayBeforeSchema2, HgwHistoryCursorSchema2, HgwHistoryPageResponseMetaSchema2, HgwHistoryPageTagSchema2, HgwSessionResumeResponseMetaSchema2, HgwPromptMetaSchema2, HgwSessionUpdateRequestSchema2, HgwSessionPartRequestSchema2, HgwSteerRequestSchema2, HgwSteerResponseSchema2, HgwFocusRequestSchema2, HgwAgentsListResponseSchema2, HgwAgentUpdateRequestSchema2, HgwAgentUpdateResponseSchema2, HgwTurnMetaSchema2, HgwNoticeMetaSchema2, HgwMessageMetaSchema2, HgwCostSchema2, HGW_SUBAGENT_STATUSES2, HgwSubagentSchema2, HgwStateMetaSchema2, HgwChunkMetaSchema2, HgwToolCallMetaSchema2, HgwPlanMetaSchema2, HgwUsageMetaSchema2, HgwAvailableCommandsMetaSchema2, HgwPermissionMetaSchema2, HgwQuestionOptionSchema2, HgwQuestionSchema2, HgwElicitationMetaSchema2, HgwArtifactDescriptorSchema2, formatArtifactUri2, parseArtifactUri2, HgwComposerPrefillNotificationSchema2, HgwErrorNotificationSchema2, HGW_REQUEST_TEXT_MAX2, HgwActivityNotificationSchema2, PushCategorySchema2, categoryOf2, PushLocaleSchema2, PRESENCE_IDLE_MS2, PRESENCE_HEARTBEAT_MS2, PRESENCE_GRACE_MS2, PRESENCE_CLOSED_GRACE_MS2, COALESCE_WINDOW_MS2, PUSH_TEXT_LIMITS2, PushMessageSchema2, PushCategoriesSchema2, PushSubscriptionJsonSchema2, PushInfoSchema2, PushRegistrationSchema2, PushUnregistrationSchema2, CallToolResultSchema2, ReadResourceResultSchema2, McpUiCspSchema2, isMcpAppCspDomain2, McpUiPermissionsSchema2, McpAppFilesSchema2, McpAppViewSchema2, viewerFileResult2, McpAppToolCallRequestSchema2, McpAppResourceReadRequestSchema2, MCP_APP_SANDBOX_PATH2, MCP_APP_SANDBOX_CSP2 };
|
|
1185
|
+
export { SESSION_CATALOG_MAX_WINDOW2, RuntimeAuthStateSchema2, OperationCapabilitySchema2, RuntimeInfoSchema2, AgentAvatarSchema2, AgentCatalogEntrySchema2, AgentCatalogResponseSchema2, AgentUpdateFields2, writesAgentField2, AgentUpdateRequestSchema2, AgentUpdateResponseSchema2, SessionStatusSchema2, SessionPlatformSchema2, SessionSchema2, newestSessionFirst2, SessionCatalogResponseSchema2, StopReason2, ToolKind2, ToolLocationSchema2, DiffOperation2, DiffChangeSchema2, ToolDiffSchema2, SessionMessageErrorStatusSchema2, SessionMessageSchema2, SessionPlanActivityMessageSchema2, SessionHistoryResponseSchema2, SessionCreateRequestSchema2, SessionCreateResponseSchema2, SessionPatchRequestSchema2, TurnStopResponseSchema2, TurnSteerRequestSchema2, TurnSteerResponseSchema2, SlashCommandSchema2, MAX_SLASH_COMMANDS2, INTERACTION_PROTOCOL2, SessionWorkspaceCapabilitiesResponseSchema2, GuestRuntimeCapabilitiesResponseSchema2, SessionModelsResponseSchema2, SessionModelUpdateRequestSchema2, SessionModelUpdateResponseSchema2, SessionContextResponseSchema2, ArtifactDescriptorSchema2, SessionTodosResponseSchema2, SessionActivityResponseSchema2, SessionAttachmentStageRequestSchema2, SessionAttachmentStageResponseSchema2, SessionAudioResponseSchema2, SessionTranscriptionRequestSchema2, SessionTranscriptionResponseSchema2, SessionSpeechRequestSchema2, ErrorResponseSchema2, ACP_PROTOCOL_VERSION2, HGW_API_PREFIX2, HGW_ACP_PATH2, HGW_ACP_AGENTS_PATH2, hgwAcpAgentPath2, HGW_META_KEY2, HGW_EXTENSION_VERSION2, HGW_AUTH_METHOD_INVITE2, HGW_ATTACHMENT_URI_SCHEME2, HGW_ARTIFACT_URI_SCHEME2, HGW_METHODS2, HGW_STOP_REASONS2, HGW_PERMISSION_KIND_SESSION2, HGW_PLAN_ID2, HGW_JSONRPC_ERRORS2, HGW_MAX_FRAME_BYTES2, IdentifierSchema2, HgwExtensionsSchema2, HgwClientCapabilitiesMetaSchema2, HgwInitializeMetaSchema2, HgwLoginMetaSchema2, HgwSessionNewMetaSchema2, HgwSessionListMetaSchema2, HgwSessionSearchMetaSchema2, HgwSessionSearchResponseSchema2, HgwSessionInfoMetaSchema2, HgwSessionResumeMetaSchema2, HGW_REPLAY_BEFORE2, HgwReplayBeforeSchema2, HgwHistoryCursorSchema2, HgwHistoryPageResponseMetaSchema2, HgwHistoryPageTagSchema2, HgwSessionResumeResponseMetaSchema2, HgwPromptMetaSchema2, HgwSessionUpdateRequestSchema2, HgwSessionPartRequestSchema2, HgwSteerRequestSchema2, HgwSteerResponseSchema2, HgwFocusRequestSchema2, HgwAgentsListResponseSchema2, HgwAgentUpdateRequestSchema2, HgwAgentUpdateResponseSchema2, HgwTurnMetaSchema2, HgwNoticeMetaSchema2, HgwMessageMetaSchema2, HgwCostSchema2, HGW_SUBAGENT_STATUSES2, HgwSubagentSchema2, HgwStateMetaSchema2, HgwChunkMetaSchema2, HgwToolCallMetaSchema2, HgwPlanMetaSchema2, HgwUsageMetaSchema2, HgwAvailableCommandsMetaSchema2, HgwPermissionMetaSchema2, HgwQuestionOptionSchema2, HgwQuestionSchema2, HgwElicitationMetaSchema2, HgwArtifactDescriptorSchema2, formatArtifactUri2, parseArtifactUri2, HgwComposerPrefillNotificationSchema2, HgwErrorNotificationSchema2, HGW_REQUEST_TEXT_MAX2, HgwActivityNotificationSchema2, PushCategorySchema2, categoryOf2, PushLocaleSchema2, PRESENCE_IDLE_MS2, PRESENCE_HEARTBEAT_MS2, PRESENCE_GRACE_MS2, PRESENCE_CLOSED_GRACE_MS2, COALESCE_WINDOW_MS2, PUSH_TEXT_LIMITS2, PushMessageSchema2, PushCategoriesSchema2, PushSubscriptionJsonSchema2, PushInfoSchema2, PushRegistrationSchema2, PushUnregistrationSchema2, CallToolResultSchema2, ReadResourceResultSchema2, McpUiCspSchema2, isMcpAppCspDomain2, McpUiPermissionsSchema2, McpAppFilesSchema2, McpAppViewSchema2, viewerFileResult2, McpAppToolCallRequestSchema2, McpAppResourceReadRequestSchema2, MCP_APP_SANDBOX_PATH2, MCP_APP_SANDBOX_CSP2 };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type SessionInfo } from "@agentclientprotocol/sdk/experimental/v2";
|
|
2
2
|
import { type HgwSessionInfoMeta } from "../protocol/acp.js";
|
|
3
3
|
import type { SessionMetadata, SessionStatus, TodoItem, WorkspaceActivityEvent } from "./workspace.js";
|
|
4
|
+
import type { Logger } from "../lifecycle/index.js";
|
|
4
5
|
import type { AcpConnection } from "./types.js";
|
|
5
6
|
/**
|
|
6
7
|
* Everything the workspace learns by subscribing to the connection: the Session row
|
|
@@ -13,8 +14,10 @@ export type AcpSessionStoreOptions = {
|
|
|
13
14
|
now?: () => number;
|
|
14
15
|
/** A live turn of a subscribed Session just stopped, however it ended. */
|
|
15
16
|
onTurnFinished?: (sessionId: string) => void;
|
|
17
|
+
/** Where a listener that throws is told; the others still hear. */
|
|
18
|
+
logger?: Logger;
|
|
16
19
|
};
|
|
17
|
-
export declare function createAcpSessionStore({ connection, now, onTurnFinished, }: AcpSessionStoreOptions): {
|
|
20
|
+
export declare function createAcpSessionStore({ connection, now, onTurnFinished, logger, }: AcpSessionStoreOptions): {
|
|
18
21
|
subscribe: (sessionId: string, agentId?: string) => () => void;
|
|
19
22
|
dispose(): void;
|
|
20
23
|
/**
|
|
@@ -36,6 +39,8 @@ export declare function createAcpSessionStore({ connection, now, onTurnFinished,
|
|
|
36
39
|
createdAt?: string;
|
|
37
40
|
platform?: import("./workspace.js").SessionPlatform;
|
|
38
41
|
}[];
|
|
42
|
+
/** Marks Sessions a read has answered for, so a missing one gates no snapshot. */
|
|
43
|
+
answer(sessionIds: readonly string[]): void;
|
|
39
44
|
/** The provider's title, as a list page or a subscribed Session reports it. */
|
|
40
45
|
setTitle: (sessionId: string, title: string) => Map<string, string>;
|
|
41
46
|
/** The proxy's read state, or the operator's own optimistic ack. */
|
package/dist/client/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
HGW_STOP_REASONS2,
|
|
15
15
|
HGW_PERMISSION_KIND_SESSION2,
|
|
16
16
|
HGW_JSONRPC_ERRORS2,
|
|
17
|
+
HGW_MAX_FRAME_BYTES2,
|
|
17
18
|
HgwInitializeMetaSchema2,
|
|
18
19
|
HgwSessionSearchMetaSchema2,
|
|
19
20
|
HgwSessionSearchResponseSchema2,
|
|
@@ -277,6 +278,13 @@ class AgentUpdateError extends Error {
|
|
|
277
278
|
}
|
|
278
279
|
}
|
|
279
280
|
|
|
281
|
+
class AcpConnectionClosedError extends Error {
|
|
282
|
+
constructor(message = "The ACP connection closed", options) {
|
|
283
|
+
super(message, options);
|
|
284
|
+
this.name = "AcpConnectionClosedError";
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
280
288
|
// client/limits.ts
|
|
281
289
|
var HANDSHAKE_DEADLINE_MS = 1e4;
|
|
282
290
|
var REQUEST_DEADLINE_MS = {
|
|
@@ -370,6 +378,21 @@ function loggedStream(stream, logger) {
|
|
|
370
378
|
})
|
|
371
379
|
};
|
|
372
380
|
}
|
|
381
|
+
var LOGGED_ID_LENGTH = 256;
|
|
382
|
+
function loggedId(row, ...path) {
|
|
383
|
+
let value = row;
|
|
384
|
+
for (const key of path)
|
|
385
|
+
value = typeof value === "object" && value !== null ? value[key] : undefined;
|
|
386
|
+
return typeof value === "string" && value.length > 0 ? value.slice(0, LOGGED_ID_LENGTH) : undefined;
|
|
387
|
+
}
|
|
388
|
+
function callEach(listeners, logger, event, ...args) {
|
|
389
|
+
for (const listener of [...listeners])
|
|
390
|
+
try {
|
|
391
|
+
listener(...args);
|
|
392
|
+
} catch (err) {
|
|
393
|
+
logger.warn({ err }, event);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
373
396
|
|
|
374
397
|
// client/connection.ts
|
|
375
398
|
var TRY_AGAIN_LATER = 1013;
|
|
@@ -420,9 +443,6 @@ var SESSION_STATES = new Map([
|
|
|
420
443
|
["refused", "unavailable"],
|
|
421
444
|
["gone", "gone"]
|
|
422
445
|
]);
|
|
423
|
-
function isTimeout(error) {
|
|
424
|
-
return error instanceof DOMException && error.name === "TimeoutError";
|
|
425
|
-
}
|
|
426
446
|
function agentUpdateError(error) {
|
|
427
447
|
if (codeOf(error) === HGW_JSONRPC_ERRORS2.unsupported)
|
|
428
448
|
return new AgentUpdateError("unsupported", "This runtime cannot store that Agent field");
|
|
@@ -466,6 +486,9 @@ function trackedInbound(stream, onReceived) {
|
|
|
466
486
|
writable: stream.writable
|
|
467
487
|
};
|
|
468
488
|
}
|
|
489
|
+
function closedUnder({ connection }, error) {
|
|
490
|
+
return connection.signal.aborted && error === connection.signal.reason;
|
|
491
|
+
}
|
|
469
492
|
function observedSocket(Socket, onOpen, onClose) {
|
|
470
493
|
return class extends Socket {
|
|
471
494
|
constructor(...args) {
|
|
@@ -637,6 +660,35 @@ function sessionMachine({
|
|
|
637
660
|
}
|
|
638
661
|
});
|
|
639
662
|
}
|
|
663
|
+
function readEach(entries, schema, skipped) {
|
|
664
|
+
const kept = [];
|
|
665
|
+
let unreadable;
|
|
666
|
+
for (const entry of entries) {
|
|
667
|
+
const read = schema.safeParse(entry);
|
|
668
|
+
if (read.success)
|
|
669
|
+
kept.push(read.data);
|
|
670
|
+
else {
|
|
671
|
+
unreadable = read.error;
|
|
672
|
+
skipped(entry);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
if (entries.length > 0 && kept.length === 0)
|
|
676
|
+
throw unreadable;
|
|
677
|
+
return kept;
|
|
678
|
+
}
|
|
679
|
+
var AgentsListEntriesSchema = HgwAgentsListResponseSchema2.extend({
|
|
680
|
+
agents: z.array(z.unknown()).max(1000)
|
|
681
|
+
});
|
|
682
|
+
var SessionSearchEntriesSchema = HgwSessionSearchResponseSchema2.extend({
|
|
683
|
+
sessions: z.array(z.unknown())
|
|
684
|
+
});
|
|
685
|
+
var FRAME_ENVELOPE_BYTES = 1024;
|
|
686
|
+
var frameEncoder = new TextEncoder;
|
|
687
|
+
function assertFrameFits(params) {
|
|
688
|
+
const bytes = frameEncoder.encode(JSON.stringify(params)).byteLength;
|
|
689
|
+
if (bytes > HGW_MAX_FRAME_BYTES2 - FRAME_ENVELOPE_BYTES)
|
|
690
|
+
throw new RequestError(HGW_JSONRPC_ERRORS2.requestTooLarge, "Request too large to send");
|
|
691
|
+
}
|
|
640
692
|
function createAcpConnection(options) {
|
|
641
693
|
const {
|
|
642
694
|
clientInfo,
|
|
@@ -660,6 +712,7 @@ function createAcpConnection(options) {
|
|
|
660
712
|
let live;
|
|
661
713
|
let recovering = false;
|
|
662
714
|
let joinable = false;
|
|
715
|
+
let recovery;
|
|
663
716
|
let invitation;
|
|
664
717
|
let lastFocus;
|
|
665
718
|
let silenceTimer = undefined;
|
|
@@ -674,23 +727,13 @@ function createAcpConnection(options) {
|
|
|
674
727
|
if (status === next)
|
|
675
728
|
return;
|
|
676
729
|
status = next;
|
|
677
|
-
|
|
678
|
-
listener(next);
|
|
730
|
+
callEach(statusListeners, logger, "acp.listener.failed", next);
|
|
679
731
|
}
|
|
680
732
|
function setOutage(next) {
|
|
681
733
|
if (outage === next)
|
|
682
734
|
return;
|
|
683
735
|
outage = next;
|
|
684
|
-
|
|
685
|
-
listener(next);
|
|
686
|
-
}
|
|
687
|
-
function settleOutage() {
|
|
688
|
-
if (status !== "ready")
|
|
689
|
-
return;
|
|
690
|
-
for (const open of sessions.values())
|
|
691
|
-
if (open.state === "joining")
|
|
692
|
-
return;
|
|
693
|
-
setOutage(undefined);
|
|
736
|
+
callEach(outageListeners, logger, "acp.listener.failed", next);
|
|
694
737
|
}
|
|
695
738
|
function emitPending(request) {
|
|
696
739
|
for (const listener of pendingListeners)
|
|
@@ -708,7 +751,9 @@ function createAcpConnection(options) {
|
|
|
708
751
|
sendLivenessProbeAsync();
|
|
709
752
|
}, LIVENESS_SILENCE_MS);
|
|
710
753
|
}
|
|
754
|
+
let lastInboundAt = Number.NEGATIVE_INFINITY;
|
|
711
755
|
function onInbound() {
|
|
756
|
+
lastInboundAt = clock.now();
|
|
712
757
|
armSilenceTimer();
|
|
713
758
|
}
|
|
714
759
|
function sendLivenessProbeAsync() {
|
|
@@ -766,14 +811,13 @@ function createAcpConnection(options) {
|
|
|
766
811
|
if (open.replaying)
|
|
767
812
|
open.replaying.delivered = true;
|
|
768
813
|
for (const { listener } of open.listeners)
|
|
769
|
-
listener.update
|
|
814
|
+
callEach(listener.update ? [listener.update] : [], logger, "acp.listener.failed", params.update, meta);
|
|
770
815
|
}).onRequest(methods2.client.session.requestPermission, ({ params, signal }) => permissionRequest(params, signal)).onRequest(methods2.client.elicitation.create, ({ params, signal }) => elicitationRequest(params, signal));
|
|
771
816
|
for (const [method, parser] of Object.entries(NOTIFICATION_PARSERS))
|
|
772
817
|
app.onNotification(method, parser, ({ params }) => {
|
|
773
818
|
if (method === HGW_METHODS2.notify.error)
|
|
774
819
|
noticeGone(params);
|
|
775
|
-
|
|
776
|
-
listener(params);
|
|
820
|
+
callEach(notificationListeners.get(method) ?? [], logger, "acp.listener.failed", params);
|
|
777
821
|
});
|
|
778
822
|
function noticeGone(params) {
|
|
779
823
|
const notice = HgwErrorNotificationSchema2.safeParse(params).data;
|
|
@@ -781,48 +825,64 @@ function createAcpConnection(options) {
|
|
|
781
825
|
return;
|
|
782
826
|
sessions.get(notice.sessionId)?.owner?.actor.send({ type: "gone" });
|
|
783
827
|
}
|
|
784
|
-
async function
|
|
828
|
+
async function liveTransport() {
|
|
785
829
|
start();
|
|
786
830
|
if (inspecting)
|
|
787
831
|
await inspecting;
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
832
|
+
if (ended || !live)
|
|
833
|
+
throw new AcpConnectionClosedError("The ACP connection is not open");
|
|
834
|
+
return live;
|
|
835
|
+
}
|
|
836
|
+
async function readyTransport() {
|
|
837
|
+
const current = await liveTransport();
|
|
791
838
|
await current.ready;
|
|
792
839
|
return current;
|
|
793
840
|
}
|
|
794
|
-
|
|
795
|
-
|
|
841
|
+
function recovered() {
|
|
842
|
+
start();
|
|
843
|
+
if (ended)
|
|
844
|
+
return Promise.reject(new AcpConnectionClosedError);
|
|
845
|
+
if (joinable)
|
|
846
|
+
return Promise.resolve();
|
|
847
|
+
recovery ??= Promise.withResolvers();
|
|
848
|
+
return recovery.promise;
|
|
849
|
+
}
|
|
850
|
+
async function request(tier, send, resend) {
|
|
851
|
+
const sessionId = resend === "read" ? undefined : resend?.sessionId;
|
|
852
|
+
for (;; ) {
|
|
853
|
+
if (sessionId !== undefined && sessions.has(sessionId))
|
|
854
|
+
await joined(sessionId);
|
|
855
|
+
else if (resend)
|
|
856
|
+
await recovered();
|
|
857
|
+
const transport = await liveTransport();
|
|
858
|
+
try {
|
|
859
|
+
await transport.ready;
|
|
860
|
+
return await requestOn(transport, tier, send);
|
|
861
|
+
} catch (error) {
|
|
862
|
+
if (!closedUnder(transport, error))
|
|
863
|
+
throw error;
|
|
864
|
+
const again = resend === "read" || sessionId !== undefined && sessions.has(sessionId);
|
|
865
|
+
if (!again)
|
|
866
|
+
throw new AcpConnectionClosedError(undefined, { cause: error });
|
|
867
|
+
await transport.connection.closed.catch((err) => logger.warn({ err }, "acp.connection.closed_with_error"));
|
|
868
|
+
}
|
|
869
|
+
}
|
|
796
870
|
}
|
|
797
871
|
async function requestOn({ connection }, tier, send, parent) {
|
|
798
872
|
const deadline = new Deadline(REQUEST_DEADLINE_MS[tier], clock, parent);
|
|
873
|
+
const sentAt = clock.now();
|
|
799
874
|
try {
|
|
800
875
|
return await deadline.run((cancellationSignal) => send(connection.agent, { cancellationSignal }));
|
|
801
876
|
} catch (error) {
|
|
802
877
|
if (deadline.signal.aborted && !parent?.aborted) {
|
|
803
|
-
if (tier
|
|
804
|
-
connection.close(error);
|
|
805
|
-
else
|
|
878
|
+
if (tier !== "probe")
|
|
806
879
|
sendLivenessProbeAsync();
|
|
880
|
+
else if (lastInboundAt <= sentAt)
|
|
881
|
+
connection.close(error);
|
|
807
882
|
}
|
|
808
883
|
throw error;
|
|
809
884
|
}
|
|
810
885
|
}
|
|
811
|
-
async function write(sessionId, tier, send) {
|
|
812
|
-
for (;; ) {
|
|
813
|
-
if (sessions.has(sessionId))
|
|
814
|
-
await joined(sessionId);
|
|
815
|
-
const transport = await readyTransport();
|
|
816
|
-
try {
|
|
817
|
-
return await requestOn(transport, tier, send);
|
|
818
|
-
} catch (error) {
|
|
819
|
-
const closedUnder = transport.connection.signal.aborted && !isTimeout(error) && sessions.has(sessionId);
|
|
820
|
-
if (!closedUnder)
|
|
821
|
-
throw error;
|
|
822
|
-
await transport.connection.closed.catch((err) => logger.warn({ err }, "acp.connection.closed_with_error"));
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
886
|
function notifyAgent(send, sessionId) {
|
|
827
887
|
(async () => {
|
|
828
888
|
if (sessionId !== undefined && sessions.has(sessionId))
|
|
@@ -921,7 +981,11 @@ function createAcpConnection(options) {
|
|
|
921
981
|
}
|
|
922
982
|
}
|
|
923
983
|
async function listAgents() {
|
|
924
|
-
|
|
984
|
+
const response = AgentsListEntriesSchema.parse(await request("short", (agent, options) => agent.request(HGW_METHODS2.agents.list, undefined, options), "read"));
|
|
985
|
+
return {
|
|
986
|
+
...response,
|
|
987
|
+
agents: readEach(response.agents, HgwAgentsListResponseSchema2.shape.agents.element, (entry) => logger.warn({ id: loggedId(entry, "summary", "id") }, "agents.entry_skipped"))
|
|
988
|
+
};
|
|
925
989
|
}
|
|
926
990
|
function settleOf({ listener }) {
|
|
927
991
|
const settle = listener.replay?.();
|
|
@@ -976,8 +1040,7 @@ function createAcpConnection(options) {
|
|
|
976
1040
|
if (next === "joined" || failure !== undefined)
|
|
977
1041
|
open.waiters = undefined;
|
|
978
1042
|
for (const { listener } of open.listeners)
|
|
979
|
-
listener.state
|
|
980
|
-
settleOutage();
|
|
1043
|
+
callEach(listener.state ? [listener.state] : [], logger, "acp.listener.failed", next);
|
|
981
1044
|
}
|
|
982
1045
|
function subscribe(sessionId, listener) {
|
|
983
1046
|
if (ended)
|
|
@@ -1028,7 +1091,6 @@ function createAcpConnection(options) {
|
|
|
1028
1091
|
open.owner?.dispose();
|
|
1029
1092
|
open.waiters?.reject(notOpen());
|
|
1030
1093
|
open.waiters = undefined;
|
|
1031
|
-
settleOutage();
|
|
1032
1094
|
if (open.state === "gone")
|
|
1033
1095
|
return;
|
|
1034
1096
|
request("short", (agent, options) => agent.request(HGW_METHODS2.session.part, { sessionId }, options)).catch((err) => {
|
|
@@ -1036,18 +1098,20 @@ function createAcpConnection(options) {
|
|
|
1036
1098
|
});
|
|
1037
1099
|
}
|
|
1038
1100
|
async function resumePage(sessionId, cursor) {
|
|
1039
|
-
await joined(sessionId);
|
|
1040
1101
|
const open = sessions.get(sessionId);
|
|
1041
1102
|
if (!open)
|
|
1042
1103
|
throw notOpen();
|
|
1043
|
-
|
|
1044
|
-
open.page = updates;
|
|
1104
|
+
let updates = [];
|
|
1045
1105
|
try {
|
|
1046
|
-
const response = await request("medium", (agent, options) =>
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1106
|
+
const response = await request("medium", (agent, options) => {
|
|
1107
|
+
updates = [];
|
|
1108
|
+
open.page = updates;
|
|
1109
|
+
return agent.request(methods2.agent.session.resume, {
|
|
1110
|
+
sessionId,
|
|
1111
|
+
cwd: AGENT_CWD,
|
|
1112
|
+
replayFrom: { type: HGW_REPLAY_BEFORE2, cursor }
|
|
1113
|
+
}, options);
|
|
1114
|
+
}, { sessionId });
|
|
1051
1115
|
const { history } = HgwHistoryPageResponseMetaSchema2.parse(hgwMetaOf(response._meta));
|
|
1052
1116
|
return { updates, history };
|
|
1053
1117
|
} finally {
|
|
@@ -1063,6 +1127,9 @@ function createAcpConnection(options) {
|
|
|
1063
1127
|
sendLivenessProbeAsync();
|
|
1064
1128
|
}
|
|
1065
1129
|
joinable = true;
|
|
1130
|
+
setOutage(undefined);
|
|
1131
|
+
recovery?.resolve();
|
|
1132
|
+
recovery = undefined;
|
|
1066
1133
|
const opened = [...sessions.keys()];
|
|
1067
1134
|
for (const open of sessions.values())
|
|
1068
1135
|
open.owner?.actor.send({ type: "ready" });
|
|
@@ -1102,7 +1169,6 @@ function createAcpConnection(options) {
|
|
|
1102
1169
|
closeTransport: () => live?.connection.close(),
|
|
1103
1170
|
markReady() {
|
|
1104
1171
|
setStatus("ready");
|
|
1105
|
-
settleOutage();
|
|
1106
1172
|
},
|
|
1107
1173
|
lose(next) {
|
|
1108
1174
|
recovering = true;
|
|
@@ -1165,13 +1231,15 @@ function createAcpConnection(options) {
|
|
|
1165
1231
|
ended = true;
|
|
1166
1232
|
setStatus("closed");
|
|
1167
1233
|
setOutage(undefined);
|
|
1168
|
-
failInitialized?.(new
|
|
1234
|
+
failInitialized?.(new AcpConnectionClosedError);
|
|
1169
1235
|
failInitialized = undefined;
|
|
1170
1236
|
settleInitialized = undefined;
|
|
1237
|
+
recovery?.reject(new AcpConnectionClosedError);
|
|
1238
|
+
recovery = undefined;
|
|
1171
1239
|
for (const open of sessions.values()) {
|
|
1172
1240
|
clock.clearTimeout(open.grace);
|
|
1173
1241
|
open.owner?.dispose();
|
|
1174
|
-
open.waiters?.reject(new
|
|
1242
|
+
open.waiters?.reject(new AcpConnectionClosedError);
|
|
1175
1243
|
}
|
|
1176
1244
|
sessions.clear();
|
|
1177
1245
|
live?.connection.close();
|
|
@@ -1208,16 +1276,22 @@ function createAcpConnection(options) {
|
|
|
1208
1276
|
const response = await request("short", (agent, options) => agent.request(methods2.agent.session.list, {
|
|
1209
1277
|
...cursor === undefined ? {} : { cursor },
|
|
1210
1278
|
_meta: { [HGW_META_KEY2]: meta }
|
|
1211
|
-
}, options));
|
|
1279
|
+
}, options), "read");
|
|
1212
1280
|
return {
|
|
1213
1281
|
sessions: response.sessions,
|
|
1214
1282
|
...response.nextCursor ? { nextCursor: response.nextCursor } : {}
|
|
1215
1283
|
};
|
|
1216
1284
|
},
|
|
1217
1285
|
async searchSessions(meta) {
|
|
1218
|
-
|
|
1219
|
-
_meta: {
|
|
1220
|
-
|
|
1286
|
+
const response = SessionSearchEntriesSchema.parse(await request("short", (agent, options) => agent.request(HGW_METHODS2.sessions.search, {
|
|
1287
|
+
_meta: {
|
|
1288
|
+
[HGW_META_KEY2]: HgwSessionSearchMetaSchema2.parse(meta)
|
|
1289
|
+
}
|
|
1290
|
+
}, options), "read"));
|
|
1291
|
+
return {
|
|
1292
|
+
...response,
|
|
1293
|
+
sessions: readEach(response.sessions, HgwSessionSearchResponseSchema2.shape.sessions.element, (entry) => logger.warn({ id: loggedId(entry, "sessionId") }, "sessions.result_skipped"))
|
|
1294
|
+
};
|
|
1221
1295
|
},
|
|
1222
1296
|
subscribe,
|
|
1223
1297
|
joined,
|
|
@@ -1226,14 +1300,20 @@ function createAcpConnection(options) {
|
|
|
1226
1300
|
resumePage,
|
|
1227
1301
|
history: (sessionId) => sessions.get(sessionId)?.history,
|
|
1228
1302
|
async prompt(sessionId, blocks, meta) {
|
|
1229
|
-
const
|
|
1303
|
+
const params = {
|
|
1304
|
+
sessionId,
|
|
1305
|
+
prompt: blocks,
|
|
1306
|
+
_meta: { [HGW_META_KEY2]: meta }
|
|
1307
|
+
};
|
|
1308
|
+
assertFrameFits(params);
|
|
1309
|
+
const response = await request("long", (agent, options) => agent.request(methods2.agent.session.prompt, params, options), { sessionId });
|
|
1230
1310
|
return { messageId: response.messageId };
|
|
1231
1311
|
},
|
|
1232
1312
|
cancel(sessionId) {
|
|
1233
1313
|
notifyAgent((agent) => agent.notify(methods2.agent.session.cancel, { sessionId }), sessionId);
|
|
1234
1314
|
},
|
|
1235
1315
|
async setConfigOption(sessionId, configId, value) {
|
|
1236
|
-
const response = await
|
|
1316
|
+
const response = await request("medium", (agent, options) => agent.request(methods2.agent.session.setConfigOption, { sessionId, configId, type: "id", value }, options), { sessionId });
|
|
1237
1317
|
return response.configOptions;
|
|
1238
1318
|
},
|
|
1239
1319
|
async deleteSession(sessionId) {
|
|
@@ -1243,7 +1323,8 @@ function createAcpConnection(options) {
|
|
|
1243
1323
|
await request("short", (agent, options) => agent.request(HGW_METHODS2.session.update, update, options));
|
|
1244
1324
|
},
|
|
1245
1325
|
async steer(steer) {
|
|
1246
|
-
|
|
1326
|
+
assertFrameFits(steer);
|
|
1327
|
+
return HgwSteerResponseSchema2.parse(await request("medium", (agent, options) => agent.request(HGW_METHODS2.session.steer, steer, options), { sessionId: steer.sessionId }));
|
|
1247
1328
|
},
|
|
1248
1329
|
focus(sessionId, presence) {
|
|
1249
1330
|
const report = {
|
|
@@ -1558,7 +1639,8 @@ function sameRow(left, right) {
|
|
|
1558
1639
|
function createAcpSessionStore({
|
|
1559
1640
|
connection,
|
|
1560
1641
|
now = Date.now,
|
|
1561
|
-
onTurnFinished
|
|
1642
|
+
onTurnFinished,
|
|
1643
|
+
logger = SILENT_LOGGER
|
|
1562
1644
|
}) {
|
|
1563
1645
|
const rows = new Map;
|
|
1564
1646
|
const titles = new Map;
|
|
@@ -1577,11 +1659,12 @@ function createAcpSessionStore({
|
|
|
1577
1659
|
return row ? [{ ...row }] : [];
|
|
1578
1660
|
});
|
|
1579
1661
|
}
|
|
1662
|
+
const answered = new Set;
|
|
1580
1663
|
function notify(subscription) {
|
|
1581
1664
|
for (const sessionId of subscription.sessionIds)
|
|
1582
|
-
if (!rows.has(sessionId))
|
|
1665
|
+
if (!rows.has(sessionId) && !answered.has(sessionId))
|
|
1583
1666
|
return;
|
|
1584
|
-
subscription.listener
|
|
1667
|
+
callEach([subscription.listener], logger, "sessions.listener.failed", rowsFor(subscription.sessionIds));
|
|
1585
1668
|
}
|
|
1586
1669
|
function publish(sessionId) {
|
|
1587
1670
|
for (const subscription of subscriptions)
|
|
@@ -1623,15 +1706,13 @@ function createAcpSessionStore({
|
|
|
1623
1706
|
function setTodos(sessionId, next) {
|
|
1624
1707
|
todos.set(sessionId, next);
|
|
1625
1708
|
for (const listener of todoListeners.get(sessionId) ?? [])
|
|
1626
|
-
listener
|
|
1709
|
+
callEach([listener], logger, "sessions.listener.failed", next.map((todo) => ({ ...todo })));
|
|
1627
1710
|
}
|
|
1628
1711
|
function emitActivity(event) {
|
|
1629
|
-
|
|
1630
|
-
listener(event);
|
|
1712
|
+
callEach(activityListeners, logger, "sessions.listener.failed", event);
|
|
1631
1713
|
}
|
|
1632
1714
|
function invalidate(sessionId) {
|
|
1633
|
-
|
|
1634
|
-
listener();
|
|
1715
|
+
callEach(invalidationListeners.get(sessionId) ?? [], logger, "sessions.listener.failed");
|
|
1635
1716
|
}
|
|
1636
1717
|
function acceptUpdate(sessionId, update, meta) {
|
|
1637
1718
|
if (SessionUpdate2.isStateUpdate(update)) {
|
|
@@ -1726,6 +1807,13 @@ function createAcpSessionStore({
|
|
|
1726
1807
|
},
|
|
1727
1808
|
put,
|
|
1728
1809
|
rowsFor,
|
|
1810
|
+
answer(sessionIds) {
|
|
1811
|
+
for (const sessionId of sessionIds)
|
|
1812
|
+
answered.add(sessionId);
|
|
1813
|
+
for (const subscription of subscriptions)
|
|
1814
|
+
if (sessionIds.some((id) => subscription.sessionIds.has(id)))
|
|
1815
|
+
notify(subscription);
|
|
1816
|
+
},
|
|
1729
1817
|
setTitle: (sessionId, title) => titles.set(sessionId, title),
|
|
1730
1818
|
setUnread: (sessionId, unread) => patch(sessionId, { unread }),
|
|
1731
1819
|
setPinned: (sessionId, pinned) => patch(sessionId, { pinned }),
|
|
@@ -1807,6 +1895,7 @@ function createAcpWorkspaceClient({
|
|
|
1807
1895
|
}) {
|
|
1808
1896
|
const store = createAcpSessionStore({
|
|
1809
1897
|
connection,
|
|
1898
|
+
logger: clientLog,
|
|
1810
1899
|
...now ? { now } : {},
|
|
1811
1900
|
onTurnFinished: (sessionId) => {
|
|
1812
1901
|
reportCreatedAgents(sessionId).catch((err) => clientLog.warn({ err }, "agent.report_created_failed"));
|
|
@@ -1853,12 +1942,25 @@ function createAcpWorkspaceClient({
|
|
|
1853
1942
|
return response;
|
|
1854
1943
|
}
|
|
1855
1944
|
function rememberRows(sessions) {
|
|
1945
|
+
const kept = [];
|
|
1946
|
+
let unreadable;
|
|
1856
1947
|
for (const session of sessions) {
|
|
1857
|
-
|
|
1948
|
+
let row;
|
|
1949
|
+
try {
|
|
1950
|
+
row = rowOf(session);
|
|
1951
|
+
} catch (error) {
|
|
1952
|
+
unreadable = error;
|
|
1953
|
+
clientLog.warn({ id: loggedId(session, "sessionId") }, "sessions.row_skipped");
|
|
1954
|
+
continue;
|
|
1955
|
+
}
|
|
1858
1956
|
remember(row.sessionId, row.info, row.updatedAt);
|
|
1859
1957
|
if (row.title)
|
|
1860
1958
|
store.setTitle(row.sessionId, row.title);
|
|
1959
|
+
kept.push(session);
|
|
1861
1960
|
}
|
|
1961
|
+
if (sessions.length > 0 && kept.length === 0)
|
|
1962
|
+
throw unreadable;
|
|
1963
|
+
return kept;
|
|
1862
1964
|
}
|
|
1863
1965
|
const pageReads = new Map;
|
|
1864
1966
|
let catalogScope;
|
|
@@ -1867,10 +1969,7 @@ function createAcpWorkspaceClient({
|
|
|
1867
1969
|
const inFlight = pageReads.get(key);
|
|
1868
1970
|
if (inFlight)
|
|
1869
1971
|
return inFlight;
|
|
1870
|
-
const read = connection.listSessions(meta, cursor).then((page) => {
|
|
1871
|
-
rememberRows(page.sessions);
|
|
1872
|
-
return page;
|
|
1873
|
-
}).finally(() => pageReads.delete(key));
|
|
1972
|
+
const read = connection.listSessions(meta, cursor).then((page) => ({ ...page, sessions: rememberRows(page.sessions) })).finally(() => pageReads.delete(key));
|
|
1874
1973
|
pageReads.set(key, read);
|
|
1875
1974
|
return read;
|
|
1876
1975
|
}
|
|
@@ -1938,16 +2037,16 @@ function createAcpWorkspaceClient({
|
|
|
1938
2037
|
let page;
|
|
1939
2038
|
try {
|
|
1940
2039
|
page = await listSessions();
|
|
1941
|
-
} catch {
|
|
2040
|
+
} catch (err) {
|
|
1942
2041
|
if (stale(generation))
|
|
1943
2042
|
return;
|
|
2043
|
+
clientLog.warn({ err, attempt }, "sessions.relist_retry_failed");
|
|
1944
2044
|
attempt += 1;
|
|
1945
2045
|
await backOff(backoffDelay(attempt, RELIST_BACKOFF));
|
|
1946
2046
|
continue;
|
|
1947
2047
|
}
|
|
1948
2048
|
const sessionIds = page.sessions.map(({ sessionId }) => sessionId);
|
|
1949
|
-
|
|
1950
|
-
listener(sessionIds);
|
|
2049
|
+
callEach(catalogListeners, clientLog, "sessions.catalog_listener.failed", sessionIds);
|
|
1951
2050
|
return;
|
|
1952
2051
|
}
|
|
1953
2052
|
}
|
|
@@ -2048,9 +2147,9 @@ function createAcpWorkspaceClient({
|
|
|
2048
2147
|
query,
|
|
2049
2148
|
...agentId === undefined ? {} : { agentId }
|
|
2050
2149
|
});
|
|
2051
|
-
rememberRows(sessions);
|
|
2052
|
-
const titles = new Map(
|
|
2053
|
-
return store.rowsFor(
|
|
2150
|
+
const kept = rememberRows(sessions);
|
|
2151
|
+
const titles = new Map(kept.map(({ sessionId, title }) => [sessionId, title ?? ""]));
|
|
2152
|
+
return store.rowsFor(kept.map(({ sessionId }) => sessionId)).map(({ sessionId, agentId, updatedAt }) => ({
|
|
2054
2153
|
sessionId,
|
|
2055
2154
|
agentId,
|
|
2056
2155
|
title: titles.get(sessionId) ?? "",
|
|
@@ -2063,6 +2162,7 @@ function createAcpWorkspaceClient({
|
|
|
2063
2162
|
},
|
|
2064
2163
|
async getSessionMetadata(sessionIds) {
|
|
2065
2164
|
await readRows(sessionIds);
|
|
2165
|
+
store.answer(sessionIds);
|
|
2066
2166
|
return store.rowsFor(sessionIds);
|
|
2067
2167
|
},
|
|
2068
2168
|
subscribeSessionMetadata: store.subscribeMetadata,
|
|
@@ -2613,6 +2713,7 @@ class HgwRemoteClient {
|
|
|
2613
2713
|
}
|
|
2614
2714
|
}
|
|
2615
2715
|
export {
|
|
2716
|
+
AcpConnectionClosedError,
|
|
2616
2717
|
AgentUpdateError,
|
|
2617
2718
|
HgwClientError,
|
|
2618
2719
|
HgwRemoteClient,
|
package/dist/client/log.d.ts
CHANGED
|
@@ -28,4 +28,15 @@ export declare function frameFields(direction: "in" | "out", message: unknown):
|
|
|
28
28
|
};
|
|
29
29
|
/** `stream` with one `acp.frame` debug line per message, each way. */
|
|
30
30
|
export declare function loggedStream(stream: WireStream, logger: Logger): WireStream;
|
|
31
|
+
/**
|
|
32
|
+
* The id at `path` in a row not yet checked, bounded for a warning. A warning
|
|
33
|
+
* about a rejected row names it by this alone, never by its content.
|
|
34
|
+
*/
|
|
35
|
+
export declare function loggedId(row: unknown, ...path: string[]): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Calls every listener with `args`, each on its own: one that throws is
|
|
38
|
+
* logged as `event` and costs only itself, never the listeners after it nor
|
|
39
|
+
* the caller that fanned out to them.
|
|
40
|
+
*/
|
|
41
|
+
export declare function callEach<Args extends readonly unknown[]>(listeners: Iterable<(...args: Args) => void>, logger: Logger, event: string, ...args: Args): void;
|
|
31
42
|
export {};
|
package/dist/client/types.d.ts
CHANGED
|
@@ -63,6 +63,13 @@ export type AcpSessionListener = {
|
|
|
63
63
|
replay?: AcpSessionReplayListener;
|
|
64
64
|
state?: (state: AcpSessionState) => void;
|
|
65
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* A read (`listAgents`, `listSessions`, `searchSessions`, `resumePage`) waits
|
|
68
|
+
* out a reconnect and goes out again on the transport that recovers, and a
|
|
69
|
+
* write for an opened Session once it has rejoined. Any other call a
|
|
70
|
+
* transport closes under, and every call once the connection has ended,
|
|
71
|
+
* rejects as `AcpConnectionClosedError`.
|
|
72
|
+
*/
|
|
66
73
|
export interface AcpConnection {
|
|
67
74
|
readonly status: AcpConnectionStatus;
|
|
68
75
|
/**
|
|
@@ -75,7 +82,10 @@ export interface AcpConnection {
|
|
|
75
82
|
/** Resolves with `InitializeResponse._meta.hgw` once the handshake settles. */
|
|
76
83
|
readonly initialized: Promise<z.infer<typeof HgwInitializeMetaSchema>>;
|
|
77
84
|
subscribeStatus(listener: (status: AcpConnectionStatus) => void): () => void;
|
|
78
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* Set from a close until the transport is ready again. Each Session's
|
|
87
|
+
* rejoin is its own state (`sessionState`), not the connection's.
|
|
88
|
+
*/
|
|
79
89
|
readonly outage: AcpConnectionOutage | undefined;
|
|
80
90
|
subscribeOutage(listener: (outage: AcpConnectionOutage | undefined) => void): () => void;
|
|
81
91
|
/**
|
|
@@ -17,6 +17,15 @@ export declare class AgentUpdateError extends Error {
|
|
|
17
17
|
readonly code: "unsupported" | "conflict";
|
|
18
18
|
constructor(code: "unsupported" | "conflict", message: string);
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* The ACP connection is gone for a request: it has ended, no transport is open
|
|
22
|
+
* to send on, or a transport closed under a request it does not send again.
|
|
23
|
+
* `cause` holds what that transport closed with, which a failed socket leaves
|
|
24
|
+
* a DOM `Event`. Gateway refusals and timeouts reject as they come.
|
|
25
|
+
*/
|
|
26
|
+
export declare class AcpConnectionClosedError extends Error {
|
|
27
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
28
|
+
}
|
|
20
29
|
export type SessionStatus = "idle" | "running" | "waiting-for-input" | "failed" | "unknown";
|
|
21
30
|
export type ActivityBase = {
|
|
22
31
|
id: string;
|
package/dist/protocol/acp.d.ts
CHANGED
|
@@ -90,7 +90,17 @@ export declare const HGW_JSONRPC_ERRORS: {
|
|
|
90
90
|
readonly temporarilyUnavailable: -31013;
|
|
91
91
|
readonly uncertainMutation: -31014;
|
|
92
92
|
readonly unsupported: -31015;
|
|
93
|
+
/**
|
|
94
|
+
* Params too large for one frame. The client raises it before sending and
|
|
95
|
+
* the gateway never sends it, so it has no machine name on the wire.
|
|
96
|
+
*/
|
|
97
|
+
readonly requestTooLarge: -31016;
|
|
93
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* The largest inbound WebSocket frame the gateway takes, in bytes. A larger
|
|
101
|
+
* one closes the socket, and with it every Session on the tab.
|
|
102
|
+
*/
|
|
103
|
+
export declare const HGW_MAX_FRAME_BYTES = 1100000;
|
|
94
104
|
export type HgwJsonRpcErrorCode = (typeof HGW_JSONRPC_ERRORS)[keyof typeof HGW_JSONRPC_ERRORS];
|
|
95
105
|
export declare const IdentifierSchema: z.ZodString;
|
|
96
106
|
export declare const HgwExtensionsSchema: z.ZodObject<{
|
package/dist/protocol/sdk.js
CHANGED
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
HGW_PERMISSION_KIND_SESSION2,
|
|
66
66
|
HGW_PLAN_ID2,
|
|
67
67
|
HGW_JSONRPC_ERRORS2,
|
|
68
|
+
HGW_MAX_FRAME_BYTES2,
|
|
68
69
|
IdentifierSchema2,
|
|
69
70
|
HgwExtensionsSchema2,
|
|
70
71
|
HgwClientCapabilitiesMetaSchema2,
|
|
@@ -215,6 +216,7 @@ export {
|
|
|
215
216
|
HGW_AUTH_METHOD_INVITE2 as HGW_AUTH_METHOD_INVITE,
|
|
216
217
|
HGW_EXTENSION_VERSION2 as HGW_EXTENSION_VERSION,
|
|
217
218
|
HGW_JSONRPC_ERRORS2 as HGW_JSONRPC_ERRORS,
|
|
219
|
+
HGW_MAX_FRAME_BYTES2 as HGW_MAX_FRAME_BYTES,
|
|
218
220
|
HGW_META_KEY2 as HGW_META_KEY,
|
|
219
221
|
HGW_METHODS2 as HGW_METHODS,
|
|
220
222
|
HGW_PERMISSION_KIND_SESSION2 as HGW_PERMISSION_KIND_SESSION,
|
package/package.json
CHANGED