@byok-sdk/client 0.8.0 → 0.9.0-rc.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 +22 -1
- package/dist/adapters/index.js +14 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/agent-home.d.ts +29 -4
- package/dist/bin/agent-memory-mcp-server.d.ts +38 -0
- package/dist/bin/agent-message-mcp-server.d.ts +24 -0
- package/dist/bin/byok-agent-memory-mcp.d.ts +2 -0
- package/dist/bin/byok-agent-memory-mcp.js +432 -0
- package/dist/bin/byok-agent-memory-mcp.js.map +1 -0
- package/dist/bin/byok-agent-message-mcp.d.ts +2 -0
- package/dist/bin/byok-agent-message-mcp.js +441 -0
- package/dist/bin/byok-agent-message-mcp.js.map +1 -0
- package/dist/bin/byok-agent.js +7808 -5492
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/bin/byok-approval-mcp.js.map +1 -1
- package/dist/bin/commands/pair.d.ts +3 -0
- package/dist/daemon/agent-memory-filesystem.d.ts +23 -0
- package/dist/daemon/agent-memory-fs-helper.d.ts +10 -0
- package/dist/daemon/agent-memory.d.ts +160 -0
- package/dist/daemon/agent-message-outbox.d.ts +58 -0
- package/dist/daemon/auth-manager.d.ts +8 -0
- package/dist/daemon/control-protocol.d.ts +36 -0
- package/dist/daemon/create-daemon.d.ts +29 -2
- package/dist/daemon/daemon-owner.d.ts +9 -0
- package/dist/daemon/device-credential-store.d.ts +58 -0
- package/dist/daemon/device-proof-signer.d.ts +5 -4
- package/dist/daemon/memory-guidance.d.ts +8 -0
- package/dist/daemon/path-mutation-gate.d.ts +25 -0
- package/dist/daemon/resolve-agent-memory-mcp-bin.d.ts +6 -0
- package/dist/daemon/resolve-agent-message-mcp-bin.d.ts +6 -0
- package/dist/daemon/store.d.ts +45 -24
- package/dist/daemon/task-runner.d.ts +88 -3
- package/dist/daemon/toolset-registry.d.ts +2 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +9976 -7469
- package/dist/index.js.map +1 -1
- package/dist/local-state-relocation.d.ts +24 -0
- package/dist/types.d.ts +2 -0
- package/package.json +7 -5
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type AgentMessageContentType, type AgentMessageEgressRequirement, type AgentMessagePublishPayload } from '@byok-sdk/protocol';
|
|
2
|
+
import type { AgentRef } from '../agent-home';
|
|
3
|
+
export declare const AGENT_MESSAGE_DIRECTORY: string;
|
|
4
|
+
export declare const AGENT_MESSAGE_OUTBOX_FILENAME = "outbox-v1.jsonl";
|
|
5
|
+
export interface AgentMessageOutboxRecord {
|
|
6
|
+
readonly schema: 1;
|
|
7
|
+
readonly taskId: string;
|
|
8
|
+
readonly tenantId: string;
|
|
9
|
+
readonly agentRef: AgentRef;
|
|
10
|
+
readonly contract: string;
|
|
11
|
+
readonly messageId: string;
|
|
12
|
+
readonly cursor: number;
|
|
13
|
+
readonly contentType: AgentMessageContentType;
|
|
14
|
+
readonly body: string;
|
|
15
|
+
readonly contentHash: string;
|
|
16
|
+
readonly byteCount: number;
|
|
17
|
+
readonly createdAt: string;
|
|
18
|
+
readonly sessionRef?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class AgentMessageOutboxError extends Error {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
/** Agent-local, append-before-send outbox. Only exact accepted disposition retires bytes. */
|
|
24
|
+
export declare class AgentMessageOutbox {
|
|
25
|
+
readonly homeDir: string;
|
|
26
|
+
readonly outboxPath: string;
|
|
27
|
+
private readonly pendingByTask;
|
|
28
|
+
private readonly dispositionByTask;
|
|
29
|
+
private nextCursor;
|
|
30
|
+
private logEntries;
|
|
31
|
+
private writeTail;
|
|
32
|
+
private constructor();
|
|
33
|
+
static open(homeDir: string): Promise<AgentMessageOutbox>;
|
|
34
|
+
/** Re-open every existing Agent-local message outbox without following Agent-home symlinks. */
|
|
35
|
+
static recover(agentsRoot: string, tenantId: string): Promise<readonly AgentMessageOutbox[]>;
|
|
36
|
+
records(): readonly AgentMessageOutboxRecord[];
|
|
37
|
+
/** Activated records with no exact disposition yet; only these may be transport-replayed. */
|
|
38
|
+
retryableRecords(): readonly AgentMessageOutboxRecord[];
|
|
39
|
+
get(taskId: string): AgentMessageOutboxRecord | undefined;
|
|
40
|
+
appendDraft(input: {
|
|
41
|
+
readonly taskId: string;
|
|
42
|
+
readonly tenantId: string;
|
|
43
|
+
readonly agentRef: AgentRef;
|
|
44
|
+
readonly requirement: AgentMessageEgressRequirement;
|
|
45
|
+
readonly contentType: AgentMessageContentType;
|
|
46
|
+
readonly body: string;
|
|
47
|
+
readonly sessionRef?: string;
|
|
48
|
+
readonly maxPendingEvents: number;
|
|
49
|
+
readonly maxPendingBytes: number;
|
|
50
|
+
}): Promise<AgentMessageOutboxRecord>;
|
|
51
|
+
activate(taskId: string, sessionRef: string): Promise<AgentMessageOutboxRecord | undefined>;
|
|
52
|
+
publishPayload(record: AgentMessageOutboxRecord): AgentMessagePublishPayload;
|
|
53
|
+
applyDisposition(taskId: string, input: unknown): Promise<'accepted' | 'held' | 'refused' | 'mismatch' | 'unknown'>;
|
|
54
|
+
private load;
|
|
55
|
+
private appendEntry;
|
|
56
|
+
private compact;
|
|
57
|
+
private exclusive;
|
|
58
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DeviceStore, type DeviceRecord } from './store';
|
|
2
|
+
import type { DeviceCredentialStore, InMemoryDeviceCredentialStore } from './device-credential-store';
|
|
2
3
|
/**
|
|
3
4
|
* Thrown when the server has revoked this device: a 401 on `/byok/challenge`
|
|
4
5
|
* or `/byok/token` (protocol §6.3). The only recourse is a fresh
|
|
@@ -11,6 +12,8 @@ export declare class DeviceRevokedError extends Error {
|
|
|
11
12
|
export interface AuthManagerOptions {
|
|
12
13
|
serverUrl: string;
|
|
13
14
|
store: DeviceStore;
|
|
15
|
+
/** Internal-only credential custody seam. Product construction uses store.credentials. */
|
|
16
|
+
credentials?: DeviceCredentialStore | InMemoryDeviceCredentialStore;
|
|
14
17
|
deviceName?: string;
|
|
15
18
|
/** Called once revocation is detected, so a caller (ConnectionManager) can stop retrying and surface the state instead of looping. */
|
|
16
19
|
onRevoked?: () => void;
|
|
@@ -31,9 +34,12 @@ export declare class AuthManager {
|
|
|
31
34
|
private stopped;
|
|
32
35
|
private pairing;
|
|
33
36
|
private credentialMutationTail;
|
|
37
|
+
private readonly credentials;
|
|
34
38
|
constructor(opts: AuthManagerOptions);
|
|
35
39
|
get deviceId(): string | undefined;
|
|
36
40
|
isRevoked(): boolean;
|
|
41
|
+
/** Internal signer read: always recompose metadata with the current OS secret authority. */
|
|
42
|
+
readCurrent(): Promise<DeviceRecord | undefined>;
|
|
37
43
|
/** Load a previously-paired device record from disk, if any (idempotent — a second call is a no-op once loaded). */
|
|
38
44
|
loadExisting(): Promise<DeviceRecord | undefined>;
|
|
39
45
|
/** `POST /byok/pair` (v2): generates a device keypair on first pair, reuses it on any subsequent (e.g. post-revocation) re-pair. */
|
|
@@ -49,4 +55,6 @@ export declare class AuthManager {
|
|
|
49
55
|
private markRevoked;
|
|
50
56
|
private scheduleProactiveRenewal;
|
|
51
57
|
private runCredentialMutation;
|
|
58
|
+
/** Read the current paired authority afresh; metadata without its OS secret is re-pair required. */
|
|
59
|
+
private loadRecord;
|
|
52
60
|
}
|
|
@@ -281,6 +281,17 @@ export interface ToolsetsReloadParams {
|
|
|
281
281
|
expectedRevision: string;
|
|
282
282
|
mcpToolsets: Record<string, McpToolsetConfig>;
|
|
283
283
|
}
|
|
284
|
+
/** Maximum opaque pairing-code payload accepted over local control IPC. */
|
|
285
|
+
export declare const ENROLLMENT_PAIRING_CODE_MAX_BYTES = 1024;
|
|
286
|
+
export interface EnrollmentPairParams {
|
|
287
|
+
pairingCode: string;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Exact shape gate for service-identity pairing. The code is opaque server
|
|
291
|
+
* authority: this only bounds transport bytes and rejects unknown fields; it
|
|
292
|
+
* never parses, normalizes or logs the code.
|
|
293
|
+
*/
|
|
294
|
+
export declare function parseEnrollmentPairParams(value: unknown): EnrollmentPairParams | undefined;
|
|
284
295
|
/** Shape-only parser; executable definition validation remains registry-owned. */
|
|
285
296
|
export declare function parseToolsetsReloadParams(value: unknown): ToolsetsReloadParams | undefined;
|
|
286
297
|
export interface ApprovalsListResult {
|
|
@@ -312,6 +323,31 @@ export interface ApprovalsRequestResult {
|
|
|
312
323
|
approved: boolean;
|
|
313
324
|
reason?: string;
|
|
314
325
|
}
|
|
326
|
+
export interface AgentMessagePublishParams {
|
|
327
|
+
contextToken: string;
|
|
328
|
+
contentType: 'text/plain' | 'text/markdown';
|
|
329
|
+
body: string;
|
|
330
|
+
}
|
|
331
|
+
export declare function parseAgentMessagePublishParams(value: unknown): AgentMessagePublishParams | undefined;
|
|
332
|
+
export interface AgentMessagePublishResult {
|
|
333
|
+
messageId: string;
|
|
334
|
+
state: 'staged' | 'pending';
|
|
335
|
+
}
|
|
336
|
+
export interface AgentMemoryRecallParams {
|
|
337
|
+
contextToken: string;
|
|
338
|
+
path: string;
|
|
339
|
+
ifRevision?: string;
|
|
340
|
+
}
|
|
341
|
+
export interface AgentMemorySaveParams {
|
|
342
|
+
contextToken: string;
|
|
343
|
+
op: 'replace' | 'delete';
|
|
344
|
+
path: string;
|
|
345
|
+
expectedRevision: string;
|
|
346
|
+
content?: string;
|
|
347
|
+
}
|
|
348
|
+
/** Parser only validates the local IPC shape. Agent identity and memory root stay daemon-owned. */
|
|
349
|
+
export declare function parseAgentMemoryRecallParams(value: unknown): AgentMemoryRecallParams | undefined;
|
|
350
|
+
export declare function parseAgentMemorySaveParams(value: unknown): AgentMemorySaveParams | undefined;
|
|
315
351
|
/**
|
|
316
352
|
* Params for `assertion.issue`: a sibling local process (the host's own CLI,
|
|
317
353
|
* installed alongside this daemon) asking the daemon to mint one short-lived,
|
|
@@ -9,7 +9,7 @@ import { type OperationalHealthSnapshot } from './operational-health';
|
|
|
9
9
|
import { type DaemonEventListener, type DaemonTaskInfo, type Unsubscribe } from './observer';
|
|
10
10
|
import { GitWorkspaceManager } from './git-workspace';
|
|
11
11
|
import { GitWorkspaceStore } from './git-workspace-store';
|
|
12
|
-
import { type
|
|
12
|
+
import { type DeviceEnrollment } from './store';
|
|
13
13
|
import { type LocalTaskJournal } from './journal/journal';
|
|
14
14
|
import { type JournalOpenFaultSeam } from './journal/sqlite-support';
|
|
15
15
|
import { LocalStoragePressureEngine, type LocalStoragePolicyInput } from './journal/storage-policy';
|
|
@@ -18,6 +18,8 @@ import { type ProgressBatcherOptions } from './progress-batcher';
|
|
|
18
18
|
import { type AgentEgressReliableAppendResult } from './agent-egress-controller';
|
|
19
19
|
import { type AgentEgressStatus } from './agent-egress-policy';
|
|
20
20
|
import { type AgentEgressSanitizer } from './agent-egress-sanitizer';
|
|
21
|
+
import { type AgentMemoryHostedProjection } from './agent-memory';
|
|
22
|
+
import type { AgentMemoryFilesystemHelperConfig } from './agent-memory-filesystem';
|
|
21
23
|
import { type AgentContentReadRoot } from './agent-content-read';
|
|
22
24
|
/**
|
|
23
25
|
* Optional white-label product display info — purely opaque passthrough
|
|
@@ -100,6 +102,19 @@ export interface DaemonConfig {
|
|
|
100
102
|
hostStorageRoot: string;
|
|
101
103
|
projection?: AgentHomeProjection;
|
|
102
104
|
};
|
|
105
|
+
/** Optional, one-way hosted projection. Without all guards it has zero network activity. */
|
|
106
|
+
agentMemory?: AgentMemoryHostedProjection;
|
|
107
|
+
/**
|
|
108
|
+
* Product-owned external secure-filesystem helper. The path must be absolute;
|
|
109
|
+
* the SDK never searches PATH or bundles a native addon. Required for Phase
|
|
110
|
+
* 2 on macOS. Windows remains fail-closed pending its native race proof.
|
|
111
|
+
*/
|
|
112
|
+
agentMemoryFilesystem?: AgentMemoryFilesystemHelperConfig;
|
|
113
|
+
/**
|
|
114
|
+
* Refuse legacy task offers locally. This is an additive capability only
|
|
115
|
+
* after the SDK-owned Agent home has passed construction-time preflight.
|
|
116
|
+
*/
|
|
117
|
+
strictAgentOnly?: boolean;
|
|
103
118
|
/**
|
|
104
119
|
* Explicit Agent-local/cloud egress selection. Omission still enforces the
|
|
105
120
|
* SDK metadata/status projection, but does not advertise or admit the new
|
|
@@ -188,6 +203,17 @@ export interface DaemonConfig {
|
|
|
188
203
|
*/
|
|
189
204
|
permissionDefaults?: PermissionPolicy;
|
|
190
205
|
storeDir?: string;
|
|
206
|
+
/**
|
|
207
|
+
* Opt-in host composition for a daemon launched under a different OS
|
|
208
|
+
* principal than the interactive CLI (notably a WinSW service). When true,
|
|
209
|
+
* an unpaired daemon holds the normal writer lease and exposes only the
|
|
210
|
+
* existing HMAC-authenticated local control surface so `enrollment.pair`
|
|
211
|
+
* can persist the credential under the daemon's own OS token. Absent by
|
|
212
|
+
* default: ordinary foreground `start()` keeps rejecting an unpaired device.
|
|
213
|
+
*/
|
|
214
|
+
serviceEnrollment?: {
|
|
215
|
+
readonly enabled: true;
|
|
216
|
+
};
|
|
191
217
|
/** Optional white-label branding — see `DaemonBranding`. Carried through verbatim to `status().branding`. */
|
|
192
218
|
branding?: DaemonBranding;
|
|
193
219
|
/**
|
|
@@ -448,7 +474,8 @@ export interface DaemonStatus {
|
|
|
448
474
|
egress: AgentEgressStatus;
|
|
449
475
|
}
|
|
450
476
|
export interface Daemon {
|
|
451
|
-
|
|
477
|
+
/** Pairing result is intentionally credential-blind. */
|
|
478
|
+
pair(pairingCode: string): Promise<DeviceEnrollment>;
|
|
452
479
|
start(): Promise<void>;
|
|
453
480
|
stop(): Promise<void>;
|
|
454
481
|
status(): DaemonStatus;
|
|
@@ -52,6 +52,15 @@ export declare class DaemonOwnerActiveError extends Error {
|
|
|
52
52
|
readonly role: OwnerRecord['role'] | 'unknown';
|
|
53
53
|
constructor(role: OwnerRecord['role'] | 'unknown');
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Read-only relocation inspection. The caller must already hold this store's
|
|
57
|
+
* path-mutation gate, so a conforming writer cannot publish after this check.
|
|
58
|
+
* Any persisted owner or reclaim object is a refusal; relocation never
|
|
59
|
+
* reclaims crash residue or repairs SDK-private state.
|
|
60
|
+
*
|
|
61
|
+
* @internal Used only by the high-level local-state relocation coordinator.
|
|
62
|
+
*/
|
|
63
|
+
export declare function assertDaemonStoreQuiescent(storeDir: string): Promise<void>;
|
|
55
64
|
/**
|
|
56
65
|
* Cross-process, fail-closed ownership for store mutations that must never
|
|
57
66
|
* race a daemon. A separate exclusive reclaim file serializes stale-owner recovery so two
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Secret fields inside the internal complete enrollment authority. */
|
|
2
|
+
export interface DeviceCredentials {
|
|
3
|
+
readonly accessToken: string;
|
|
4
|
+
readonly expiresAt: string;
|
|
5
|
+
readonly devicePrivateKeyPem: string;
|
|
6
|
+
}
|
|
7
|
+
/** Non-secret deterministic projection of the authenticated enrollment. */
|
|
8
|
+
export interface DeviceMetadata {
|
|
9
|
+
readonly deviceId: string;
|
|
10
|
+
readonly tenantId: string;
|
|
11
|
+
readonly devicePublicKey: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The single local enrollment authority. Keeping identity and credential
|
|
15
|
+
* bytes in one OS-managed entry prevents a crash from composing a token/key
|
|
16
|
+
* from one pairing response with metadata from another.
|
|
17
|
+
*/
|
|
18
|
+
export type DeviceRecord = DeviceMetadata & DeviceCredentials;
|
|
19
|
+
export interface DeviceCommandResult {
|
|
20
|
+
readonly exitCode: number;
|
|
21
|
+
readonly stdout: string;
|
|
22
|
+
readonly stderr: string;
|
|
23
|
+
}
|
|
24
|
+
export type DeviceCommandRunner = (executable: string, args: readonly string[], stdin?: string) => Promise<DeviceCommandResult>;
|
|
25
|
+
/** Typed unavailability; callers must surface re-pair/operational failure, never write a file fallback. */
|
|
26
|
+
export declare class DeviceCredentialStoreUnavailableError extends Error {
|
|
27
|
+
constructor(message?: string);
|
|
28
|
+
}
|
|
29
|
+
export declare class DeviceCredentialStoreError extends Error {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
export interface DeviceCredentialStoreOptions {
|
|
33
|
+
readonly productId: string;
|
|
34
|
+
readonly platform?: NodeJS.Platform;
|
|
35
|
+
readonly commandRunner?: DeviceCommandRunner;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Internal OS-backed authority for the bearer token and device private key.
|
|
39
|
+
* The constructor deliberately accepts no path or backend selector: real
|
|
40
|
+
* callers get the platform provider; tests import this internal module and
|
|
41
|
+
* inject a double directly.
|
|
42
|
+
*/
|
|
43
|
+
export declare class DeviceCredentialStore {
|
|
44
|
+
#private;
|
|
45
|
+
constructor(options: DeviceCredentialStoreOptions);
|
|
46
|
+
read(): Promise<DeviceRecord | undefined>;
|
|
47
|
+
replace(record: DeviceRecord): Promise<void>;
|
|
48
|
+
/** Returns true only after the sole secret authority is confirmed absent. */
|
|
49
|
+
clear(): Promise<boolean>;
|
|
50
|
+
}
|
|
51
|
+
/** Test-only double; it is intentionally internal and never selected by a production config. */
|
|
52
|
+
export declare class InMemoryDeviceCredentialStore {
|
|
53
|
+
#private;
|
|
54
|
+
read(): Promise<DeviceRecord | undefined>;
|
|
55
|
+
replace(record: DeviceRecord): Promise<void>;
|
|
56
|
+
clear(): Promise<boolean>;
|
|
57
|
+
}
|
|
58
|
+
export declare function runDeviceCommand(executable: string, args: readonly string[], stdin?: string): Promise<DeviceCommandResult>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DeviceProofEnvelopeV1 } from '@byok-sdk/core';
|
|
2
|
-
import type {
|
|
2
|
+
import type { AuthManager } from './auth-manager';
|
|
3
3
|
export interface DeviceProofRequest {
|
|
4
4
|
readonly method: string;
|
|
5
5
|
/** Exact origin-relative path, including the query string when present. */
|
|
@@ -17,7 +17,7 @@ export interface DeviceProofSigner {
|
|
|
17
17
|
sign(request: DeviceProofRequest): Promise<DeviceProofEnvelopeV1>;
|
|
18
18
|
}
|
|
19
19
|
export interface StoredDeviceProofSignerOptions {
|
|
20
|
-
readonly
|
|
20
|
+
readonly auth: Pick<AuthManager, 'readCurrent'>;
|
|
21
21
|
/** Explicit host configuration. Pairing/bearer state is never mined for tenant identity. */
|
|
22
22
|
readonly tenantId: string;
|
|
23
23
|
readonly productId: string;
|
|
@@ -28,8 +28,9 @@ export interface StoredDeviceProofSignerOptions {
|
|
|
28
28
|
/**
|
|
29
29
|
* Signs request-bound S6 proofs with the paired device identity key.
|
|
30
30
|
*
|
|
31
|
-
* The
|
|
32
|
-
*
|
|
31
|
+
* The authenticated enrollment authority is read for every signature rather
|
|
32
|
+
* than cached: clearing the OS credential immediately removes local signing
|
|
33
|
+
* authority. Canonicalization is
|
|
33
34
|
* imported from `@byok-sdk/core`, the one frozen byte authority; this module only
|
|
34
35
|
* supplies the Node Ed25519 operation.
|
|
35
36
|
*/
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral instructions for an Agent's model-authored local memory.
|
|
3
|
+
*
|
|
4
|
+
* This is deliberately prompt guidance only: the SDK does not read memory
|
|
5
|
+
* content, infer durable values, or auto-inject files into the operation.
|
|
6
|
+
*/
|
|
7
|
+
export declare const AGENT_MEMORY_GUIDANCE: string;
|
|
8
|
+
export declare function prependAgentMemoryGuidance(instruction: string): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type PathMutationGateScope = 'store' | 'agent-home-root';
|
|
2
|
+
export interface PathMutationGateInput {
|
|
3
|
+
readonly scope: PathMutationGateScope;
|
|
4
|
+
readonly targetPath: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PathMutationGateAcquireOptions {
|
|
7
|
+
/** Bounded wait for another conforming short-lived writer; relocation uses zero. */
|
|
8
|
+
readonly waitMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface PathMutationGate {
|
|
11
|
+
readonly scope: PathMutationGateScope;
|
|
12
|
+
readonly targetPath: string;
|
|
13
|
+
readonly identity: string;
|
|
14
|
+
release(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export declare class PathMutationGateBusyError extends Error {
|
|
17
|
+
readonly scope: PathMutationGateScope;
|
|
18
|
+
readonly targetPath: string;
|
|
19
|
+
constructor(scope: PathMutationGateScope, targetPath: string);
|
|
20
|
+
}
|
|
21
|
+
/** Canonicalize through the deepest existing ancestor without creating the target. */
|
|
22
|
+
export declare function resolvePathWithoutCreate(input: string): Promise<string>;
|
|
23
|
+
/** Acquire multiple path gates in one deterministic order to prevent deadlock. */
|
|
24
|
+
export declare function acquirePathMutationGates(inputs: readonly PathMutationGateInput[]): Promise<readonly PathMutationGate[]>;
|
|
25
|
+
export declare function acquirePathMutationGate(input: PathMutationGateInput, options?: PathMutationGateAcquireOptions): Promise<PathMutationGate>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface ResolvedAgentMemoryMcpBin {
|
|
2
|
+
readonly command: string;
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
/** Resolve the SDK-owned stdio Agent-memory MCP helper shipped beside the client bundle. */
|
|
6
|
+
export declare function resolveAgentMemoryMcpBin(externalHelperConfigured?: boolean): ResolvedAgentMemoryMcpBin | undefined;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface ResolvedAgentMessageMcpBin {
|
|
2
|
+
readonly command: string;
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
/** Resolve the SDK-owned stdio MCP helper shipped beside the client bundle. */
|
|
6
|
+
export declare function resolveAgentMessageMcpBin(): ResolvedAgentMessageMcpBin;
|
package/dist/daemon/store.d.ts
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import { type EnsureSecureDirOptions } from '../util/secure-dir';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
import { DeviceCredentialStore, InMemoryDeviceCredentialStore, type DeviceMetadata } from './device-credential-store';
|
|
3
|
+
export type { DeviceMetadata, DeviceRecord } from './device-credential-store';
|
|
4
|
+
/**
|
|
5
|
+
* Non-secret projection of an authenticated device enrollment. This is the
|
|
6
|
+
* complete permitted `device.json` shape. The complete record, including
|
|
7
|
+
* these authenticated metadata fields and secret bytes, lives atomically in
|
|
8
|
+
* DeviceCredentialStore; this file is only its deterministic projection.
|
|
9
|
+
*
|
|
10
|
+
* Internal only: the package root exposes DeviceEnrollment/status, never this
|
|
11
|
+
* storage record.
|
|
12
|
+
*/
|
|
13
|
+
/** Public credential-blind result of explicit pairing. */
|
|
14
|
+
export interface DeviceEnrollment {
|
|
15
|
+
readonly deviceId: string;
|
|
16
|
+
}
|
|
17
|
+
export interface DeviceEnrollmentStatusOptions {
|
|
18
|
+
productId: string;
|
|
19
|
+
storeDir?: string;
|
|
14
20
|
}
|
|
21
|
+
/** Credential-blind cold read model for host setup and diagnostics. */
|
|
22
|
+
export type DeviceEnrollmentStatus = {
|
|
23
|
+
state: 'unpaired';
|
|
24
|
+
} | {
|
|
25
|
+
state: 'paired';
|
|
26
|
+
deviceId: string;
|
|
27
|
+
} | {
|
|
28
|
+
state: 're_pair_required';
|
|
29
|
+
};
|
|
15
30
|
/**
|
|
16
31
|
* A durable enrollment record cannot be used by any steady-state path. Only
|
|
17
32
|
* the explicit pair operation may replace it with a fresh authenticated row.
|
|
@@ -20,17 +35,17 @@ export declare class DeviceRecordRePairRequiredError extends Error {
|
|
|
20
35
|
constructor();
|
|
21
36
|
}
|
|
22
37
|
/**
|
|
23
|
-
* Persists
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* runtime's own credentials (see the credential-isolation rule on
|
|
27
|
-
* `RuntimeAdapter`). Stored 0600 under `storeDir` (default
|
|
28
|
-
* `~/.byok/<productId>/`); OS keychain storage is deferred (tracked as a
|
|
29
|
-
* future roadmap item, not promised for any specific milestone).
|
|
38
|
+
* Persists only bounded non-secret enrollment projection. The paired bearer
|
|
39
|
+
* token and private key are never accepted here and are owned by the internal
|
|
40
|
+
* OS DeviceCredentialStore.
|
|
30
41
|
*/
|
|
31
42
|
export declare class DeviceStore {
|
|
32
43
|
private readonly secureDirOptions?;
|
|
44
|
+
/** Process-local keyed doubles preserve restart semantics in isolated tests. */
|
|
45
|
+
private static readonly testCredentials;
|
|
33
46
|
private readonly filePath;
|
|
47
|
+
/** Internal test seam. Product construction always supplies productId and gets an OS store. */
|
|
48
|
+
readonly credentials: DeviceCredentialStore | InMemoryDeviceCredentialStore;
|
|
34
49
|
/**
|
|
35
50
|
* `secureDirOptions` is a test-only DI seam (mirrors `EnsureSecureDirOptions`'s
|
|
36
51
|
* own `run`/`platform` overrides) — every real caller omits it, getting
|
|
@@ -41,7 +56,7 @@ export declare class DeviceStore {
|
|
|
41
56
|
* ACL-unprotected credential") is verifiable from a real `darwin`/`linux`
|
|
42
57
|
* CI/dev machine, not just asserted.
|
|
43
58
|
*/
|
|
44
|
-
constructor(storeDir: string, secureDirOptions?: EnsureSecureDirOptions | undefined);
|
|
59
|
+
constructor(storeDir: string, secureDirOptions?: EnsureSecureDirOptions | undefined, productId?: string);
|
|
45
60
|
static defaultDir(productId: string): string;
|
|
46
61
|
/**
|
|
47
62
|
* Resolve the one store pathname every daemon/CLI component must share.
|
|
@@ -50,14 +65,20 @@ export declare class DeviceStore {
|
|
|
50
65
|
* cwd to pin a quarantine directory inode.
|
|
51
66
|
*/
|
|
52
67
|
static resolveDir(productId: string, configured?: string): string;
|
|
53
|
-
load(): Promise<
|
|
68
|
+
load(): Promise<DeviceMetadata | undefined>;
|
|
54
69
|
/**
|
|
55
70
|
* Read and remove the exact bounded, no-follow device record under the
|
|
56
71
|
* caller's mutation lease. The hard-link guard keeps the inspected inode
|
|
57
72
|
* identifiable until the synchronous pathname check and unlink complete.
|
|
58
73
|
*/
|
|
59
|
-
remove(): Promise<
|
|
60
|
-
save(record:
|
|
61
|
-
clear(): Promise<void>;
|
|
74
|
+
remove(): Promise<DeviceMetadata | undefined>;
|
|
75
|
+
save(record: DeviceMetadata): Promise<void>;
|
|
62
76
|
private openBounded;
|
|
63
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Read the canonical device store without projecting credential or tenant
|
|
80
|
+
* material. A legacy/tampered record remains distinct from an absent record so
|
|
81
|
+
* hosts can require explicit re-pair instead of silently changing semantics.
|
|
82
|
+
* Filesystem and pathname-safety failures intentionally remain errors.
|
|
83
|
+
*/
|
|
84
|
+
export declare function readDeviceEnrollmentStatus(options: DeviceEnrollmentStatusOptions): Promise<DeviceEnrollmentStatus>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentEgressPolicy, type Envelope, type PermissionPolicy, type RuntimeId, type TaskOfferPayload, type TaskOfferForAgentPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferForAgentWithEgressFreshPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
|
|
1
|
+
import { type AgentMessageContentType, type AgentEgressPolicy, type Envelope, type PermissionPolicy, type RuntimeId, type TerminalProjectionSelection, type TaskOfferPayload, type TaskOfferForAgentPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferForAgentWithEgressFreshPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
|
|
2
2
|
import { type McpToolsetConfig, type RuntimeAdapter } from '../types';
|
|
3
3
|
import { AgentHomeManager, type AgentRef } from '../agent-home';
|
|
4
4
|
import { AgentSessionHandoffStore, type AgentTerminalCause } from './agent-session-handoff-store';
|
|
@@ -12,6 +12,9 @@ import type { SessionWorkspaceStore } from './session-workspace-store';
|
|
|
12
12
|
import type { GitWorkspaceManager, GitWorkspaceObservation } from './git-workspace';
|
|
13
13
|
import type { GitWorkspaceStore, GitWorkspacePhase } from './git-workspace-store';
|
|
14
14
|
import type { AgentEgressController } from './agent-egress-controller';
|
|
15
|
+
import type { ResolvedAgentMessageMcpBin } from './resolve-agent-message-mcp-bin';
|
|
16
|
+
import type { ResolvedAgentMemoryMcpBin } from './resolve-agent-memory-mcp-bin';
|
|
17
|
+
import { type AgentMemoryAuditWarning, type AgentMemoryHostedProjection } from './agent-memory';
|
|
15
18
|
/**
|
|
16
19
|
* M4 Phase 3: default wait for `requestApproval` (see its own doc comment)
|
|
17
20
|
* before force-resolving an unanswered out-of-band approval as a fail-closed
|
|
@@ -138,12 +141,15 @@ export declare const RESULT_DOCUMENT_UNDELIVERABLE_REASON_PREFIX = "result docum
|
|
|
138
141
|
export interface ResultDocumentTask {
|
|
139
142
|
readonly taskId: string;
|
|
140
143
|
readonly sessionRef: string;
|
|
144
|
+
/** Exact offer-scoped second projection; absent for legacy and message-only offers. */
|
|
145
|
+
readonly terminalProjection?: Readonly<TerminalProjectionSelection>;
|
|
141
146
|
}
|
|
142
147
|
/**
|
|
143
148
|
* Host-supplied glue that turns a finished task's final output into the
|
|
144
149
|
* product's structured terminal result (`task.complete.document`). Returning
|
|
145
|
-
* `undefined` means "this task has no structured result"
|
|
146
|
-
*
|
|
150
|
+
* `undefined` means "this task has no structured result" for legacy offers.
|
|
151
|
+
* An explicit `terminalProjection.mode: 'result-document'` instead treats
|
|
152
|
+
* `undefined` as a fail-closed missing required document.
|
|
147
153
|
*
|
|
148
154
|
* SYNCHRONOUS by contract, like every other single-purpose callback on
|
|
149
155
|
* `TaskRunnerDeps`, and the runtime ENFORCES that rather than trusting it:
|
|
@@ -195,6 +201,8 @@ export interface TaskRunnerDeps {
|
|
|
195
201
|
workspaceRoot: string;
|
|
196
202
|
/** Strict Agent offer authority. Absent means legacy offers never resolve an Agent home. */
|
|
197
203
|
agentHome?: AgentHomeManager;
|
|
204
|
+
/** Local authority: legacy offers are declined after journal/dedup/cancel precedence. */
|
|
205
|
+
strictAgentOnly?: boolean;
|
|
198
206
|
/** Exact host-selected policy accepted by `task.offer_for_agent_with_egress`. */
|
|
199
207
|
agentEgressPolicy?: Readonly<AgentEgressPolicy>;
|
|
200
208
|
/** Always-present projection/sanitizer consumer; it defaults to metadata-only. */
|
|
@@ -256,6 +264,8 @@ export interface TaskRunnerDeps {
|
|
|
256
264
|
approvalRegistry: ApprovalRegistry;
|
|
257
265
|
storeDir: string;
|
|
258
266
|
productId: string;
|
|
267
|
+
/** Authenticated enrollment tenant projection; required by Agent message durability/recovery. */
|
|
268
|
+
tenantId?: string;
|
|
259
269
|
/**
|
|
260
270
|
* The already-resolved, process-immutable U4a Local Agent release identity.
|
|
261
271
|
* `TaskRunner` only consumes this value; it never creates, normalizes, or
|
|
@@ -357,6 +367,14 @@ export interface TaskRunnerDeps {
|
|
|
357
367
|
resultDocument?: {
|
|
358
368
|
readonly extract: ResultDocumentExtractor;
|
|
359
369
|
};
|
|
370
|
+
/** SDK-owned, task-scoped MCP helper. Required only for offers declaring messageEgress. */
|
|
371
|
+
agentMessageMcpBin?: Readonly<ResolvedAgentMessageMcpBin>;
|
|
372
|
+
/** SDK-owned MCP helper injected only into strict Agent tasks. */
|
|
373
|
+
agentMemoryMcpBin?: Readonly<ResolvedAgentMemoryMcpBin>;
|
|
374
|
+
/** Explicit external secure-fs helper. No PATH discovery or bundled native addon exists. */
|
|
375
|
+
agentMemoryFilesystemHelperBin?: string;
|
|
376
|
+
/** Optional local-to-hosted redacted projection port. Omission is zero-network. */
|
|
377
|
+
agentMemoryHostedProjection?: AgentMemoryHostedProjection;
|
|
360
378
|
}
|
|
361
379
|
/** See {@link TaskRunnerDeps.admissionGuard}. */
|
|
362
380
|
export type AdmissionGuardDecision = {
|
|
@@ -385,6 +403,16 @@ type AcceptedOfferPayload = TaskOfferPayload | TaskOfferWithToolsetsPayload | Ta
|
|
|
385
403
|
export declare class TaskRunner {
|
|
386
404
|
private readonly deps;
|
|
387
405
|
private readonly tasks;
|
|
406
|
+
private readonly pendingMessageTasks;
|
|
407
|
+
private readonly messageContextByToken;
|
|
408
|
+
private readonly messageContextByTask;
|
|
409
|
+
private readonly memoryContextByToken;
|
|
410
|
+
private readonly memoryContextByTask;
|
|
411
|
+
private readonly memoryInFlightByTask;
|
|
412
|
+
private readonly memoryClosingTasks;
|
|
413
|
+
private readonly memoryFilesystemByTask;
|
|
414
|
+
private readonly recoveredMessageOutboxes;
|
|
415
|
+
private readonly recoveredMessageRetryTimers;
|
|
388
416
|
/**
|
|
389
417
|
* Finding F4 (cancel lost during the offer-processing window): a
|
|
390
418
|
* `task.cancel` for a taskId that hasn't finished `handleOffer` yet (still
|
|
@@ -479,6 +507,12 @@ export declare class TaskRunner {
|
|
|
479
507
|
* cancellation intent.
|
|
480
508
|
*/
|
|
481
509
|
private readonly finishedTaskIds;
|
|
510
|
+
/**
|
|
511
|
+
* Bounded local receive dedup for strict legacy declines. A decline is not a
|
|
512
|
+
* task terminal receipt, so it must never enter `finishedTaskIds`; retaining
|
|
513
|
+
* it separately keeps replay idempotent without claiming or finishing work.
|
|
514
|
+
*/
|
|
515
|
+
private readonly strictDeclinedTaskIds;
|
|
482
516
|
/**
|
|
483
517
|
* M4 Phase 2 (daemon control socket `shutdown` RPC): set once by
|
|
484
518
|
* {@link stopAcceptingOffers}, checked at the very top of `handleOffer` —
|
|
@@ -507,6 +541,44 @@ export declare class TaskRunner {
|
|
|
507
541
|
* approval count, not the adapter's own event-queue depth.
|
|
508
542
|
*/
|
|
509
543
|
getQueueWatermarks(): TaskQueueWatermark[];
|
|
544
|
+
/** Authenticated control-socket entry used only by the SDK-owned task MCP helper. */
|
|
545
|
+
publishAgentMessage(input: {
|
|
546
|
+
readonly contextToken: string;
|
|
547
|
+
readonly contentType: AgentMessageContentType;
|
|
548
|
+
readonly body: string;
|
|
549
|
+
}): Promise<{
|
|
550
|
+
messageId: string;
|
|
551
|
+
state: 'staged' | 'pending';
|
|
552
|
+
}>;
|
|
553
|
+
/** Authenticated control-socket entry used only by the SDK-owned memory MCP helper. */
|
|
554
|
+
recallAgentMemory(input: {
|
|
555
|
+
readonly contextToken: string;
|
|
556
|
+
readonly path: string;
|
|
557
|
+
readonly ifRevision?: string;
|
|
558
|
+
}): Promise<{
|
|
559
|
+
path: string;
|
|
560
|
+
revision: string;
|
|
561
|
+
content: string;
|
|
562
|
+
auditWarning?: AgentMemoryAuditWarning;
|
|
563
|
+
}>;
|
|
564
|
+
/** Authenticated control-socket entry used only by the SDK-owned memory MCP helper. */
|
|
565
|
+
saveAgentMemory(input: {
|
|
566
|
+
readonly contextToken: string;
|
|
567
|
+
readonly op: 'replace' | 'delete';
|
|
568
|
+
readonly path: string;
|
|
569
|
+
readonly expectedRevision: string;
|
|
570
|
+
readonly content?: string;
|
|
571
|
+
}): Promise<{
|
|
572
|
+
path: string;
|
|
573
|
+
revision?: string;
|
|
574
|
+
deleted: boolean;
|
|
575
|
+
}>;
|
|
576
|
+
/** Restore activated, unaccepted message drafts before transport admission on daemon restart. */
|
|
577
|
+
recoverAgentMessageOutboxes(agentsRoot: string): Promise<void>;
|
|
578
|
+
/** Retry stable recovered records after a transport handshake/re-handshake. */
|
|
579
|
+
retryRecoveredAgentMessages(): void;
|
|
580
|
+
private sendAgentMessageRecord;
|
|
581
|
+
private handleAgentMessageDisposition;
|
|
510
582
|
/** M4 Phase 2: stop claiming any FUTURE `task.offer` — see `stoppingOffers`'s own doc comment. Idempotent. */
|
|
511
583
|
stopAcceptingOffers(): void;
|
|
512
584
|
/**
|
|
@@ -612,11 +684,23 @@ export declare class TaskRunner {
|
|
|
612
684
|
private armMaxDurationTimer;
|
|
613
685
|
handleEnvelope(envelope: Envelope): Promise<void>;
|
|
614
686
|
private handleOffer;
|
|
687
|
+
private withAgentMessageMcp;
|
|
688
|
+
private revokeAgentMessageContext;
|
|
689
|
+
/** Injected only after strict Agent admission; a host registry may never replace this reserved name. */
|
|
690
|
+
private withAgentMemoryMcp;
|
|
691
|
+
/** Reconstruct all sensitive context from the active sealed task, never from MCP/model arguments. */
|
|
692
|
+
private activeMemoryContext;
|
|
693
|
+
private runMemoryOperation;
|
|
694
|
+
private quiesceAndSnapshotAgentMemory;
|
|
695
|
+
private bindAgentMemoryFilesystem;
|
|
696
|
+
private closeAgentMemoryFilesystem;
|
|
697
|
+
private revokeAgentMemoryContext;
|
|
615
698
|
/** Protocol §7: an instruction too large to inline arrives as a `blobRef` — resolve it via the blob client rather than failing closed. */
|
|
616
699
|
private resolveInstruction;
|
|
617
700
|
/** Resolve every requested logical id locally and reject missing/colliding server authority before claim. */
|
|
618
701
|
private resolveMcpServers;
|
|
619
702
|
private pump;
|
|
703
|
+
private publishSuccessfulCompletion;
|
|
620
704
|
/**
|
|
621
705
|
* Protocol §7: an `artifact` `AgentEvent` only names a file the runtime
|
|
622
706
|
* wrote into the task workspace (`name`/`contentType` — it carries no
|
|
@@ -1019,6 +1103,7 @@ export declare class TaskRunner {
|
|
|
1019
1103
|
private reserveSemanticTerminal;
|
|
1020
1104
|
/** M3-B: bounded insert for `finishedTaskIds` — see its class-level doc comment and `MAX_TRACKED_TASK_IDS`. Evicts the oldest (first-inserted) entry once over cap, same idiom as `ConnectionHub.checkAndRecordDuplicate` (packages/server/src/hub.ts). */
|
|
1021
1105
|
private addFinishedTaskId;
|
|
1106
|
+
private addStrictDeclinedTaskId;
|
|
1022
1107
|
/** `reuseDir`, when set (a known sessionRef's recorded workspace), is used verbatim instead of a fresh `workspaceRoot/<taskId>` directory — `mkdir recursive` is idempotent either way, so ensuring-exists is safe to do unconditionally. */
|
|
1023
1108
|
private resolveWorkspaceDir;
|
|
1024
1109
|
/**
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ToolsetId } from '@byok-sdk/protocol';
|
|
2
2
|
import type { McpToolsetConfig, McpToolsetObservation, McpToolsetRegistryStatus, McpToolsetReloadReceipt } from '../types';
|
|
3
|
+
export declare const AGENT_MESSAGE_MCP_SERVER_NAME = "byokagentmessage";
|
|
4
|
+
export declare const AGENT_MEMORY_MCP_SERVER_NAME = "byokagentmemory";
|
|
3
5
|
export type McpToolsetConfigInput = Record<string, McpToolsetConfig> | undefined;
|
|
4
6
|
export interface McpToolsetRegistrySnapshot {
|
|
5
7
|
revision: string;
|