@byok-sdk/client 0.13.0 → 0.15.0
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 +95 -0
- package/dist/adapters/claude/process-client.d.ts +24 -0
- package/dist/adapters/codex/codex-adapter.d.ts +2 -0
- package/dist/adapters/codex/process-runner.d.ts +62 -18
- package/dist/adapters/detect-outcome.d.ts +18 -0
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +546 -76
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/pi/events.d.ts +1 -1
- package/dist/adapters/pi/rpc-client.d.ts +47 -1
- package/dist/adapters/pi/subagents-policy-extension.js +1 -1
- package/dist/adapters/pi/subagents-policy-extension.js.map +1 -1
- package/dist/adapters/pi/team-interaction-extension.d.ts +24 -0
- package/dist/adapters/pi/team-interaction-extension.js +81 -0
- package/dist/adapters/pi/team-interaction-extension.js.map +1 -0
- package/dist/adapters/process-tree.d.ts +74 -4
- package/dist/adapters/provider-credential-environment.d.ts +1 -1
- package/dist/adapters/win32-job-object.d.ts +101 -0
- package/dist/bin/byok-agent-memory-mcp.js +29 -0
- package/dist/bin/byok-agent-memory-mcp.js.map +1 -1
- package/dist/bin/byok-agent-message-mcp.js +29 -0
- package/dist/bin/byok-agent-message-mcp.js.map +1 -1
- package/dist/bin/byok-agent-team-mcp.js +29 -0
- package/dist/bin/byok-agent-team-mcp.js.map +1 -1
- package/dist/bin/byok-agent.js +20274 -18057
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/bin/byok-approval-mcp.js +29 -0
- package/dist/bin/byok-approval-mcp.js.map +1 -1
- package/dist/bin/byok-mcp-env.d.ts +2 -0
- package/dist/bin/byok-mcp-env.js +36 -0
- package/dist/bin/byok-mcp-env.js.map +1 -0
- package/dist/bin/commands/doctor.d.ts +3 -0
- package/dist/bin/commands/team-pi-relay.d.ts +24 -0
- package/dist/bin/commands/team-relay.d.ts +11 -0
- package/dist/bin/mcp-env-launcher.d.ts +5 -0
- package/dist/bin/runtime-probe.d.ts +6 -7
- package/dist/bin/team-codex-relay.d.ts +32 -0
- package/dist/bin/team-notification-relay.d.ts +40 -0
- package/dist/bin/team-pi-session.d.ts +59 -0
- package/dist/daemon/admission-wait.d.ts +2 -0
- package/dist/daemon/agent-egress-policy.d.ts +8 -0
- package/dist/daemon/agent-egress-spool.d.ts +1 -0
- package/dist/daemon/agent-message-outbox.d.ts +15 -3
- package/dist/daemon/artifact-read.d.ts +7 -0
- package/dist/daemon/connection-manager.d.ts +23 -176
- package/dist/daemon/control-protocol.d.ts +2 -0
- package/dist/daemon/create-daemon.d.ts +43 -1
- package/dist/daemon/event-spill.d.ts +90 -0
- package/dist/daemon/journal/journal.d.ts +15 -3
- package/dist/daemon/journal/sqlite-journal.d.ts +7 -2
- package/dist/daemon/long-poll-transport.d.ts +2 -50
- package/dist/daemon/runtime-start.d.ts +3 -0
- package/dist/daemon/store.d.ts +2 -0
- package/dist/daemon/task-runner.d.ts +36 -0
- package/dist/daemon/team-workspace.d.ts +9 -0
- package/dist/daemon/terminal-commit-queue.d.ts +21 -0
- package/dist/daemon/terminal-identity.d.ts +6 -0
- package/dist/diagnostics/device-doctor.d.ts +46 -0
- package/dist/diagnostics/diagnostics.d.ts +3 -80
- package/dist/diagnostics/types.d.ts +82 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2824 -649
- package/dist/index.js.map +1 -1
- package/dist/runtime-detection.d.ts +3 -0
- package/dist/runtime-failure.d.ts +6 -0
- package/dist/sdk-reserved-helper-host.d.ts +1 -1
- package/dist/types.d.ts +20 -10
- package/dist/util/durable-jsonl.d.ts +12 -0
- package/package.json +8 -5
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
|
|
4
|
+
async function runMcpEnvLauncher() {
|
|
5
|
+
const key = process.env.BYOK_MCP_ENV_KEY;
|
|
6
|
+
if (!key || !/^BYOK_MCP_PAYLOAD_[A-F0-9]{32}$/.test(key)) throw new Error("invalid MCP environment binding");
|
|
7
|
+
const encoded = process.env[key];
|
|
8
|
+
if (!encoded) throw new Error("missing sealed MCP environment");
|
|
9
|
+
let config;
|
|
10
|
+
try {
|
|
11
|
+
config = JSON.parse(encoded);
|
|
12
|
+
if (!config || typeof config.command !== "string" || !config.command || config.args !== void 0 && (!Array.isArray(config.args) || config.args.some((value) => typeof value !== "string")) || config.env !== void 0 && (typeof config.env !== "object" || config.env === null || Array.isArray(config.env) || Object.values(config.env).some((value) => typeof value !== "string"))) throw new Error();
|
|
13
|
+
} catch {
|
|
14
|
+
throw new Error("invalid sealed MCP environment");
|
|
15
|
+
}
|
|
16
|
+
const env = { ...process.env };
|
|
17
|
+
delete env.BYOK_MCP_ENV_KEY;
|
|
18
|
+
for (const name of Object.keys(env)) if (name.startsWith("BYOK_MCP_PAYLOAD_")) delete env[name];
|
|
19
|
+
Object.assign(env, config.env);
|
|
20
|
+
await new Promise((resolve, reject) => {
|
|
21
|
+
const child = spawn(config.command, config.args ?? [], { env, stdio: "inherit", windowsHide: true });
|
|
22
|
+
child.once("error", () => reject(new Error("MCP child could not be spawned")));
|
|
23
|
+
child.once("close", (code) => {
|
|
24
|
+
if (code === 0) resolve();
|
|
25
|
+
else reject(new Error("MCP child exited unsuccessfully"));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/bin/byok-mcp-env.ts
|
|
31
|
+
runMcpEnvLauncher().catch(() => {
|
|
32
|
+
process.stderr.write("byok-mcp-env: MCP launch failed\n");
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=byok-mcp-env.js.map
|
|
36
|
+
//# sourceMappingURL=byok-mcp-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/bin/mcp-env-launcher.ts","../../src/bin/byok-mcp-env.ts"],"names":[],"mappings":";;;AAMA,eAAsB,iBAAA,GAAmC;AACvD,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,CAAI,gBAAA;AACxB,EAAA,IAAI,CAAC,GAAA,IAAO,CAAC,iCAAA,CAAkC,IAAA,CAAK,GAAG,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,iCAAiC,CAAA;AAC3G,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAC/B,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAC9D,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AAC3B,IAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,CAAO,OAAA,KAAY,YAAY,CAAC,MAAA,CAAO,OAAA,IACvD,MAAA,CAAO,IAAA,KAAS,KAAA,CAAA,KAAc,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,IAAK,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAA,KAAA,KAAS,OAAO,KAAA,KAAU,QAAQ,CAAA,CAAA,IAChH,MAAA,CAAO,QAAQ,KAAA,CAAA,KAAc,OAAO,MAAA,CAAO,GAAA,KAAQ,QAAA,IAAY,MAAA,CAAO,QAAQ,IAAA,IAAQ,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,GAAG,CAAA,IAC7G,OAAO,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAA,KAAA,KAAS,OAAO,KAAA,KAAU,QAAQ,CAAA,CAAA,EAAK,MAAM,IAAI,KAAA,EAAM;AAAA,EAC/F,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AACA,EAAA,MAAM,GAAA,GAAM,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAI;AAC7B,EAAA,OAAO,GAAA,CAAI,gBAAA;AACX,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,EAAG,IAAI,IAAA,CAAK,UAAA,CAAW,mBAAmB,CAAA,EAAG,OAAO,GAAA,CAAI,IAAI,CAAA;AAC9F,EAAA,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,GAAG,CAAA;AAC7B,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,OAAA,EAAS,OAAO,IAAA,IAAQ,EAAC,EAAG,EAAE,GAAA,EAAK,KAAA,EAAO,SAAA,EAAW,WAAA,EAAa,MAAM,CAAA;AACnG,IAAA,KAAA,CAAM,IAAA,CAAK,SAAS,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,gCAAgC,CAAC,CAAC,CAAA;AAC7E,IAAA,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA,IAAA,KAAQ;AAC1B,MAAA,IAAI,IAAA,KAAS,GAAG,OAAA,EAAQ;AAAA,WACnB,MAAA,CAAO,IAAI,KAAA,CAAM,iCAAiC,CAAC,CAAA;AAAA,IAC1D,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;;;AC9BA,iBAAA,EAAkB,CAAE,MAAM,MAAM;AAC9B,EAAA,OAAA,CAAQ,MAAA,CAAO,MAAM,mCAAmC,CAAA;AACxD,EAAA,OAAA,CAAQ,QAAA,GAAW,CAAA;AACrB,CAAC,CAAA","file":"byok-mcp-env.js","sourcesContent":["import { spawn } from 'node:child_process';\n\n/** Project one sealed server's env through Codex's documented env_vars channel.\n * No secret or original server argument is carried in the launcher argv.\n * The child remains in Codex's owned process group / Windows Job Object.\n */\nexport async function runMcpEnvLauncher(): Promise<void> {\n const key = process.env.BYOK_MCP_ENV_KEY;\n if (!key || !/^BYOK_MCP_PAYLOAD_[A-F0-9]{32}$/.test(key)) throw new Error('invalid MCP environment binding');\n const encoded = process.env[key];\n if (!encoded) throw new Error('missing sealed MCP environment');\n let config: { command: string; args?: string[]; env?: Record<string, string> };\n try {\n config = JSON.parse(encoded);\n if (!config || typeof config.command !== 'string' || !config.command\n || (config.args !== undefined && (!Array.isArray(config.args) || config.args.some(value => typeof value !== 'string')))\n || (config.env !== undefined && (typeof config.env !== 'object' || config.env === null || Array.isArray(config.env)\n || Object.values(config.env).some(value => typeof value !== 'string')))) throw new Error();\n } catch {\n throw new Error('invalid sealed MCP environment');\n }\n const env = { ...process.env };\n delete env.BYOK_MCP_ENV_KEY;\n for (const name of Object.keys(env)) if (name.startsWith('BYOK_MCP_PAYLOAD_')) delete env[name];\n Object.assign(env, config.env);\n await new Promise<void>((resolve, reject) => {\n const child = spawn(config.command, config.args ?? [], { env, stdio: 'inherit', windowsHide: true });\n child.once('error', () => reject(new Error('MCP child could not be spawned')));\n child.once('close', code => {\n if (code === 0) resolve();\n else reject(new Error('MCP child exited unsuccessfully'));\n });\n });\n}\n","#!/usr/bin/env node\nimport { runMcpEnvLauncher } from './mcp-env-launcher';\n\nrunMcpEnvLauncher().catch(() => {\n process.stderr.write('byok-mcp-env: MCP launch failed\\n');\n process.exitCode = 1;\n});\n"]}
|
|
@@ -3,6 +3,9 @@ import { type CollectDiagnosticsOptions } from '../../diagnostics/diagnostics';
|
|
|
3
3
|
export interface DoctorOptions extends CollectDiagnosticsOptions {
|
|
4
4
|
json?: boolean;
|
|
5
5
|
fix?: boolean;
|
|
6
|
+
repair?: string;
|
|
7
|
+
expectedDeviceId?: string;
|
|
8
|
+
expectedTenantId?: string;
|
|
6
9
|
confirmed?: boolean;
|
|
7
10
|
log?: (line: string) => void;
|
|
8
11
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DaemonConfig } from '../../daemon/create-daemon';
|
|
2
|
+
import { type CodexTeamBinding } from '../team-codex-relay';
|
|
3
|
+
export declare function parsePiRelayBindings(value: unknown, workspaceId: string): {
|
|
4
|
+
codex: CodexTeamBinding;
|
|
5
|
+
pi: {
|
|
6
|
+
context: string;
|
|
7
|
+
lease: import("../..").TeamMemberLease;
|
|
8
|
+
afterSeq: number;
|
|
9
|
+
cwd: string;
|
|
10
|
+
sessionDir: string;
|
|
11
|
+
provider: string;
|
|
12
|
+
model: string;
|
|
13
|
+
systemPrompt: string;
|
|
14
|
+
extensionPaths: string[];
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export declare function runTeamPiRelayCommand(input: {
|
|
18
|
+
config: DaemonConfig;
|
|
19
|
+
workspaceId: string;
|
|
20
|
+
bindingsFile: string;
|
|
21
|
+
codexBin: string;
|
|
22
|
+
maxNotifications: number;
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DaemonConfig } from '../../daemon/create-daemon';
|
|
2
|
+
/** One foreground owner per room. Stale locks are never guessed away or stolen. */
|
|
3
|
+
export declare function acquireTeamRelayLock(storeDir: string, workspaceId: string): Promise<() => Promise<void>>;
|
|
4
|
+
export declare function runTeamRelayCommand(input: {
|
|
5
|
+
config: DaemonConfig;
|
|
6
|
+
workspaceId: string;
|
|
7
|
+
bindingsFile: string;
|
|
8
|
+
codexBin: string;
|
|
9
|
+
maxNotifications: number;
|
|
10
|
+
signal: AbortSignal;
|
|
11
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Project one sealed server's env through Codex's documented env_vars channel.
|
|
2
|
+
* No secret or original server argument is carried in the launcher argv.
|
|
3
|
+
* The child remains in Codex's owned process group / Windows Job Object.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runMcpEnvLauncher(): Promise<void>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RuntimeDetectResult } from '../types';
|
|
1
2
|
import { type RuntimeAdapter } from '../index';
|
|
2
3
|
export declare const RUNTIME_PROBE_TIMEOUT_MS = 5000;
|
|
3
4
|
/** The bundled adapter set `byok-agent status`/`byok-agent runtimes` probe by default — same unset-vs-set allowlist contract as `createDaemon` itself. */
|
|
@@ -13,7 +14,9 @@ export declare function defaultRuntimeAdapters(runtimeAllowlist: string[] | unde
|
|
|
13
14
|
*/
|
|
14
15
|
export interface ProbedRuntime {
|
|
15
16
|
id: string;
|
|
17
|
+
/** Deterministic projection of outcome, never adapter-authored. */
|
|
16
18
|
present: boolean;
|
|
19
|
+
outcome: RuntimeDetectResult['kind'];
|
|
17
20
|
version?: string;
|
|
18
21
|
authPresent?: boolean;
|
|
19
22
|
steer: boolean;
|
|
@@ -21,13 +24,9 @@ export interface ProbedRuntime {
|
|
|
21
24
|
permissionModes: string[];
|
|
22
25
|
}
|
|
23
26
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* resolves `{present: false}` rather than rejecting) — the catch here is a
|
|
28
|
-
* defensive backstop for a `RuntimeAdapter` that doesn't hold that
|
|
29
|
-
* convention, not a workaround for an observed failure in the bundled
|
|
30
|
-
* three.
|
|
27
|
+
* Fresh, parallel local observations. A custom adapter timeout is an observation
|
|
28
|
+
* deadline only: detect() has no cancellation contract. Never expose arbitrary
|
|
29
|
+
* adapter errors or interpret an old/malformed result as available.
|
|
31
30
|
*/
|
|
32
31
|
export declare function probeRuntimes(adapters: readonly RuntimeAdapter[], options?: {
|
|
33
32
|
timeoutMs?: number;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type TeamMemberLease } from '../daemon/team-workspace';
|
|
2
|
+
export interface CodexTeamBinding {
|
|
3
|
+
readonly context: string;
|
|
4
|
+
readonly lease: TeamMemberLease;
|
|
5
|
+
readonly threadId: string;
|
|
6
|
+
readonly endpoint: string;
|
|
7
|
+
readonly afterSeq: number;
|
|
8
|
+
}
|
|
9
|
+
export interface TeamNotificationSnapshot {
|
|
10
|
+
workspaceId: string;
|
|
11
|
+
memberId: string;
|
|
12
|
+
registryRevision: string;
|
|
13
|
+
expiresAt: string;
|
|
14
|
+
acknowledgedThroughSeq: number;
|
|
15
|
+
latestPeerSeq: number | null;
|
|
16
|
+
}
|
|
17
|
+
/** Local endpoints only. Never select a default daemon or infer a thread from its name. */
|
|
18
|
+
export declare function validateCodexRelayEndpoint(value: unknown): asserts value is string;
|
|
19
|
+
export declare function parseCodexTeamBinding(binding: unknown, workspaceId: string): CodexTeamBinding;
|
|
20
|
+
export declare function parseCodexTeamBindings(value: unknown, workspaceId: string): readonly CodexTeamBinding[];
|
|
21
|
+
export declare function loadPrivateTeamDocument(file: string): Promise<unknown>;
|
|
22
|
+
export declare function loadCodexTeamBindings(file: string, workspaceId: string): Promise<readonly CodexTeamBinding[]>;
|
|
23
|
+
export declare function codexTeamNotification(workspaceId: string, throughSeq: number): string;
|
|
24
|
+
/** The native queue receipt contract is qualified against this CLI version. */
|
|
25
|
+
export declare function preflightCodexRelay(codexBin: string, signal: AbortSignal): Promise<string>;
|
|
26
|
+
/** Only a confirmed exact-thread queue receipt advances this epoch's notification watermark. */
|
|
27
|
+
export declare function queueCodexTeamNotification(input: {
|
|
28
|
+
codexBin: string;
|
|
29
|
+
binding: CodexTeamBinding;
|
|
30
|
+
throughSeq: number;
|
|
31
|
+
signal: AbortSignal;
|
|
32
|
+
}): Promise<string>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TeamMemberLease } from '../daemon/team-workspace';
|
|
2
|
+
export interface TeamRelayBinding {
|
|
3
|
+
readonly context: string;
|
|
4
|
+
readonly lease: TeamMemberLease;
|
|
5
|
+
readonly afterSeq: number;
|
|
6
|
+
}
|
|
7
|
+
export type TeamRelayState = 'running' | 'paused' | 'stopped' | 'budget_exhausted' | 'failed';
|
|
8
|
+
export declare class TeamNotificationRelay<T extends TeamRelayBinding> {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private state;
|
|
11
|
+
private attempts;
|
|
12
|
+
private error;
|
|
13
|
+
private readonly watermarks;
|
|
14
|
+
private pending;
|
|
15
|
+
private readonly abort;
|
|
16
|
+
constructor(options: {
|
|
17
|
+
bindings: readonly T[];
|
|
18
|
+
maxNotifications: number;
|
|
19
|
+
snapshot: (binding: T, afterSeq: number) => Promise<unknown>;
|
|
20
|
+
describe: (binding: T) => Record<string, string>;
|
|
21
|
+
ready?: (binding: T) => Promise<boolean>;
|
|
22
|
+
enqueue: (binding: T, throughSeq: number, signal: AbortSignal) => Promise<string>;
|
|
23
|
+
});
|
|
24
|
+
status(): {
|
|
25
|
+
state: TeamRelayState;
|
|
26
|
+
attempts: number;
|
|
27
|
+
maxNotifications: number;
|
|
28
|
+
error?: "queue_delivery_unknown" | "snapshot_failed" | undefined;
|
|
29
|
+
bindings: {
|
|
30
|
+
workspaceId: string;
|
|
31
|
+
memberId: string;
|
|
32
|
+
notifiedThroughSeq: number | undefined;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
pause(): void;
|
|
36
|
+
resume(): void;
|
|
37
|
+
stop(): void;
|
|
38
|
+
tick(): Promise<void>;
|
|
39
|
+
private performTick;
|
|
40
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface PiInteractionResponse {
|
|
2
|
+
sessionId: string;
|
|
3
|
+
requestId: string;
|
|
4
|
+
response: {
|
|
5
|
+
cancelled: true;
|
|
6
|
+
} | {
|
|
7
|
+
confirmed: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
value: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface PiTeamSessionOptions {
|
|
13
|
+
workspaceId: string;
|
|
14
|
+
cwd: string;
|
|
15
|
+
sessionDir: string;
|
|
16
|
+
provider: string;
|
|
17
|
+
model: string;
|
|
18
|
+
systemPrompt: string;
|
|
19
|
+
mcpConfig: Record<string, unknown>;
|
|
20
|
+
extensionPaths?: readonly string[];
|
|
21
|
+
onEvent: (event: Record<string, unknown>) => void;
|
|
22
|
+
}
|
|
23
|
+
/** One owned RPC child; GUI replies never share a model-controlled tool channel. */
|
|
24
|
+
export declare class PiTeamSession {
|
|
25
|
+
private readonly options;
|
|
26
|
+
private client;
|
|
27
|
+
private sessionId;
|
|
28
|
+
private revision;
|
|
29
|
+
private phase;
|
|
30
|
+
private readonly interactions;
|
|
31
|
+
private readonly replying;
|
|
32
|
+
private stopping;
|
|
33
|
+
private active;
|
|
34
|
+
private pendingInputs;
|
|
35
|
+
private readonly privateFiles;
|
|
36
|
+
private constructor();
|
|
37
|
+
static start(options: PiTeamSessionOptions): Promise<PiTeamSession>;
|
|
38
|
+
status(): {
|
|
39
|
+
sessionId: string | undefined;
|
|
40
|
+
phase: "closed" | "failed" | "open" | "starting" | "waiting";
|
|
41
|
+
revision: number;
|
|
42
|
+
pendingUi: {
|
|
43
|
+
id: string | undefined;
|
|
44
|
+
method: unknown;
|
|
45
|
+
responding: boolean;
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
private fail;
|
|
49
|
+
private onFrame;
|
|
50
|
+
private onInteraction;
|
|
51
|
+
private request;
|
|
52
|
+
private state;
|
|
53
|
+
ready(): Promise<boolean>;
|
|
54
|
+
notify(throughSeq: number, signal: AbortSignal): Promise<string>;
|
|
55
|
+
sendInput(message: string): Promise<string>;
|
|
56
|
+
respond(input: PiInteractionResponse): Promise<void>;
|
|
57
|
+
drain(signal: AbortSignal): Promise<void>;
|
|
58
|
+
stop(): Promise<void>;
|
|
59
|
+
}
|
|
@@ -31,6 +31,14 @@ export declare function resolveAgentEgressPolicy(policy: AgentEgressPolicy | und
|
|
|
31
31
|
* Default activity projection. Every retained string is SDK-authored; no
|
|
32
32
|
* runtime trajectory, tool, prompt, environment, argv, path, or credential
|
|
33
33
|
* value survives this transformation.
|
|
34
|
+
*
|
|
35
|
+
* Each case CONSTRUCTS a fresh event from SDK-authored literals rather than
|
|
36
|
+
* editing the incoming one, which is what makes the guarantee total rather
|
|
37
|
+
* than a list of fields someone remembered to strip. `spill` on
|
|
38
|
+
* `tool_use`/`tool_result` is covered by exactly that: a `BlobRef` is a
|
|
39
|
+
* readable locator for the omitted tool payload — content, not metadata — so
|
|
40
|
+
* it never survives a metadata-status projection, and neither do the byte
|
|
41
|
+
* counts that would leak the payload's size.
|
|
34
42
|
*/
|
|
35
43
|
export declare function metadataStatusEvent(event: AgentEvent): AgentEvent;
|
|
36
44
|
export declare function eventBytes(event: AgentEvent): number;
|
|
@@ -20,12 +20,14 @@ export interface AgentMessageOutboxRecord {
|
|
|
20
20
|
export declare class AgentMessageOutboxError extends Error {
|
|
21
21
|
constructor(message: string);
|
|
22
22
|
}
|
|
23
|
-
/** Agent-local
|
|
23
|
+
/** Agent-local append-before-send authority. Only acceptance or explicit terminal archival retires bytes. */
|
|
24
24
|
export declare class AgentMessageOutbox {
|
|
25
25
|
readonly homeDir: string;
|
|
26
26
|
readonly outboxPath: string;
|
|
27
27
|
private readonly pendingByTask;
|
|
28
|
+
private readonly revokedTasks;
|
|
28
29
|
private readonly dispositionByTask;
|
|
30
|
+
private readonly file;
|
|
29
31
|
private nextCursor;
|
|
30
32
|
private logEntries;
|
|
31
33
|
private writeTail;
|
|
@@ -34,7 +36,7 @@ export declare class AgentMessageOutbox {
|
|
|
34
36
|
/** Re-open every existing Agent-local message outbox without following Agent-home symlinks. */
|
|
35
37
|
static recover(agentsRoot: string, tenantId: string): Promise<readonly AgentMessageOutbox[]>;
|
|
36
38
|
records(): readonly AgentMessageOutboxRecord[];
|
|
37
|
-
/**
|
|
39
|
+
/** Records without disposition or local revoke; transport replay additionally requires session binding. */
|
|
38
40
|
retryableRecords(): readonly AgentMessageOutboxRecord[];
|
|
39
41
|
get(taskId: string): AgentMessageOutboxRecord | undefined;
|
|
40
42
|
appendDraft(input: {
|
|
@@ -48,11 +50,21 @@ export declare class AgentMessageOutbox {
|
|
|
48
50
|
readonly maxPendingEvents: number;
|
|
49
51
|
readonly maxPendingBytes: number;
|
|
50
52
|
}): Promise<AgentMessageOutboxRecord>;
|
|
51
|
-
activate(taskId: string, sessionRef: string): Promise<AgentMessageOutboxRecord | undefined>;
|
|
53
|
+
activate(taskId: string, sessionRef: string, isCurrent?: () => boolean): Promise<AgentMessageOutboxRecord | undefined>;
|
|
54
|
+
/** Local lifecycle cancellation, never a synthesized consumer disposition. */
|
|
55
|
+
revoke(taskId: string): Promise<void>;
|
|
56
|
+
private isTerminalEvidence;
|
|
52
57
|
publishPayload(record: AgentMessageOutboxRecord): AgentMessagePublishPayload;
|
|
53
58
|
applyDisposition(taskId: string, input: unknown): Promise<'accepted' | 'held' | 'refused' | 'mismatch' | 'unknown'>;
|
|
54
59
|
private load;
|
|
55
60
|
private appendEntry;
|
|
61
|
+
/**
|
|
62
|
+
* Explicit operator maintenance under the Agent-home single-writer lease.
|
|
63
|
+
* Copy complete terminal evidence durably before removing it from the live log.
|
|
64
|
+
* Archives are audit artifacts, never another replay input. held remains live.
|
|
65
|
+
*/
|
|
66
|
+
archiveTerminalRecords(archiveDirectory: string): Promise<string | undefined>;
|
|
67
|
+
private snapshotEntries;
|
|
56
68
|
private compact;
|
|
57
69
|
private exclusive;
|
|
58
70
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FileHandle } from 'node:fs/promises';
|
|
2
|
+
export declare const DEFAULT_ARTIFACT_LIMITS: Readonly<{
|
|
3
|
+
maxFileBytes: number;
|
|
4
|
+
maxTaskBytes: number;
|
|
5
|
+
}>;
|
|
6
|
+
/** The caller retains fd ownership; no pathname is reopened. */
|
|
7
|
+
export declare function readArtifactBytes(handle: FileHandle, maxBytes: number, signal: AbortSignal, account: (bytes: number) => void): Promise<Buffer>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { HarnessInfo } from '@byok-sdk/protocol';
|
|
1
2
|
import { type CapabilityFlag, type Envelope, type RuntimeInfo, type ToolsetId } from '@byok-sdk/protocol';
|
|
2
3
|
import { AuthManager } from './auth-manager';
|
|
3
4
|
import type { CursorStore } from './cursor-store';
|
|
@@ -14,6 +15,7 @@ export interface ConnectionManagerOptions {
|
|
|
14
15
|
/** U4a Local Agent release version, sent unchanged in `conn.hello`. */
|
|
15
16
|
clientVersion?: string;
|
|
16
17
|
runtimes: RuntimeInfo[];
|
|
18
|
+
harnesses?: HarnessInfo[];
|
|
17
19
|
/** Reads current sorted logical IDs from the validated local registry for every `conn.hello`. */
|
|
18
20
|
getConfiguredToolsets?: () => readonly ToolsetId[];
|
|
19
21
|
auth: AuthManager;
|
|
@@ -25,6 +27,11 @@ export interface ConnectionManagerOptions {
|
|
|
25
27
|
*/
|
|
26
28
|
onEnvelope: (envelope: Envelope) => void | Promise<void>;
|
|
27
29
|
onStateChange?: (state: ConnectionState) => void;
|
|
30
|
+
/** Await durable disposition before retiring the exact accepted/rejected bytes. */
|
|
31
|
+
onOutboundAccepted?: (envelopes: readonly Envelope[]) => Promise<void>;
|
|
32
|
+
onOutboundRejected?: (envelope: Envelope) => Promise<void>;
|
|
33
|
+
onOutboundQueued?: (envelope: Envelope) => void;
|
|
34
|
+
beforeOutboundPost?: (envelopes: readonly Envelope[]) => void;
|
|
28
35
|
/** Backoff between failed long-poll HTTP attempts. Default 2s. */
|
|
29
36
|
longPollRetryDelayMs?: number;
|
|
30
37
|
/** Minimum delay before the next long-poll request after an empty (no-events) response. Default 250ms. */
|
|
@@ -68,25 +75,11 @@ export declare class ConnectionManager {
|
|
|
68
75
|
* guarantees in docs/protocol.md §9.
|
|
69
76
|
*/
|
|
70
77
|
private stalledAtSeq;
|
|
71
|
-
/**
|
|
72
|
-
* Design A (Wave 2, F3-on-long-poll): the second, in-memory watermark
|
|
73
|
-
* alongside the durable `cursor`. `cursor` only ever advances AFTER a
|
|
74
|
-
* `task.*` handler's side effects resolve successfully, and is persisted
|
|
75
|
-
* (see `advanceCursor`) — that semantics is unchanged. `deliveredSeq`
|
|
76
|
-
* advances eagerly, the instant a `task.*` envelope is admitted past
|
|
77
|
-
* dedup (see `deliver`/`noteDelivered`), independent of whether its
|
|
78
|
-
* handler has even started, let alone succeeded. It exists so a repeated
|
|
79
|
-
* read at the durable cursor does not re-dispatch an envelope already in
|
|
80
|
-
* flight — `handleOffer` must not start a second adapter session while a
|
|
81
|
-
* first attempt is still running. On WS this same field is written the
|
|
82
|
-
* same way, but since a live WS connection only ever pushes a given `seq`
|
|
83
|
-
* once, it never has an observable effect there beyond mirroring
|
|
84
|
-
* `cursor` (see `dedupWatermark`'s doc comment for why redelivery
|
|
85
|
-
* correctness doesn't depend on resetting it anywhere).
|
|
86
|
-
*/
|
|
87
|
-
private deliveredSeq;
|
|
88
|
-
/** Finding F3: serializes `onEnvelope` calls into a per-connection FIFO — one envelope's handler always fully settles before the next one starts. */
|
|
78
|
+
/** Drain barrier for independently running handlers; not an admission lock. */
|
|
89
79
|
private processingChain;
|
|
80
|
+
private cursorInitialization;
|
|
81
|
+
private completionTail;
|
|
82
|
+
private readonly controlTails;
|
|
90
83
|
/**
|
|
91
84
|
* Design B (finding N4): the ONE outbound queue holds `Envelope` OBJECTS,
|
|
92
85
|
* never re-encoded/rebuilt strings, so a
|
|
@@ -112,38 +105,13 @@ export declare class ConnectionManager {
|
|
|
112
105
|
private terminalError;
|
|
113
106
|
private settledWaiters;
|
|
114
107
|
private pendingCursorSave;
|
|
115
|
-
/**
|
|
116
|
-
* Finding P2 (Fix 2b): seqs currently admitted into `processingChain` but
|
|
117
|
-
* not yet settled — added in `deliver()` the moment a `task.*` envelope is
|
|
118
|
-
* accepted past the ordinary watermark check, removed in `process()`'s
|
|
119
|
-
* `finally` once that specific attempt resolves (success OR failure).
|
|
120
|
-
* While stalled, `dedupWatermark()` deliberately stays frozen below
|
|
121
|
-
* already-delivered seqs (see its own doc comment) so the failed seq's own
|
|
122
|
-
* redelivery can get through — but that same frozen watermark also means
|
|
123
|
-
* every OTHER seq above it rides along on every re-poll too. Without this,
|
|
124
|
-
* a seq already mid-flight (e.g. a `task.offer` whose prepared operation start()
|
|
125
|
-
* hasn't resolved yet) would be re-enqueued into `processingChain` on
|
|
126
|
-
* every such re-poll, piling up duplicate copies that — once the first
|
|
127
|
-
* finally resolves and the chain unwinds through them — run its handler
|
|
128
|
-
* again; for `task.offer` specifically, a second adapter session
|
|
129
|
-
* orphaning the first (`TaskRunner`'s own `this.tasks.has` guard, finding
|
|
130
|
-
* P2c, is the second, independent layer against exactly that).
|
|
131
|
-
*/
|
|
108
|
+
/** Admission dedup while an individual handler is running. */
|
|
132
109
|
private readonly inFlightSeqs;
|
|
133
|
-
/**
|
|
134
|
-
* Finding P2 (Fix 2b): seqs whose handler has already resolved
|
|
135
|
-
* successfully at least once this session, tracked only while a stall is
|
|
136
|
-
* in effect — cleared the moment `stalledAtSeq` itself clears (see
|
|
137
|
-
* `process()`), since once unstalled the ordinary watermark check via
|
|
138
|
-
* `deliveredSeq` already covers everything delivered so far, making this
|
|
139
|
-
* redundant. Needed because the stall-gap-prevention rule in `process()`
|
|
140
|
-
* deliberately does NOT advance `cursor` past a seq above the
|
|
141
|
-
* still-unresolved `stalledAtSeq`, even once that seq's own handler
|
|
142
|
-
* succeeds — so `dedupWatermark()` alone can't distinguish "already
|
|
143
|
-
* succeeded, don't re-run" from "never yet attempted" for anything in
|
|
144
|
-
* that gap.
|
|
145
|
-
*/
|
|
110
|
+
/** Successful side effects retained until their durable acknowledgement. */
|
|
146
111
|
private readonly processedSeqs;
|
|
112
|
+
private readonly failedEnvelopes;
|
|
113
|
+
/** Received work lacking a successful handler receipt, including malformed frames. */
|
|
114
|
+
private readonly unresolvedSeqs;
|
|
147
115
|
/**
|
|
148
116
|
* Finding P3: the pending `drainOutbox` long-poll retry backoff, if any —
|
|
149
117
|
* cancellable so `enterRevoked()` can unblock it immediately instead of
|
|
@@ -298,142 +266,21 @@ export declare class ConnectionManager {
|
|
|
298
266
|
* - F3 (at-most-once): the old code persisted the cursor advance BEFORE
|
|
299
267
|
* `onEnvelope` even ran (fire-and-forget) — a handler that then failed
|
|
300
268
|
* left a redelivery-proof envelope permanently marked processed. Inbound
|
|
301
|
-
*
|
|
302
|
-
*
|
|
269
|
+
* handlers may run independently; their receipt commits are serialized.
|
|
270
|
+
* The cursor only advances
|
|
303
271
|
* AFTER the handler resolves successfully; a rejection leaves the
|
|
304
272
|
* cursor where it was (see `stalledAtSeq`), so a future reconnect's
|
|
305
273
|
* redelivery re-attempts it — safe because every server->daemon type is
|
|
306
274
|
* documented idempotent (protocol §9).
|
|
307
275
|
*/
|
|
308
276
|
private deliver;
|
|
309
|
-
/**
|
|
310
|
-
*
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
* `cursor` (see the constructor). Normally this local watermark is
|
|
314
|
-
* `deliveredSeq` — which is always >= `cursor` (every envelope that
|
|
315
|
-
* reaches `advanceCursor` already passed through `noteDelivered` first,
|
|
316
|
-
* see `deliver`) — so this is the literal `max(cursor, deliveredSeq)` the
|
|
317
|
-
* design calls for, just expressed via that invariant rather than an
|
|
318
|
-
* explicit `Math.max`.
|
|
319
|
-
*
|
|
320
|
-
* While `stalledAtSeq` is set, this collapses to the durable `cursor`
|
|
321
|
-
* alone, deliberately ignoring however far `deliveredSeq` had already run
|
|
322
|
-
* ahead before the failure was known: that's what lets the stalled
|
|
323
|
-
* envelope's own redelivery (and everything after it, right up to a
|
|
324
|
-
* fresh success) get past this same dedup check instead of being
|
|
325
|
-
* self-deduped by the client's own earlier eager tracking of envelopes
|
|
326
|
-
* whose outcome wasn't known yet. No separate "reset deliveredSeq on
|
|
327
|
-
* reconnect" step is needed for this to be correct — collapsing to
|
|
328
|
-
* `cursor` exactly while stalled already produces the right answer on
|
|
329
|
-
* every long-poll retry path. NOT resetting it unconditionally on every
|
|
330
|
-
* retry lets `deliveredSeq` keep doing its job of not re-dispatching
|
|
331
|
-
* something already in flight while a handler is still running.
|
|
332
|
-
*/
|
|
277
|
+
/** A committed terminal can settle a failed offer receipt even if cloud
|
|
278
|
+
* cancellation has since filtered that offer from mailbox replay. */
|
|
279
|
+
retryTaskReceipts(taskId: string): void;
|
|
280
|
+
/** Only a durable acknowledgement can deduplicate a whole prefix. */
|
|
333
281
|
private dedupWatermark;
|
|
334
|
-
/** Design A: eagerly advance the in-memory delivery watermark — called for every `task.*` envelope `deliver()` admits past dedup, regardless of transport or of whether its handler has even started yet. */
|
|
335
|
-
private noteDelivered;
|
|
336
282
|
private process;
|
|
337
|
-
/**
|
|
338
|
-
* M4 Phase 4 (version-negotiation drill fix): `LongPollClient` calls this
|
|
339
|
-
* for a batch entry it could not parse into a known `Envelope` at all (an
|
|
340
|
-
* unrecognized message type (see `long-poll-transport.ts`'s own doc
|
|
341
|
-
* comment on `parseLooseEventsPollResponse`) but which still carried a numeric,
|
|
342
|
-
* task-class envelope-level `seq` (the caller only invokes this for a
|
|
343
|
-
* `task.`-prefixed type — see `long-poll-transport.ts`'s own
|
|
344
|
-
* `extractSkippableSeq`; `conn.*`-shaped or type-less entries never reach
|
|
345
|
-
* here at all, mirroring F2's "conn.* is never cursor-tracked" rule).
|
|
346
|
-
* There is no real `Envelope` to hand to a handler — a genuinely
|
|
347
|
-
* unrecognized type has nothing this build could ever act on.
|
|
348
|
-
*
|
|
349
|
-
* GATEKEEPER-CAUGHT REGRESSION (fixed here): this used to call
|
|
350
|
-
* `advanceCursor(seq)` DIRECTLY, synchronously, the instant a skip was
|
|
351
|
-
* detected in `LongPollClient.loop()`'s per-entry for-loop. That is NOT
|
|
352
|
-
* "instantaneous and race-free" the way the previous version of this
|
|
353
|
-
* comment claimed — the hazard was never the skip racing against itself,
|
|
354
|
-
* it was the skip racing AHEAD of an EARLIER real envelope in the SAME
|
|
355
|
-
* batch that is still in flight on `processingChain` (`deliver()`, above,
|
|
356
|
-
* only ever CHAINS `process()` onto that promise chain — it never awaits
|
|
357
|
-
* it before returning). Concretely, batch `[real seq1, unknown seq2]`:
|
|
358
|
-
* `deliver(seq1)` chains `process(seq1)` but returns immediately without
|
|
359
|
-
* running it; the for-loop then reaches `seq2` and (pre-fix) called
|
|
360
|
-
* `advanceCursor(2)` synchronously, BEFORE `process(seq1)` had even
|
|
361
|
-
* started, let alone failed. If `seq1`'s handler then failed,
|
|
362
|
-
* `stalledAtSeq` became 1 — but the durable cursor was already 2, so
|
|
363
|
-
* `dedupWatermark()` returned 2, and every future redelivery of seq1 was
|
|
364
|
-
* dedup-dropped as "already past the cursor" forever: permanent envelope
|
|
365
|
-
* loss, exactly the F3 bug class the whole `stalledAtSeq`/frozen-watermark
|
|
366
|
-
* mechanism exists to prevent.
|
|
367
|
-
*
|
|
368
|
-
* Fix: the cursor-advancing half is now CHAINED onto `processingChain`
|
|
369
|
-
* too, exactly like `process()`'s own post-handler bookkeeping — so it
|
|
370
|
-
* only ever runs once every earlier envelope already queued ahead of it
|
|
371
|
-
* has fully settled (success or failure), and can observe `stalledAtSeq`'s
|
|
372
|
-
* REAL, up-to-date value rather than whatever it happened to be at the
|
|
373
|
-
* instant the skip was first noticed. The guard mirrors `process()`'s own
|
|
374
|
-
* success-path guard exactly: never advance past a still-unresolved
|
|
375
|
-
* earlier failure, unless (degenerate, cannot really happen for a skip)
|
|
376
|
-
* this exact seq IS the stalled one.
|
|
377
|
-
*
|
|
378
|
-
* `noteDelivered` (the eager, in-memory watermark) stays UNCHAINED —
|
|
379
|
-
* called immediately, unconditionally, regardless of `stalledAtSeq` —
|
|
380
|
-
* matching `deliver()`'s own eager, unconditional call for a real
|
|
381
|
-
* envelope: its only job is "don't re-dispatch something already handed off,"
|
|
382
|
-
* independent of outcome, and that property does not depend on FIFO
|
|
383
|
-
* ordering the way the DURABLE cursor does.
|
|
384
|
-
*
|
|
385
|
-
* Deliberately NO top-level `dedupWatermark() <= seq` early-return before
|
|
386
|
-
* queuing the chained callback (an earlier draft of this fix had one, and
|
|
387
|
-
* it was itself subtly wrong): `deliveredSeq` can already reflect a seq
|
|
388
|
-
* from the FIRST time it was ever seen, while the DURABLE cursor is still
|
|
389
|
-
* behind it because a stall intervened before that seq's chained
|
|
390
|
-
* advancement ran — a pre-check keyed on `deliveredSeq` would then
|
|
391
|
-
* wrongly treat a LATER redelivery of the same seq (arriving once the
|
|
392
|
-
* stall has since cleared) as "already accounted for" and never queue
|
|
393
|
-
* another attempt, permanently stranding the cursor one seq short. Always
|
|
394
|
-
* queuing is safe and cheap: `advanceCursor`'s own `seq <= this.cursor`
|
|
395
|
-
* guard already makes a genuinely-redundant call a no-op, so there is no
|
|
396
|
-
* correctness reason to short-circuit earlier, only a (here, unnecessary)
|
|
397
|
-
* micro-optimization one.
|
|
398
|
-
*/
|
|
399
|
-
private noteSkippedSeq;
|
|
400
|
-
/**
|
|
401
|
-
* Finding R1 (cross-model re-review — was NOT-CLOSED against F1):
|
|
402
|
-
* `LongPollClient` calls this for a batch entry whose `type` it
|
|
403
|
-
* recognized but whose payload failed schema validation
|
|
404
|
-
* ({@link EnvelopeValidationError}) — a genuine delivery failure at that
|
|
405
|
-
* seq, unlike `noteSkippedSeq`'s forward-compat case. Deliberately mirrors
|
|
406
|
-
* `process()`'s own catch block (`if (tracked && this.stalledAtSeq ===
|
|
407
|
-
* undefined) this.stalledAtSeq = envelope.seq;`) as closely as possible:
|
|
408
|
-
* the SAME "only the lowest unresolved failure holds the stall" rule, the
|
|
409
|
-
* SAME resulting freeze of `dedupWatermark()` at the durable cursor
|
|
410
|
-
* (protocol §9 keeps this seq alive), and — because it's the SAME
|
|
411
|
-
* `stalledAtSeq` field `process()`'s own post-success guard already
|
|
412
|
-
* checks — anything ELSE delivered after this seq (same batch or a later
|
|
413
|
-
* one) is automatically held back from advancing the cursor too, with
|
|
414
|
-
* zero changes needed to `process()` itself.
|
|
415
|
-
*
|
|
416
|
-
* Chained onto `processingChain` for exactly the reason `noteSkippedSeq`
|
|
417
|
-
* documents for its own identical chaining (see that method's sibling
|
|
418
|
-
* doc comment on `LongPollClient`, "GATEKEEPER-CAUGHT REGRESSION"): an
|
|
419
|
-
* EARLIER real envelope in the SAME batch may still be in flight on that
|
|
420
|
-
* FIFO chain when this is called (`deliver()` only ever chains
|
|
421
|
-
* `process()` onto it, never awaits before returning) — mutating
|
|
422
|
-
* `stalledAtSeq` synchronously here could race ahead of that still-
|
|
423
|
-
* unresolved earlier envelope. Chaining instead guarantees this only
|
|
424
|
-
* takes effect once every earlier-queued envelope has already settled,
|
|
425
|
-
* and reads `stalledAtSeq`'s real, up-to-date value rather than whatever
|
|
426
|
-
* it happened to be the instant the failure was first noticed.
|
|
427
|
-
*
|
|
428
|
-
* No `noteDelivered` call here (contrast `noteSkippedSeq`, which does
|
|
429
|
-
* call it): a validation-failed entry never becomes a real `Envelope` and
|
|
430
|
-
* never reaches `deliver()`, so it was never "delivered" in the eager
|
|
431
|
-
* in-memory-watermark sense that field tracks — there is nothing for it
|
|
432
|
-
* to eagerly mark. Once a corrected redelivery of this exact seq DOES
|
|
433
|
-
* arrive as a real envelope, it flows through the ordinary `deliver()`
|
|
434
|
-
* path (which calls `noteDelivered` itself) and, on success, clears the
|
|
435
|
-
* stall via `process()`'s own existing logic — no special-casing needed.
|
|
436
|
-
*/
|
|
283
|
+
/** Recorded synchronously at receive, before a later successful receipt can commit. */
|
|
437
284
|
private noteValidationFailure;
|
|
438
285
|
private advanceCursor;
|
|
439
286
|
private quarantineRejectedOutbound;
|
|
@@ -465,5 +465,7 @@ export declare function parseTeamWorkspaceJoinParams(value: unknown): TeamWorksp
|
|
|
465
465
|
export declare function parseTeamContextParams(value: unknown): TeamContextParams | undefined;
|
|
466
466
|
export declare function parseTeamMessagePostParams(value: unknown): TeamMessagePostParams | undefined;
|
|
467
467
|
export declare function parseTeamMessageReadParams(value: unknown): TeamMessageReadParams | undefined;
|
|
468
|
+
/** Exact local operator RPC; the shared read-parameter shape has no model identity fields. */
|
|
469
|
+
export declare function parseTeamNotificationSnapshotParams(value: unknown): TeamMessageReadParams | undefined;
|
|
468
470
|
export declare function parseTeamMessageAckParams(value: unknown): TeamMessageAckParams | undefined;
|
|
469
471
|
export declare function parseTeamMessageInspectParams(value: unknown): TeamMessageInspectParams | undefined;
|