@byok-sdk/client 0.5.0 → 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 +91 -1
- package/dist/adapters/index.js +183 -34
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/pi/events.d.ts +1 -1
- package/dist/adapters/pi/mcp-config.d.ts +1 -0
- package/dist/adapters/pi/mcp-extension.js +25 -0
- package/dist/adapters/pi/mcp-extension.js.map +1 -0
- package/dist/adapters/pi/permission-mapping.d.ts +1 -1
- package/dist/adapters/pi/pi-adapter.d.ts +5 -0
- package/dist/adapters/pi/resolve-extensions.d.ts +11 -0
- package/dist/agent-home.d.ts +106 -0
- package/dist/bin/byok-agent.js +12902 -9340
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/bin/byok-approval-mcp.js.map +1 -1
- package/dist/bin/commands/toolsets.d.ts +8 -0
- package/dist/bin/config.d.ts +3 -1
- package/dist/bin/format.d.ts +5 -1
- package/dist/bin/official-release.d.ts +1 -0
- package/dist/bin/version.d.ts +2 -0
- package/dist/daemon/agent-content-audit-store.d.ts +35 -0
- package/dist/daemon/agent-content-read.d.ts +169 -0
- package/dist/daemon/agent-egress-controller.d.ts +76 -0
- package/dist/daemon/agent-egress-policy.d.ts +36 -0
- package/dist/daemon/agent-egress-sanitizer.d.ts +38 -0
- package/dist/daemon/agent-egress-spool.d.ts +116 -0
- package/dist/daemon/agent-session-handoff-store.d.ts +82 -0
- package/dist/daemon/blob-client.d.ts +6 -2
- package/dist/daemon/connection-manager.d.ts +4 -2
- package/dist/daemon/control-protocol.d.ts +12 -0
- package/dist/daemon/create-daemon.d.ts +83 -3
- package/dist/daemon/long-poll-transport.d.ts +60 -0
- package/dist/daemon/presence-publisher.d.ts +9 -3
- package/dist/daemon/task-runner.d.ts +73 -4
- package/dist/daemon/toolset-registry.d.ts +30 -0
- package/dist/daemon/url.d.ts +21 -0
- package/dist/daemon/ws-transport.d.ts +32 -5
- package/dist/index.d.ts +14 -2
- package/dist/index.js +12682 -9191
- package/dist/index.js.map +1 -1
- package/dist/release-identity.d.ts +15 -0
- package/dist/types.d.ts +44 -0
- package/package.json +7 -5
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { AgentHomeLayout, type AgentRef } from '../agent-home';
|
|
2
|
+
import { AgentContentAuditStore } from './agent-content-audit-store';
|
|
3
|
+
export declare const AGENT_CONTENT_READ_SURFACES: readonly ['workspace', 'transcript', 'artifact'];
|
|
4
|
+
export type AgentContentReadSurface = (typeof AGENT_CONTENT_READ_SURFACES)[number];
|
|
5
|
+
/** Additive capability names. Each surface is independently admitted. */
|
|
6
|
+
export declare const AGENT_CONTENT_READ_CAPABILITIES: Readonly<{
|
|
7
|
+
readonly workspace: "agent-content-workspace-read";
|
|
8
|
+
readonly transcript: "agent-content-transcript-read";
|
|
9
|
+
readonly artifact: "agent-content-artifact-read";
|
|
10
|
+
}>;
|
|
11
|
+
export declare const AGENT_CONTENT_READ_CAPABILITY_WORKSPACE: "agent-content-workspace-read";
|
|
12
|
+
export declare const AGENT_CONTENT_READ_CAPABILITY_TRANSCRIPT: "agent-content-transcript-read";
|
|
13
|
+
export declare const AGENT_CONTENT_READ_CAPABILITY_ARTIFACT: "agent-content-artifact-read";
|
|
14
|
+
export declare const AGENT_CONTENT_READ_DECISIONS: readonly ['allow', 'deny'];
|
|
15
|
+
export type AgentContentReadDecision = (typeof AGENT_CONTENT_READ_DECISIONS)[number];
|
|
16
|
+
/**
|
|
17
|
+
* Reasons are stable policy observations, not user-facing prose. A denied
|
|
18
|
+
* read has exactly one reason and never returns any bytes.
|
|
19
|
+
*/
|
|
20
|
+
export declare const AGENT_CONTENT_READ_REASONS: readonly ['invalid-request', 'policy-disabled', 'capability-missing', 'policy-revision-mismatch', 'absolute-target', 'non-relative-target', 'dot-segment', 'sensitive-name', 'root-not-allowlisted', 'root-invalid', 'path-escape', 'target-missing', 'symlink', 'not-regular-file', 'byte-limit', 'mime-not-allowlisted', 'text-not-allowlisted', 'text-decode-failed', 'identity-mismatch'];
|
|
21
|
+
export type AgentContentReadReason = (typeof AGENT_CONTENT_READ_REASONS)[number];
|
|
22
|
+
export type AgentContentReadDropReason = AgentContentReadReason;
|
|
23
|
+
export type AgentContentActorKind = 'user' | 'agent' | 'system';
|
|
24
|
+
export interface AgentContentReadActor {
|
|
25
|
+
readonly kind: AgentContentActorKind;
|
|
26
|
+
readonly id: string;
|
|
27
|
+
}
|
|
28
|
+
/** Exact identity copied from the persisted Agent session handoff. */
|
|
29
|
+
export interface AgentContentSessionIdentity {
|
|
30
|
+
readonly agentRef: AgentRef;
|
|
31
|
+
readonly sessionRef: string;
|
|
32
|
+
readonly runtimeId: string;
|
|
33
|
+
readonly cwd: string;
|
|
34
|
+
}
|
|
35
|
+
export type AgentContentReadRoot = {
|
|
36
|
+
readonly kind: 'agent-home';
|
|
37
|
+
} | {
|
|
38
|
+
readonly kind: 'runtime-allowlisted';
|
|
39
|
+
readonly root: string;
|
|
40
|
+
};
|
|
41
|
+
/** The policy is one authority; no semantic defaults are inferred from a request. */
|
|
42
|
+
export interface AgentContentReadPolicy {
|
|
43
|
+
readonly enabled: true;
|
|
44
|
+
readonly capability: string;
|
|
45
|
+
readonly root: AgentContentReadRoot;
|
|
46
|
+
readonly policyRevision: string;
|
|
47
|
+
/** Positive hard limit applied before allocating the file contents. */
|
|
48
|
+
readonly maxBytes: number;
|
|
49
|
+
/** Positive hard limit for an explicitly requested UTF-8 decode. */
|
|
50
|
+
readonly maxTextBytes: number;
|
|
51
|
+
/** Exact MIME strings. Wildcards are not accepted. */
|
|
52
|
+
readonly allowedMimeTypes: readonly string[];
|
|
53
|
+
/** Exact subset of allowedMimeTypes permitted with decodeAs=utf8. */
|
|
54
|
+
readonly textMimeTypes: readonly string[];
|
|
55
|
+
/** Product additions may tighten this list; SDK-reserved names cannot be removed. */
|
|
56
|
+
readonly sensitiveNames?: readonly string[];
|
|
57
|
+
/** Transcript reads must bind to this persisted identity, unless a resolver is supplied. */
|
|
58
|
+
readonly expectedTranscriptIdentity?: AgentContentSessionIdentity;
|
|
59
|
+
}
|
|
60
|
+
export type AgentContentReadPolicySelection = 'disabled' | AgentContentReadPolicy;
|
|
61
|
+
export type ContentReadPolicy = AgentContentReadPolicy;
|
|
62
|
+
export interface AgentContentReadRequest {
|
|
63
|
+
readonly requestId: string;
|
|
64
|
+
readonly actor: AgentContentReadActor;
|
|
65
|
+
readonly tenantId: string;
|
|
66
|
+
readonly deviceId: string;
|
|
67
|
+
readonly agentRef: AgentRef;
|
|
68
|
+
readonly surface: AgentContentReadSurface;
|
|
69
|
+
/** Portable, slash-separated relative target. */
|
|
70
|
+
readonly relativeTarget: string;
|
|
71
|
+
/** Caller-declared MIME. No extension or content inference is performed. */
|
|
72
|
+
readonly mimeType: string;
|
|
73
|
+
readonly capability: string;
|
|
74
|
+
readonly policyRevision: string;
|
|
75
|
+
/** Optional narrower request bound; it can never widen policy.maxBytes. */
|
|
76
|
+
readonly maxBytes?: number;
|
|
77
|
+
/** Optional narrower request MIME declaration; it can never widen policy allowlist. */
|
|
78
|
+
readonly allowedMimeTypes?: readonly string[];
|
|
79
|
+
/** Omit for bytes; utf8 is explicit and bounded by maxTextBytes. */
|
|
80
|
+
readonly decodeAs?: 'bytes' | 'utf8';
|
|
81
|
+
/** Required for transcript; optional for workspace/artifact projections. */
|
|
82
|
+
readonly session?: AgentContentSessionIdentity;
|
|
83
|
+
}
|
|
84
|
+
export interface AgentContentAuditReceipt {
|
|
85
|
+
readonly version: 1;
|
|
86
|
+
readonly requestId: string;
|
|
87
|
+
readonly actor: AgentContentReadActor;
|
|
88
|
+
readonly tenantId: string;
|
|
89
|
+
readonly deviceId: string;
|
|
90
|
+
readonly agentRef: AgentRef;
|
|
91
|
+
readonly surface: AgentContentReadSurface;
|
|
92
|
+
readonly session?: AgentContentSessionIdentity;
|
|
93
|
+
/** Canonical relative target only; no absolute pathname is ever recorded. */
|
|
94
|
+
readonly relativeTarget: string;
|
|
95
|
+
readonly policyRevision: string;
|
|
96
|
+
readonly byteCount: number;
|
|
97
|
+
readonly contentHash?: string;
|
|
98
|
+
readonly decision: AgentContentReadDecision;
|
|
99
|
+
readonly reason?: AgentContentReadReason;
|
|
100
|
+
readonly recordedAt: string;
|
|
101
|
+
}
|
|
102
|
+
export interface AgentContentReadAllowed {
|
|
103
|
+
readonly decision: 'allow';
|
|
104
|
+
readonly surface: AgentContentReadSurface;
|
|
105
|
+
readonly relativeTarget: string;
|
|
106
|
+
readonly mimeType: string;
|
|
107
|
+
readonly byteCount: number;
|
|
108
|
+
readonly contentHash: string;
|
|
109
|
+
readonly content: Uint8Array;
|
|
110
|
+
readonly text?: string;
|
|
111
|
+
readonly receipt: AgentContentAuditReceipt;
|
|
112
|
+
}
|
|
113
|
+
export interface AgentContentReadDenied {
|
|
114
|
+
readonly decision: 'deny';
|
|
115
|
+
readonly surface: AgentContentReadSurface;
|
|
116
|
+
readonly relativeTarget: string;
|
|
117
|
+
readonly reason: AgentContentReadReason;
|
|
118
|
+
readonly receipt: AgentContentAuditReceipt;
|
|
119
|
+
}
|
|
120
|
+
export type AgentContentReadResult = AgentContentReadAllowed | AgentContentReadDenied;
|
|
121
|
+
export type AgentContentReadDecisionRecord = AgentContentReadResult;
|
|
122
|
+
export declare class AgentContentReadPolicyError extends Error {
|
|
123
|
+
constructor(message: string);
|
|
124
|
+
}
|
|
125
|
+
export declare class AgentContentReadRequestError extends Error {
|
|
126
|
+
constructor(message: string);
|
|
127
|
+
}
|
|
128
|
+
export declare class AgentContentReadAuditError extends Error {
|
|
129
|
+
constructor(message: string, options?: ErrorOptions);
|
|
130
|
+
}
|
|
131
|
+
export interface AgentContentReadPolicyEngineOptions {
|
|
132
|
+
readonly agentHomeLayout?: AgentHomeLayout;
|
|
133
|
+
readonly policies: Readonly<Record<AgentContentReadSurface, AgentContentReadPolicySelection>>;
|
|
134
|
+
readonly capabilities: Iterable<string>;
|
|
135
|
+
readonly runtimeAllowlistedRoots?: readonly string[];
|
|
136
|
+
readonly auditStore: AgentContentAuditStore;
|
|
137
|
+
/** Optional all-surface session gate for hosts that require a live handoff before every read. */
|
|
138
|
+
readonly resolveSessionIdentity?: (request: AgentContentReadRequest) => Promise<AgentContentSessionIdentity | undefined> | AgentContentSessionIdentity | undefined;
|
|
139
|
+
/** Binds transcript claims to AgentSessionHandoffStore-backed exact identity. */
|
|
140
|
+
readonly resolveTranscriptIdentity?: (request: AgentContentReadRequest) => Promise<AgentContentSessionIdentity | undefined> | AgentContentSessionIdentity | undefined;
|
|
141
|
+
}
|
|
142
|
+
export declare const SDK_RESERVED_CONTENT_NAMES: readonly string[];
|
|
143
|
+
export declare function createAgentContentReadPolicy(input: AgentContentReadPolicy): AgentContentReadPolicy;
|
|
144
|
+
/**
|
|
145
|
+
* Independent local content-read policy engine. It reads one explicitly
|
|
146
|
+
* requested file at a time; it never walks, mirrors, indexes, or parses an
|
|
147
|
+
* Agent home or runtime directory.
|
|
148
|
+
*/
|
|
149
|
+
export declare class AgentContentReadPolicyEngine {
|
|
150
|
+
private readonly options;
|
|
151
|
+
private readonly policies;
|
|
152
|
+
private readonly capabilities;
|
|
153
|
+
private readonly runtimeRoots;
|
|
154
|
+
private readonly runtimeRootCache;
|
|
155
|
+
private readonly resolveSessionIdentity?;
|
|
156
|
+
private readonly resolveTranscriptIdentity?;
|
|
157
|
+
constructor(options: AgentContentReadPolicyEngineOptions);
|
|
158
|
+
read(input: AgentContentReadRequest): Promise<AgentContentReadResult>;
|
|
159
|
+
/** Alias used by integration adapters that call the operation request. */
|
|
160
|
+
readContent(request: AgentContentReadRequest): Promise<AgentContentReadResult>;
|
|
161
|
+
/** A request is one bounded read, never a directory listing or recursive mirror. */
|
|
162
|
+
request(request: AgentContentReadRequest): Promise<AgentContentReadResult>;
|
|
163
|
+
private resolveRoot;
|
|
164
|
+
private validateRuntimeRoot;
|
|
165
|
+
private checkSessionIdentity;
|
|
166
|
+
private checkTranscriptIdentity;
|
|
167
|
+
private deny;
|
|
168
|
+
private appendReceipt;
|
|
169
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { AgentEvent } from '@byok-sdk/protocol';
|
|
2
|
+
import type { AgentRef } from '../agent-home';
|
|
3
|
+
import { type AgentEgressDropReason, type AgentEgressDropReceipt, type AgentEgressPolicy, type AgentEgressStatus } from './agent-egress-policy';
|
|
4
|
+
import { type AgentReliableAck, type AgentContentReceiptWithoutReliableIdentity, type AgentReliableEgressRecord } from './agent-egress-spool';
|
|
5
|
+
import { type AgentEgressSanitizer } from './agent-egress-sanitizer';
|
|
6
|
+
export interface AgentEgressControllerOptions {
|
|
7
|
+
readonly policy: Readonly<AgentEgressPolicy>;
|
|
8
|
+
/** Authenticated tenant identity, never accepted from an egress event. */
|
|
9
|
+
readonly tenantId?: string;
|
|
10
|
+
readonly sanitizer?: AgentEgressSanitizer;
|
|
11
|
+
}
|
|
12
|
+
export interface AgentEgressProgressInput {
|
|
13
|
+
readonly agentRef?: AgentRef;
|
|
14
|
+
readonly taskId: string;
|
|
15
|
+
readonly events: readonly AgentEvent[];
|
|
16
|
+
readonly serverCapabilities: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export interface AgentEgressReliableInput {
|
|
19
|
+
readonly homeDir: string;
|
|
20
|
+
readonly agentRef: AgentRef;
|
|
21
|
+
readonly payload: unknown;
|
|
22
|
+
readonly sessionRef: string;
|
|
23
|
+
readonly taskId?: string;
|
|
24
|
+
readonly eventId?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentEgressContentReceiptInput {
|
|
27
|
+
readonly homeDir: string;
|
|
28
|
+
readonly agentRef: AgentRef;
|
|
29
|
+
/** The content-free payload before the spool supplies stable event/cursor identity. */
|
|
30
|
+
readonly payload: AgentContentReceiptWithoutReliableIdentity;
|
|
31
|
+
readonly taskId?: string;
|
|
32
|
+
}
|
|
33
|
+
export type AgentEgressReliableAppendResult = Readonly<{
|
|
34
|
+
ok: true;
|
|
35
|
+
record: AgentReliableEgressRecord;
|
|
36
|
+
}> | Readonly<{
|
|
37
|
+
ok: false;
|
|
38
|
+
reason: AgentEgressDropReason;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* The one daemon-owned policy consumer. Reliable and latest-value retain
|
|
42
|
+
* distinct types and stores; retries are sends, and only exact acknowledgments
|
|
43
|
+
* retire durable records.
|
|
44
|
+
*/
|
|
45
|
+
export declare class AgentEgressController {
|
|
46
|
+
private readonly options;
|
|
47
|
+
private readonly latest;
|
|
48
|
+
private readonly spools;
|
|
49
|
+
private readonly latestStatus;
|
|
50
|
+
private readonly reliableStatus;
|
|
51
|
+
private readonly drops;
|
|
52
|
+
constructor(options: AgentEgressControllerOptions);
|
|
53
|
+
get policy(): Readonly<AgentEgressPolicy>;
|
|
54
|
+
status(): AgentEgressStatus;
|
|
55
|
+
dropReceipts(): readonly AgentEgressDropReceipt[];
|
|
56
|
+
noteTransportDrop(reason: AgentEgressDropReason, agentRef?: AgentRef): void;
|
|
57
|
+
/** Project before TaskRunner builds a `task.progress` envelope. */
|
|
58
|
+
projectLatestValue(input: AgentEgressProgressInput): readonly AgentEvent[];
|
|
59
|
+
appendReliable(input: AgentEgressReliableInput): Promise<AgentEgressReliableAppendResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Content decisions are reliable facts too. They never enter the generic
|
|
62
|
+
* egress payload authority: the spool persists their exact protocol payload
|
|
63
|
+
* with `wireType: agent.content.receipt` before any transport attempt.
|
|
64
|
+
*/
|
|
65
|
+
appendContentReceipt(input: AgentEgressContentReceiptInput): Promise<AgentEgressReliableAppendResult>;
|
|
66
|
+
/** Retires only the record whose full Agent/tenant/revision/id/cursor tuple matches. */
|
|
67
|
+
acknowledge(ack: AgentReliableAck): Promise<boolean>;
|
|
68
|
+
/** Re-open every existing Agent-local spool before retrying stable records after restart. */
|
|
69
|
+
recover(agentsRoot: string): Promise<void>;
|
|
70
|
+
reliableRecords(): readonly AgentReliableEgressRecord[];
|
|
71
|
+
/** Missing ack capability holds records in their reliable lane; it never makes them lossy. */
|
|
72
|
+
retryableReliableRecords(serverCapabilities: readonly string[]): readonly AgentReliableEgressRecord[];
|
|
73
|
+
private spoolFor;
|
|
74
|
+
private tenantPendingBytes;
|
|
75
|
+
private noteDrop;
|
|
76
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type AgentEgressDropReason, type AgentEgressPolicy, type AgentEvent } from '@byok-sdk/protocol';
|
|
2
|
+
export type { AgentEgressDropReason, AgentEgressPolicy } from '@byok-sdk/protocol';
|
|
3
|
+
export interface AgentEgressDropReceipt {
|
|
4
|
+
lane: 'latest-value' | 'reliable';
|
|
5
|
+
reason: AgentEgressDropReason;
|
|
6
|
+
agentId?: string;
|
|
7
|
+
tenantId?: string;
|
|
8
|
+
eventId?: string;
|
|
9
|
+
occurredAt: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AgentEgressLaneStatus {
|
|
12
|
+
pendingEvents: number;
|
|
13
|
+
pendingBytes: number;
|
|
14
|
+
replaced: number;
|
|
15
|
+
dropped: number;
|
|
16
|
+
lastDropReason?: AgentEgressDropReason;
|
|
17
|
+
}
|
|
18
|
+
export interface AgentEgressStatus {
|
|
19
|
+
policyRevision: string;
|
|
20
|
+
latestValue: AgentEgressLaneStatus;
|
|
21
|
+
reliable: AgentEgressLaneStatus;
|
|
22
|
+
}
|
|
23
|
+
/** Safe policy selected only when the host has not opted into content. */
|
|
24
|
+
export declare const DEFAULT_AGENT_EGRESS_POLICY: Readonly<AgentEgressPolicy>;
|
|
25
|
+
export declare class AgentEgressPolicyError extends Error {
|
|
26
|
+
constructor(message: string);
|
|
27
|
+
}
|
|
28
|
+
/** Resolve/validate once at construction; unknown policy shapes never become an implicit default. */
|
|
29
|
+
export declare function resolveAgentEgressPolicy(policy: AgentEgressPolicy | undefined): Readonly<AgentEgressPolicy>;
|
|
30
|
+
/**
|
|
31
|
+
* Default activity projection. Every retained string is SDK-authored; no
|
|
32
|
+
* runtime trajectory, tool, prompt, environment, argv, path, or credential
|
|
33
|
+
* value survives this transformation.
|
|
34
|
+
*/
|
|
35
|
+
export declare function metadataStatusEvent(event: AgentEvent): AgentEvent;
|
|
36
|
+
export declare function eventBytes(event: AgentEvent): number;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type Envelope } from '@byok-sdk/protocol';
|
|
2
|
+
import { type AgentEgressDropReason, type AgentEgressPolicy } from './agent-egress-policy';
|
|
3
|
+
export interface AgentEgressSanitizerContext {
|
|
4
|
+
readonly lane: 'latest-value' | 'reliable';
|
|
5
|
+
readonly policyRevision: string;
|
|
6
|
+
readonly envelopeType?: string;
|
|
7
|
+
readonly agentId?: string;
|
|
8
|
+
readonly tenantId?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Optional named host redaction hook for an explicitly contentful policy.
|
|
12
|
+
* It receives the SDK-projected value, never a second raw wire
|
|
13
|
+
* representation. Throwing/refusing drops the event; callers never receive
|
|
14
|
+
* an original-payload fallback.
|
|
15
|
+
*/
|
|
16
|
+
export type AgentEgressSanitizer = (value: unknown, context: AgentEgressSanitizerContext) => unknown;
|
|
17
|
+
export declare class AgentEgressSanitizationError extends Error {
|
|
18
|
+
readonly reason: AgentEgressDropReason;
|
|
19
|
+
constructor(message: string, reason?: AgentEgressDropReason);
|
|
20
|
+
}
|
|
21
|
+
export type SanitizedEnvelope = Readonly<{
|
|
22
|
+
ok: true;
|
|
23
|
+
envelope: Envelope;
|
|
24
|
+
}> | Readonly<{
|
|
25
|
+
ok: false;
|
|
26
|
+
reason: AgentEgressDropReason;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* The one envelope-boundary sanitizer used before either transport sees an
|
|
30
|
+
* envelope. It parses the final value through the frozen protocol so a
|
|
31
|
+
* broken custom sanitizer also fails locally, before WS bytes or long-poll
|
|
32
|
+
* JSON can be created.
|
|
33
|
+
*/
|
|
34
|
+
export declare function sanitizeEgressEnvelope(envelope: Envelope, policy: Readonly<AgentEgressPolicy>, sanitizer: AgentEgressSanitizer | undefined, context?: Omit<AgentEgressSanitizerContext, 'lane' | 'policyRevision' | 'envelopeType'> & {
|
|
35
|
+
lane?: 'latest-value' | 'reliable';
|
|
36
|
+
}): SanitizedEnvelope;
|
|
37
|
+
/** Sanitizes a reliable payload before it is hashed/appended, never after. */
|
|
38
|
+
export declare function sanitizeReliablePayload(payload: unknown, policy: Readonly<AgentEgressPolicy>, sanitizer: AgentEgressSanitizer | undefined, context?: Omit<AgentEgressSanitizerContext, 'lane' | 'policyRevision'>): unknown;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type AgentContentReceiptPayload } from '@byok-sdk/protocol';
|
|
2
|
+
import type { AgentRef } from '../agent-home';
|
|
3
|
+
import { type AgentEgressPolicy, type AgentEgressDropReason } from './agent-egress-policy';
|
|
4
|
+
export declare const AGENT_EGRESS_DIRECTORY: string;
|
|
5
|
+
export declare const AGENT_RELIABLE_SPOOL_FILENAME = "reliable-v1.jsonl";
|
|
6
|
+
/** A spool row's intended envelope type, never inferred from its payload. */
|
|
7
|
+
export declare const AGENT_RELIABLE_WIRE_TYPES: readonly ['agent.egress.reliable', 'agent.content.receipt'];
|
|
8
|
+
export type AgentReliableWireType = (typeof AGENT_RELIABLE_WIRE_TYPES)[number];
|
|
9
|
+
type OmitReliableIdentity<T> = T extends unknown ? Omit<T, 'eventId' | 'cursor'> : never;
|
|
10
|
+
export type AgentContentReceiptWithoutReliableIdentity = OmitReliableIdentity<AgentContentReceiptPayload>;
|
|
11
|
+
export interface AgentReliableEgressRecord {
|
|
12
|
+
readonly schema: 1;
|
|
13
|
+
readonly wireType: AgentReliableWireType;
|
|
14
|
+
readonly agentRef: AgentRef;
|
|
15
|
+
readonly tenantId: string;
|
|
16
|
+
readonly policyRevision: string;
|
|
17
|
+
readonly eventId: string;
|
|
18
|
+
readonly cursor: number;
|
|
19
|
+
readonly payload: unknown;
|
|
20
|
+
readonly payloadHash: string;
|
|
21
|
+
readonly byteCount: number;
|
|
22
|
+
readonly createdAt: string;
|
|
23
|
+
readonly sessionRef?: string;
|
|
24
|
+
readonly taskId?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentReliableAppendInput {
|
|
27
|
+
readonly agentRef: AgentRef;
|
|
28
|
+
readonly tenantId: string;
|
|
29
|
+
readonly policyRevision: string;
|
|
30
|
+
readonly payload: unknown;
|
|
31
|
+
readonly sessionRef?: string;
|
|
32
|
+
readonly taskId?: string;
|
|
33
|
+
readonly eventId?: string;
|
|
34
|
+
readonly createdAt?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Content receipts use the existing durable spool but retain their own wire
|
|
38
|
+
* type and validated receipt payload. The request id is the stable event id:
|
|
39
|
+
* a retried local read cannot mint a competing receipt identity.
|
|
40
|
+
*/
|
|
41
|
+
export interface AgentContentReceiptAppendInput {
|
|
42
|
+
readonly agentRef: AgentRef;
|
|
43
|
+
readonly tenantId: string;
|
|
44
|
+
readonly policyRevision: string;
|
|
45
|
+
readonly sessionRef: string;
|
|
46
|
+
readonly payload: AgentContentReceiptWithoutReliableIdentity;
|
|
47
|
+
readonly taskId?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface AgentReliableAck {
|
|
50
|
+
readonly agentRef: AgentRef;
|
|
51
|
+
readonly tenantId: string;
|
|
52
|
+
readonly sessionRef: string;
|
|
53
|
+
readonly policyRevision: string;
|
|
54
|
+
readonly eventId: string;
|
|
55
|
+
readonly cursor: number;
|
|
56
|
+
}
|
|
57
|
+
export declare class AgentReliableSpoolError extends Error {
|
|
58
|
+
constructor(message: string);
|
|
59
|
+
}
|
|
60
|
+
export declare class AgentReliableQuotaError extends AgentReliableSpoolError {
|
|
61
|
+
readonly reason: Extract<AgentEgressDropReason, 'quota_exceeded' | 'backpressure'>;
|
|
62
|
+
constructor(reason: Extract<AgentEgressDropReason, 'quota_exceeded' | 'backpressure'>, message: string);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Per-Agent durable append-before-send log. It is deliberately separate from
|
|
66
|
+
* the inbound task journal: its only truth is outbound reliable egress
|
|
67
|
+
* pending/exact-ack state.
|
|
68
|
+
*/
|
|
69
|
+
export declare class AgentReliableSpool {
|
|
70
|
+
readonly homeDir: string;
|
|
71
|
+
readonly spoolPath: string;
|
|
72
|
+
private readonly pending;
|
|
73
|
+
private nextCursor;
|
|
74
|
+
private logEntries;
|
|
75
|
+
private writeTail;
|
|
76
|
+
private constructor();
|
|
77
|
+
static open(homeDir: string): Promise<AgentReliableSpool>;
|
|
78
|
+
get pendingEvents(): number;
|
|
79
|
+
get pendingBytes(): number;
|
|
80
|
+
records(): readonly AgentReliableEgressRecord[];
|
|
81
|
+
append(input: AgentReliableAppendInput, policy: Readonly<AgentEgressPolicy>, tenantPendingBytes: number): Promise<AgentReliableEgressRecord>;
|
|
82
|
+
/**
|
|
83
|
+
* Append one complete, protocol-validated content receipt before its first
|
|
84
|
+
* send. `eventId` is fixed to `requestId`; the durable spool alone allocates
|
|
85
|
+
* the positive cursor, then validates the final payload before fsync.
|
|
86
|
+
*/
|
|
87
|
+
appendContentReceipt(input: AgentContentReceiptAppendInput, policy: Readonly<AgentEgressPolicy>, tenantPendingBytes: number): Promise<AgentReliableEgressRecord>;
|
|
88
|
+
/** Exact matching ack is the only transition which retires a record. */
|
|
89
|
+
acknowledge(ack: AgentReliableAck): Promise<boolean>;
|
|
90
|
+
private load;
|
|
91
|
+
private appendEntry;
|
|
92
|
+
private compact;
|
|
93
|
+
private exclusive;
|
|
94
|
+
}
|
|
95
|
+
export interface LatestValueRecord {
|
|
96
|
+
readonly agentRef: AgentRef;
|
|
97
|
+
readonly tenantId: string;
|
|
98
|
+
readonly event: import('@byok-sdk/protocol').AgentEvent;
|
|
99
|
+
readonly byteCount: number;
|
|
100
|
+
readonly updatedAt: string;
|
|
101
|
+
}
|
|
102
|
+
/** In-memory latest-value state; it is never replayed as durable history. */
|
|
103
|
+
export declare class AgentLatestValueState {
|
|
104
|
+
private readonly recordsByAgent;
|
|
105
|
+
offer(record: Omit<LatestValueRecord, 'byteCount' | 'updatedAt'>, policy: Readonly<AgentEgressPolicy>): Readonly<{
|
|
106
|
+
accepted: true;
|
|
107
|
+
replaced: boolean;
|
|
108
|
+
record: LatestValueRecord;
|
|
109
|
+
}> | Readonly<{
|
|
110
|
+
accepted: false;
|
|
111
|
+
reason: Extract<AgentEgressDropReason, 'quota_exceeded' | 'backpressure'>;
|
|
112
|
+
}>;
|
|
113
|
+
get pendingEvents(): number;
|
|
114
|
+
get pendingBytes(): number;
|
|
115
|
+
}
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type AgentRef } from '../agent-home';
|
|
2
|
+
export type AgentTerminalCause = 'complete' | 'failed' | 'cancelled';
|
|
3
|
+
export interface AgentSessionHandoff {
|
|
4
|
+
readonly agentRef: AgentRef;
|
|
5
|
+
/** Task that created the native runtime session. */
|
|
6
|
+
readonly taskId: string;
|
|
7
|
+
readonly sessionRef: string;
|
|
8
|
+
readonly runtimeId: string;
|
|
9
|
+
/** Canonical Agent home and runtime cwd; these are intentionally one value. */
|
|
10
|
+
readonly cwd: string;
|
|
11
|
+
readonly leaseId: string;
|
|
12
|
+
readonly terminalCause?: AgentTerminalCause;
|
|
13
|
+
readonly terminalReason?: string;
|
|
14
|
+
readonly updatedAt: string;
|
|
15
|
+
}
|
|
16
|
+
export interface AgentSessionHandoffMatch {
|
|
17
|
+
readonly agentRef: AgentRef;
|
|
18
|
+
readonly sessionRef: string;
|
|
19
|
+
readonly runtimeId: string;
|
|
20
|
+
readonly cwd: string;
|
|
21
|
+
}
|
|
22
|
+
export interface AgentTaskTerminalEvidence {
|
|
23
|
+
readonly agentRef: AgentRef;
|
|
24
|
+
readonly taskId: string;
|
|
25
|
+
readonly runtimeId: string;
|
|
26
|
+
/** Canonical Agent home and sealed runtime cwd. */
|
|
27
|
+
readonly cwd: string;
|
|
28
|
+
readonly leaseId: string;
|
|
29
|
+
/** Present when adapter start succeeded but handoff persistence failed. */
|
|
30
|
+
readonly sessionRef?: string;
|
|
31
|
+
readonly terminalCause: 'failed';
|
|
32
|
+
readonly terminalReason: string;
|
|
33
|
+
readonly updatedAt: string;
|
|
34
|
+
}
|
|
35
|
+
export interface AgentTaskTerminalMatch {
|
|
36
|
+
readonly agentRef: AgentRef;
|
|
37
|
+
readonly taskId: string;
|
|
38
|
+
readonly runtimeId: string;
|
|
39
|
+
readonly cwd: string;
|
|
40
|
+
}
|
|
41
|
+
export declare class AgentSessionHandoffStoreError extends Error {
|
|
42
|
+
constructor(message: string);
|
|
43
|
+
}
|
|
44
|
+
export declare class AgentSessionHandoffCorruptError extends AgentSessionHandoffStoreError {
|
|
45
|
+
constructor(message: string);
|
|
46
|
+
}
|
|
47
|
+
export declare class AgentSessionHandoffMismatchError extends AgentSessionHandoffStoreError {
|
|
48
|
+
constructor(message: string);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Durable, fail-closed session evidence stored inside the canonical Agent
|
|
52
|
+
* home. Each session gets one hash-addressed append-only JSONL ledger under
|
|
53
|
+
* `.byok/runtime-sessions/`; session text never becomes a pathname. Unlike
|
|
54
|
+
* the legacy SessionWorkspaceStore, corrupt bytes are never interpreted as a
|
|
55
|
+
* missing mapping.
|
|
56
|
+
*/
|
|
57
|
+
export declare class AgentSessionHandoffStore {
|
|
58
|
+
private readonly queues;
|
|
59
|
+
get(expected: AgentSessionHandoffMatch): Promise<AgentSessionHandoff | undefined>;
|
|
60
|
+
/** Append-only readback for audit/recovery; every historical terminal remains visible. */
|
|
61
|
+
history(expected: AgentSessionHandoffMatch): Promise<readonly AgentSessionHandoff[]>;
|
|
62
|
+
/** Exact identity check used before a strict Agent resume is admitted. */
|
|
63
|
+
requireMatch(expected: AgentSessionHandoffMatch): Promise<AgentSessionHandoff>;
|
|
64
|
+
/** Append-only, fsynced write. The caller awaits this before task.started. */
|
|
65
|
+
record(input: Omit<AgentSessionHandoff, 'updatedAt' | 'terminalCause' | 'terminalReason'>): Promise<AgentSessionHandoff>;
|
|
66
|
+
/** Records the first terminal cause without changing the exact handoff identity. */
|
|
67
|
+
recordTerminal(expected: AgentSessionHandoffMatch, cause: AgentTerminalCause, reason?: string): Promise<AgentSessionHandoff>;
|
|
68
|
+
/**
|
|
69
|
+
* Persists a claimed Agent task failure that happened before an active
|
|
70
|
+
* session handoff existed. Callers await the fsync before sending
|
|
71
|
+
* `task.fail`, so cloud state can never outrun the Agent-local evidence.
|
|
72
|
+
*/
|
|
73
|
+
recordTaskTerminal(input: Omit<AgentTaskTerminalEvidence, 'updatedAt' | 'terminalCause'>): Promise<AgentTaskTerminalEvidence>;
|
|
74
|
+
getTaskTerminal(expectedInput: AgentTaskTerminalMatch): Promise<AgentTaskTerminalEvidence | undefined>;
|
|
75
|
+
private filePath;
|
|
76
|
+
private taskTerminalFilePath;
|
|
77
|
+
private enqueue;
|
|
78
|
+
private load;
|
|
79
|
+
private loadAll;
|
|
80
|
+
private loadTaskTerminal;
|
|
81
|
+
private append;
|
|
82
|
+
}
|
|
@@ -3,7 +3,9 @@ import type { AuthManager } from './auth-manager';
|
|
|
3
3
|
/** Seam `TaskRunner` depends on, so tests can substitute a fake without spinning up real HTTP endpoints. */
|
|
4
4
|
export interface BlobResolver {
|
|
5
5
|
resolveInstruction(blobRef: BlobRef): Promise<string>;
|
|
6
|
-
uploadArtifact(content: string | Uint8Array, contentType: string
|
|
6
|
+
uploadArtifact(content: string | Uint8Array, contentType: string, options?: {
|
|
7
|
+
readonly idempotencyKey?: string;
|
|
8
|
+
}): Promise<BlobRef>;
|
|
7
9
|
}
|
|
8
10
|
/**
|
|
9
11
|
* HTTP-side blob transfer (protocol §7): resolving an instruction `blobRef`
|
|
@@ -18,5 +20,7 @@ export declare class BlobClient implements BlobResolver {
|
|
|
18
20
|
/** `blobRef` -> `GET /byok/blobs/:id/url` -> fetch the presigned download URL -> text content. Always resolves fresh rather than trusting any inlined `BlobRef.url`, per docs/protocol.md §7. */
|
|
19
21
|
resolveInstruction(blobRef: BlobRef): Promise<string>;
|
|
20
22
|
/** `POST /byok/blobs` (declares size/contentType/contentHash) -> PUT the bytes to the presigned upload URL -> a `BlobRef` for `task.artifact.blobRef`. */
|
|
21
|
-
uploadArtifact(content: string | Uint8Array, contentType: string
|
|
23
|
+
uploadArtifact(content: string | Uint8Array, contentType: string, options?: {
|
|
24
|
+
readonly idempotencyKey?: string;
|
|
25
|
+
}): Promise<BlobRef>;
|
|
22
26
|
}
|
|
@@ -9,9 +9,11 @@ export interface ConnectionManagerOptions {
|
|
|
9
9
|
deviceId: string;
|
|
10
10
|
productId: string;
|
|
11
11
|
capabilities: CapabilityFlag[];
|
|
12
|
+
/** U4a Local Agent release version; passed unchanged to both transports. */
|
|
13
|
+
clientVersion?: string;
|
|
12
14
|
runtimes: RuntimeInfo[];
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
+
/** Reads current sorted logical IDs from the validated local registry for every WS hello. */
|
|
16
|
+
getConfiguredToolsets?: () => readonly ToolsetId[];
|
|
15
17
|
auth: AuthManager;
|
|
16
18
|
cursorStore: CursorStore;
|
|
17
19
|
/**
|
|
@@ -3,6 +3,8 @@ import type { ApprovalDecision, PendingApproval } from './approvals';
|
|
|
3
3
|
import type { StorageCategory } from './journal/journal';
|
|
4
4
|
import type { StoragePressureState } from './journal/storage-policy';
|
|
5
5
|
import type { OperationalHealthSnapshot } from './operational-health';
|
|
6
|
+
import type { LocalAgentReleaseIdentity } from '../release-identity';
|
|
7
|
+
import type { McpToolsetConfig, McpToolsetRegistryStatus } from '../types';
|
|
6
8
|
/**
|
|
7
9
|
* M4 Phase 2: shared local-IPC contract between the daemon's control server
|
|
8
10
|
* (`control-server.ts`) and the CLI's control client (`bin/control-client.ts`)
|
|
@@ -244,6 +246,8 @@ export interface ControlStorageCompaction {
|
|
|
244
246
|
}
|
|
245
247
|
/** Result shape for the `status` method — see `create-daemon.ts`'s control-method wiring for how each field is sourced, and `bin/format.ts`'s `formatLiveStatusLines` for how the CLI renders it. */
|
|
246
248
|
export interface ControlStatusResult {
|
|
249
|
+
/** Process-immutable Local Agent application release; absent only for an older control peer. */
|
|
250
|
+
localAgentRelease?: Readonly<LocalAgentReleaseIdentity>;
|
|
247
251
|
pid: number;
|
|
248
252
|
uptimeMs: number;
|
|
249
253
|
paired: boolean;
|
|
@@ -270,7 +274,15 @@ export interface ControlStatusResult {
|
|
|
270
274
|
storage?: ControlStorageStatus;
|
|
271
275
|
/** Local lifecycle/retry budget. This is not the transport state above. */
|
|
272
276
|
operationalHealth: OperationalHealthSnapshot;
|
|
277
|
+
/** Redacted content-addressed status from the daemon's single local registry. */
|
|
278
|
+
toolsets: McpToolsetRegistryStatus;
|
|
273
279
|
}
|
|
280
|
+
export interface ToolsetsReloadParams {
|
|
281
|
+
expectedRevision: string;
|
|
282
|
+
mcpToolsets: Record<string, McpToolsetConfig>;
|
|
283
|
+
}
|
|
284
|
+
/** Shape-only parser; executable definition validation remains registry-owned. */
|
|
285
|
+
export declare function parseToolsetsReloadParams(value: unknown): ToolsetsReloadParams | undefined;
|
|
274
286
|
export interface ApprovalsListResult {
|
|
275
287
|
approvals: PendingApproval[];
|
|
276
288
|
}
|