@meistrari/agent-core 0.0.0 → 0.1.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.
Files changed (83) hide show
  1. package/README.md +24 -3
  2. package/bin/supervisor.ts +116 -0
  3. package/package.json +42 -3
  4. package/scripts/build-supervisor-executable.ts +32 -0
  5. package/src/agents/agent-error-serializer.ts +23 -0
  6. package/src/agents/agent-event-stream.ts +81 -0
  7. package/src/agents/agent-id.ts +17 -0
  8. package/src/agents/agent-operation.ts +11 -0
  9. package/src/agents/agent-provider.ts +37 -0
  10. package/src/agents/agent-run.ts +32 -0
  11. package/src/agents/agent-runtime-error.ts +161 -0
  12. package/src/agents/agent-session-events.ts +32 -0
  13. package/src/agents/agent-tool-runner.ts +83 -0
  14. package/src/agents/agent-tool.ts +111 -0
  15. package/src/agents/author-context.ts +36 -0
  16. package/src/agents/claude/claude-command-mapper.ts +234 -0
  17. package/src/agents/claude/claude-event-mapper.ts +736 -0
  18. package/src/agents/claude/claude-provider.ts +191 -0
  19. package/src/agents/claude/claude-run.ts +464 -0
  20. package/src/agents/claude/claude-tool-mapper.ts +186 -0
  21. package/src/agents/claude/index.ts +1 -0
  22. package/src/agents/codex/codex-auth.ts +34 -0
  23. package/src/agents/codex/codex-command-mapper.ts +78 -0
  24. package/src/agents/codex/codex-event-mapper.ts +708 -0
  25. package/src/agents/codex/codex-json-rpc-client.ts +326 -0
  26. package/src/agents/codex/codex-protocol.ts +36 -0
  27. package/src/agents/codex/codex-provider.ts +1050 -0
  28. package/src/agents/codex/codex-run.ts +404 -0
  29. package/src/agents/codex/codex-skill-catalog.ts +158 -0
  30. package/src/agents/codex/codex-skill-roots.ts +19 -0
  31. package/src/agents/codex/codex-tool-mapper.ts +55 -0
  32. package/src/agents/codex/codex.errors.ts +68 -0
  33. package/src/agents/codex/generated/meta.gen.ts +606 -0
  34. package/src/agents/codex/generated/namespaces.gen.ts +311 -0
  35. package/src/agents/codex/generated/schema.gen.ts +34883 -0
  36. package/src/agents/codex/index.ts +2 -0
  37. package/src/agents/index.ts +14 -0
  38. package/src/agents/input-attachment-preparation.ts +86 -0
  39. package/src/agents/input-attachment.errors.ts +16 -0
  40. package/src/agents/instructions.ts +8 -0
  41. package/src/agents/materialized-input-attachment.ts +26 -0
  42. package/src/agents/message-id.ts +23 -0
  43. package/src/agents/normalize.ts +8 -0
  44. package/src/agents/sandbox-environment.ts +1 -0
  45. package/src/agents/tools/ping.tool.ts +13 -0
  46. package/src/agents/user-input-request.ts +470 -0
  47. package/src/provenance.gen.ts +3 -3
  48. package/src/supervisor/agent-provider-factory.ts +189 -0
  49. package/src/supervisor/bootstrap-binder.ts +125 -0
  50. package/src/supervisor/config.ts +49 -0
  51. package/src/supervisor/control-authority-verifier.ts +135 -0
  52. package/src/supervisor/create-supervisor-runtime.ts +25 -0
  53. package/src/supervisor/errors.ts +24 -0
  54. package/src/supervisor/index.ts +34 -0
  55. package/src/supervisor/persistence/json.ts +21 -0
  56. package/src/supervisor/persistence/state-discovery.ts +56 -0
  57. package/src/supervisor/persistence/supervisor-store.ts +364 -0
  58. package/src/supervisor/ports/index.ts +109 -0
  59. package/src/supervisor/provider-factory.ts +37 -0
  60. package/src/supervisor/resident.ts +143 -0
  61. package/src/supervisor/rpc-client.ts +120 -0
  62. package/src/supervisor/runtime-handler.ts +309 -0
  63. package/src/supervisor/websocket-server.ts +434 -0
  64. package/src/supervisor-protocol/bootstrap.ts +1 -1
  65. package/src/template-onboarding.ts +47 -0
  66. package/src/testing/es256-test-keys.ts +73 -0
  67. package/src/testing/in-memory-runtime-control-plane.ts +205 -0
  68. package/src/testing/index.ts +6 -0
  69. package/src/testing/loopback-supervisor-connection.ts +71 -0
  70. package/src/testing/scripted-provider.ts +64 -0
  71. package/src/worker-runtime-client/command-pump.ts +132 -0
  72. package/src/worker-runtime-client/connection-attempt.ts +340 -0
  73. package/src/worker-runtime-client/control-authority-signer.ts +100 -0
  74. package/src/worker-runtime-client/e2b-supervisor-connection.ts +102 -0
  75. package/src/worker-runtime-client/frame-processor.ts +178 -0
  76. package/src/worker-runtime-client/index.ts +27 -0
  77. package/src/worker-runtime-client/lease-reconciler.ts +14 -0
  78. package/src/worker-runtime-client/ports.ts +137 -0
  79. package/src/worker-runtime-client/postgres-notification-listener.ts +91 -0
  80. package/src/worker-runtime-client/rpc-dispatcher.ts +27 -0
  81. package/src/worker-runtime-client/rpc-request-manager.ts +141 -0
  82. package/src/worker-runtime-client/sandbox-connection-runtime.ts +300 -0
  83. package/src/worker-runtime-client/token-crypto.ts +46 -0
@@ -1,6 +1,6 @@
1
1
  // Generated by scripts/write-provenance.ts. Do not edit by hand.
2
2
  export const generatedProvenance = {
3
- version: "0.0.0",
4
- sha: "3a023ce55b472e60cc194b759feac98f7ae61dba",
5
- buildTime: "2026-09-04T18:05:02.217Z",
3
+ version: "0.1.0",
4
+ sha: "9cd95365c6d39d1f44098fdd8006087c3adabfb4",
5
+ buildTime: "2026-09-04T20:01:49.852Z",
6
6
  } as const
@@ -0,0 +1,189 @@
1
+ import type { AgentProvider, AgentRun } from '../agents'
2
+ import type { AgentInputAttachmentPreparation } from '../agents/materialized-input-attachment'
3
+ import type { AgentEvent, AgentProviderId } from '../protocol'
4
+ import type { EphemeralCredentials, SessionBootstrapBody, SessionBootstrapGitToken } from '../supervisor-protocol/bootstrap'
5
+ import type { WireSendPromptCommand } from '../supervisor-protocol/command-body'
6
+ import type { WireEventBody } from '../supervisor-protocol/event-body'
7
+ import type { SupervisorAgentRunSnapshot } from '../supervisor-protocol/supervisor-agent-run-snapshot'
8
+ import type { SupervisorAgentRuntime, SupervisorProviderFactory } from './provider-factory'
9
+ import type { SupervisorRpcClient } from './rpc-client'
10
+ import { wrapAgentEvent } from '../supervisor-protocol/agent-event-wrapper'
11
+ import { createSupervisorProviderFactory } from './provider-factory'
12
+
13
+ export interface AgentProviderBindingStore {
14
+ load: (input: { sessionId: string, provider: AgentProviderId }) => Promise<string | undefined>
15
+ save: (input: { sessionId: string, provider: AgentProviderId, providerSessionId: string }) => Promise<void>
16
+ }
17
+
18
+ export interface AgentSupervisorProviderFactoryOptions {
19
+ createProvider: (input: {
20
+ bootstrap: SessionBootstrapBody
21
+ credentials?: EphemeralCredentials
22
+ gitToken?: SessionBootstrapGitToken
23
+ rpc: SupervisorRpcClient
24
+ }) => AgentProvider<'claude'> | AgentProvider<'codex'>
25
+ bindingStore: AgentProviderBindingStore
26
+ prepareInputAttachments?: (input: {
27
+ commandId: string
28
+ command: WireSendPromptCommand
29
+ signal: AbortSignal
30
+ }) => Promise<AgentInputAttachmentPreparation | undefined>
31
+ onSecretsRefreshed?: (input: {
32
+ credentials?: EphemeralCredentials
33
+ gitToken?: SessionBootstrapGitToken
34
+ }) => void | Promise<void>
35
+ }
36
+
37
+ export function createAgentSupervisorProviderFactory(
38
+ options: AgentSupervisorProviderFactoryOptions,
39
+ ): SupervisorProviderFactory {
40
+ return createSupervisorProviderFactory(async (input) => {
41
+ const provider = options.createProvider(input)
42
+ if (provider.id !== input.bootstrap.agent.provider)
43
+ throw new Error(`Provider factory returned ${provider.id} for ${input.bootstrap.agent.provider}.`)
44
+
45
+ const previousProviderSessionId = await options.bindingStore.load({
46
+ sessionId: input.bootstrap.sessionId,
47
+ provider: provider.id,
48
+ })
49
+ const sessionInput = {
50
+ sessionId: input.bootstrap.sessionId,
51
+ cwd: input.bootstrap.agent.cwd,
52
+ workspaceRepositoryRoots: input.bootstrap.repositories.map(repository => repository.root),
53
+ model: input.bootstrap.agent.model,
54
+ reasoningEffort: input.bootstrap.agent.reasoningEffort,
55
+ }
56
+ const run = provider.id === 'claude'
57
+ ? previousProviderSessionId
58
+ ? await provider.resumeSession({ ...sessionInput, provider: 'claude', providerSessionId: previousProviderSessionId }, { signal: input.signal })
59
+ : await provider.openSession({ ...sessionInput, provider: 'claude' }, { signal: input.signal })
60
+ : previousProviderSessionId
61
+ ? await provider.resumeSession({ ...sessionInput, provider: 'codex', providerSessionId: previousProviderSessionId }, { signal: input.signal })
62
+ : await provider.openSession({ ...sessionInput, provider: 'codex' }, { signal: input.signal })
63
+
64
+ await options.bindingStore.save({
65
+ sessionId: input.bootstrap.sessionId,
66
+ provider: provider.id,
67
+ providerSessionId: run.metadata.providerSessionId,
68
+ })
69
+
70
+ return new AgentSupervisorRuntime({
71
+ run,
72
+ prepareInputAttachments: options.prepareInputAttachments,
73
+ onSecretsRefreshed: options.onSecretsRefreshed,
74
+ })
75
+ })
76
+ }
77
+
78
+ class AgentSupervisorRuntime implements SupervisorAgentRuntime {
79
+ private state: SupervisorAgentRunSnapshot = { status: 'attached', agentState: null }
80
+ private emit: ((body: WireEventBody) => void) | undefined
81
+ private readonly pendingEvents: WireEventBody[] = []
82
+ private readonly eventPump: Promise<void>
83
+
84
+ constructor(private readonly input: {
85
+ run: AgentRun
86
+ prepareInputAttachments?: AgentSupervisorProviderFactoryOptions['prepareInputAttachments']
87
+ onSecretsRefreshed?: AgentSupervisorProviderFactoryOptions['onSecretsRefreshed']
88
+ }) {
89
+ this.eventPump = this.consumeEvents()
90
+ }
91
+
92
+ snapshot(): SupervisorAgentRunSnapshot {
93
+ return this.state
94
+ }
95
+
96
+ async handle(input: Parameters<SupervisorAgentRuntime['handle']>[0]): Promise<void> {
97
+ this.attachEmitter(input.emit)
98
+ const metadata = this.input.run.metadata
99
+ if (input.body.type === 'agent.send-prompt') {
100
+ const inputAttachmentPreparation = await this.input.prepareInputAttachments?.({
101
+ commandId: input.commandId,
102
+ command: input.body,
103
+ signal: input.signal,
104
+ })
105
+ await this.input.run.sendPrompt({
106
+ type: 'agent.send-prompt',
107
+ provider: metadata.provider,
108
+ sessionId: metadata.sessionId,
109
+ providerSessionId: metadata.providerSessionId,
110
+ commandId: input.commandId,
111
+ mode: input.body.mode,
112
+ origin: 'user',
113
+ prompt: input.body.prompt,
114
+ author: input.body.user
115
+ ? {
116
+ name: input.body.user.name,
117
+ email: input.body.user.email,
118
+ gitEmail: input.body.user.gitEmail,
119
+ }
120
+ : undefined,
121
+ }, {
122
+ signal: input.signal,
123
+ inputAttachmentPreparation,
124
+ senderContext: input.body.user?.senderContext,
125
+ })
126
+ return
127
+ }
128
+ if (input.body.type === 'agent.interrupt') {
129
+ await this.input.run.interrupt({
130
+ type: 'agent.interrupt',
131
+ provider: metadata.provider,
132
+ sessionId: metadata.sessionId,
133
+ providerSessionId: metadata.providerSessionId,
134
+ commandId: input.commandId,
135
+ }, { signal: input.signal })
136
+ return
137
+ }
138
+ await this.input.run.respondUserInput({
139
+ type: 'agent.respond-user-input',
140
+ provider: metadata.provider,
141
+ sessionId: metadata.sessionId,
142
+ providerSessionId: metadata.providerSessionId,
143
+ commandId: input.commandId,
144
+ requestId: input.body.requestId,
145
+ answers: input.body.answers,
146
+ }, { signal: input.signal })
147
+ }
148
+
149
+ async refreshSecrets(input: {
150
+ credentials?: EphemeralCredentials
151
+ gitToken?: SessionBootstrapGitToken
152
+ }): Promise<void> {
153
+ await this.input.onSecretsRefreshed?.(input)
154
+ }
155
+
156
+ async close(input: { signal: AbortSignal }): Promise<void> {
157
+ const metadata = this.input.run.metadata
158
+ await this.input.run.stop({
159
+ type: 'agent.stop',
160
+ provider: metadata.provider,
161
+ sessionId: metadata.sessionId,
162
+ providerSessionId: metadata.providerSessionId,
163
+ reason: 'supervisor_closed',
164
+ }, { signal: input.signal }).catch(() => undefined)
165
+ await this.eventPump.catch(() => undefined)
166
+ }
167
+
168
+ private attachEmitter(emit: (body: WireEventBody) => void): void {
169
+ this.emit = emit
170
+ for (const event of this.pendingEvents.splice(0))
171
+ emit(event)
172
+ }
173
+
174
+ private async consumeEvents(): Promise<void> {
175
+ for await (const event of this.input.run.events) {
176
+ if (event.type === 'session.state.changed')
177
+ this.state = { status: 'attached', agentState: event.payload.state }
178
+ this.emitEvent(event)
179
+ }
180
+ }
181
+
182
+ private emitEvent(event: AgentEvent): void {
183
+ const wrapped = wrapAgentEvent(event)
184
+ if (this.emit)
185
+ this.emit(wrapped)
186
+ else
187
+ this.pendingEvents.push(wrapped)
188
+ }
189
+ }
@@ -0,0 +1,125 @@
1
+ import type { Logger } from '../logger'
2
+ import type { SessionBootstrapBody } from '../supervisor-protocol/bootstrap'
3
+ import type { SessionBootstrapEnvelope } from '../supervisor-protocol/envelopes/control-plane-to-supervisor'
4
+ import type { RejectedCommandAckEnvelope, RuntimeStateEnvelope } from '../supervisor-protocol/envelopes/supervisor-to-control-plane'
5
+ import type { RuntimeConnectionHandler } from './runtime-handler'
6
+ import { supervisorSessionDirectory, TERMINAL_ERROR_CODE } from './config'
7
+ import { SupervisorConfigurationError } from './errors'
8
+ import { sha256CanonicalJson } from './persistence/json'
9
+ import { SupervisorStore } from './persistence/supervisor-store'
10
+
11
+ export interface BootstrapAdmission {
12
+ assertAllowed: (body: SessionBootstrapBody) => Promise<void>
13
+ }
14
+
15
+ export type SupervisorProcessBinding
16
+ = | { status: 'unbound' }
17
+ | { status: 'bound', store: SupervisorStore, sessionId: string }
18
+
19
+ type BootstrapBinding
20
+ = | { outcome: 'accepted', runtimeState: RuntimeStateEnvelope, activate: () => Promise<RuntimeConnectionHandler> }
21
+ | { outcome: 'rejected', ack: RejectedCommandAckEnvelope, terminate: () => void }
22
+
23
+ export type BootstrapBinder = (input: {
24
+ envelope: SessionBootstrapEnvelope
25
+ runtimeConnectionAttemptId: string
26
+ }) => Promise<BootstrapBinding>
27
+
28
+ export function createBootstrapBinder(input: {
29
+ stateRoot: string
30
+ getBinding: () => SupervisorProcessBinding
31
+ setBinding: (binding: SupervisorProcessBinding) => void
32
+ admission?: BootstrapAdmission
33
+ activate: (input: { store: SupervisorStore, envelope: SessionBootstrapEnvelope }) => Promise<RuntimeConnectionHandler>
34
+ shutdown: (code: number) => void
35
+ logger: Logger
36
+ }): BootstrapBinder {
37
+ return async (request) => {
38
+ try {
39
+ return await bind(request)
40
+ }
41
+ catch (error) {
42
+ if (!(error instanceof SupervisorConfigurationError))
43
+ throw error
44
+ input.logger.error({ code: error.code, err: error }, 'resident supervisor rejected immutable bootstrap configuration')
45
+ return {
46
+ outcome: 'rejected',
47
+ ack: {
48
+ kind: 'command.ack',
49
+ commandId: request.envelope.body.initialCommand.commandId,
50
+ commandSeq: request.envelope.body.initialCommand.commandSeq,
51
+ status: 'rejected',
52
+ errorCode: error.code,
53
+ detail: error.publicMessage.slice(0, 240),
54
+ },
55
+ terminate: () => input.shutdown(TERMINAL_ERROR_CODE),
56
+ }
57
+ }
58
+ }
59
+
60
+ async function bind(request: {
61
+ envelope: SessionBootstrapEnvelope
62
+ runtimeConnectionAttemptId: string
63
+ }): Promise<BootstrapBinding> {
64
+ let binding = input.getBinding()
65
+ if (binding.status === 'unbound') {
66
+ try {
67
+ await input.admission?.assertAllowed(request.envelope.body)
68
+ }
69
+ catch (cause) {
70
+ throw new SupervisorConfigurationError({
71
+ code: 'agent-core.bootstrap-admission-rejected',
72
+ message: 'Supervisor bootstrap admission rejected the immutable configuration.',
73
+ publicMessage: 'The sandbox configuration is not allowed.',
74
+ cause,
75
+ })
76
+ }
77
+ const sessionDirectory = supervisorSessionDirectory({
78
+ stateRoot: input.stateRoot,
79
+ sessionId: request.envelope.body.sessionId,
80
+ })
81
+ const store = SupervisorStore.open({ sqlitePath: `${sessionDirectory}/state.sqlite` })
82
+ try {
83
+ store.bind({
84
+ body: request.envelope.body,
85
+ connectionGeneration: request.envelope.connectionGeneration,
86
+ runtimeConnectionAttemptId: request.runtimeConnectionAttemptId,
87
+ })
88
+ }
89
+ catch (cause) {
90
+ store.close()
91
+ throw cause
92
+ }
93
+ binding = { status: 'bound', store, sessionId: request.envelope.body.sessionId }
94
+ input.setBinding(binding)
95
+ }
96
+ else {
97
+ if (binding.sessionId !== request.envelope.body.sessionId) {
98
+ throw new SupervisorConfigurationError({
99
+ code: 'agent-core.bootstrap-session-conflict',
100
+ message: 'Supervisor is already bound to another session.',
101
+ publicMessage: 'The sandbox is already bound to another session.',
102
+ })
103
+ }
104
+ const persisted = binding.store.binding()
105
+ if (!persisted || persisted.bodyHash !== sha256CanonicalJson(request.envelope.body)) {
106
+ throw new SupervisorConfigurationError({
107
+ code: 'agent-core.bootstrap-configuration-conflict',
108
+ message: 'Supervisor reconnect bootstrap differs from its immutable binding.',
109
+ publicMessage: 'The sandbox configuration cannot change after bootstrap.',
110
+ })
111
+ }
112
+ }
113
+ const acceptedBinding = binding
114
+ return {
115
+ outcome: 'accepted',
116
+ runtimeState: {
117
+ kind: 'runtime.state',
118
+ lastReceivedCommandSeq: acceptedBinding.store.lastReceivedCommandSeq(),
119
+ nextEventSeq: acceptedBinding.store.localEventMax() + 1,
120
+ agentRun: acceptedBinding.store.agentRunSnapshot(),
121
+ },
122
+ activate: async () => await input.activate({ store: acceptedBinding.store, envelope: request.envelope }),
123
+ }
124
+ }
125
+ }
@@ -0,0 +1,49 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { homedir } from 'node:os'
3
+ import { join } from 'node:path'
4
+
5
+ export const CLEAN_EXIT_CODE = 0
6
+ export const RECOVERABLE_ERROR_CODE = 75
7
+ export const TERMINAL_ERROR_CODE = 78
8
+ export const residentSupervisorPort = 8080
9
+ export const residentSupervisorUnixSocketPath = '/run/agent-core/control.sock'
10
+ export const residentSupervisorControlPath = '/control/ws'
11
+ export const residentSupervisorHealthPath = '/health'
12
+ export const sandboxControlAuthorityJwksPath = '/opt/agent-core/control-authority-jwks.json'
13
+ export const e2bSandboxIdPath = '/run/e2b/.E2B_SANDBOX_ID'
14
+
15
+ export interface ResidentSupervisorConfig {
16
+ host?: string
17
+ port?: number
18
+ unixSocketPath?: string
19
+ controlPath: string
20
+ healthPath: string
21
+ stateRoot: string
22
+ sandboxIdPath: string
23
+ authorityJwksPath: string
24
+ }
25
+
26
+ export function residentSupervisorConfig(input: {
27
+ homeDir?: string
28
+ authorityJwksPath?: string
29
+ sandboxIdPath?: string
30
+ stateRoot?: string
31
+ listen?: 'protected-unix' | 'loopback-tcp'
32
+ port?: number
33
+ } = {}): ResidentSupervisorConfig {
34
+ const listen = input.listen ?? 'protected-unix'
35
+ return {
36
+ ...(listen === 'protected-unix'
37
+ ? { unixSocketPath: residentSupervisorUnixSocketPath }
38
+ : { host: '127.0.0.1', port: input.port ?? residentSupervisorPort }),
39
+ controlPath: residentSupervisorControlPath,
40
+ healthPath: residentSupervisorHealthPath,
41
+ stateRoot: input.stateRoot ?? join(input.homeDir ?? homedir(), '.agent-core', 'supervisor'),
42
+ sandboxIdPath: input.sandboxIdPath ?? e2bSandboxIdPath,
43
+ authorityJwksPath: input.authorityJwksPath ?? sandboxControlAuthorityJwksPath,
44
+ }
45
+ }
46
+
47
+ export function supervisorSessionDirectory(input: { stateRoot: string, sessionId: string }): string {
48
+ return join(input.stateRoot, createHash('sha256').update(input.sessionId, 'utf8').digest('hex'))
49
+ }
@@ -0,0 +1,135 @@
1
+ import type { SandboxControlAuthorityClaims } from '../supervisor-protocol/control-authority'
2
+ import { Buffer } from 'node:buffer'
3
+ import { readFile } from 'node:fs/promises'
4
+ import { z } from 'zod'
5
+ import { InfrastructureError, ValidationError } from '../errors'
6
+ import {
7
+ sandboxControlAuthorityAssertionLifetimeSeconds,
8
+ sandboxControlAuthorityClaimsSchema,
9
+ sandboxControlAuthorityClockSkewSeconds,
10
+ sandboxControlAuthorityProtectedHeaderSchema,
11
+ sandboxControlAuthorityPublicJwksSchema,
12
+ } from '../supervisor-protocol/control-authority'
13
+
14
+ const verificationConfigSchema = z.object({
15
+ issuer: z.string().min(1),
16
+ jwks: sandboxControlAuthorityPublicJwksSchema,
17
+ }).strict()
18
+
19
+ export type VerifySupervisorControlAuthority = (input: {
20
+ assertion: string | null
21
+ providerSandboxId: string
22
+ sessionId: string
23
+ sessionSandboxId: string
24
+ connectionGeneration: number
25
+ runtimeConnectionAttemptId: string
26
+ eventAckFloor: number
27
+ }) => Promise<SandboxControlAuthorityClaims>
28
+
29
+ export async function createSupervisorControlAuthorityVerifier(input: {
30
+ jwksPath?: string
31
+ configuration?: { issuer: string, jwks: unknown }
32
+ }): Promise<VerifySupervisorControlAuthority> {
33
+ try {
34
+ const raw = input.configuration ?? JSON.parse(await readFile(requiredPath(input.jwksPath), 'utf8'))
35
+ const config = verificationConfigSchema.parse(raw)
36
+ const verificationKeys = new Map<string, CryptoKey>()
37
+ for (const jwk of config.jwks.keys) {
38
+ const key = await crypto.subtle.importKey('jwk', jwk, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify'])
39
+ verificationKeys.set(jwk.kid, key)
40
+ }
41
+ return async (request) => {
42
+ if (!request.assertion)
43
+ throw new ControlAuthorityAdmissionError({ reason: 'missing' })
44
+ let claims: SandboxControlAuthorityClaims
45
+ try {
46
+ const segments = request.assertion.split('.')
47
+ if (segments.length !== 3)
48
+ throw new Error('Authority assertion is not a compact JWS.')
49
+ const [encodedHeader, encodedPayload, encodedSignature] = segments
50
+ if (!encodedHeader || !encodedPayload || !encodedSignature)
51
+ throw new Error('Authority assertion contains an empty segment.')
52
+ const protectedHeader = sandboxControlAuthorityProtectedHeaderSchema.parse(JSON.parse(decodeBase64Url(encodedHeader)))
53
+ const verificationKey = verificationKeys.get(protectedHeader.kid)
54
+ if (!verificationKey)
55
+ throw new Error('Authority assertion key ID is unknown.')
56
+ const verified = await crypto.subtle.verify(
57
+ { name: 'ECDSA', hash: 'SHA-256' },
58
+ verificationKey,
59
+ Buffer.from(encodedSignature, 'base64url'),
60
+ new TextEncoder().encode(`${encodedHeader}.${encodedPayload}`),
61
+ )
62
+ if (!verified)
63
+ throw new Error('Authority assertion signature is invalid.')
64
+ claims = sandboxControlAuthorityClaimsSchema.parse(JSON.parse(decodeBase64Url(encodedPayload)))
65
+ verifyTemporalClaims({ claims, issuer: config.issuer })
66
+ }
67
+ catch (cause) {
68
+ throw new ControlAuthorityAdmissionError({ reason: 'unverified', cause })
69
+ }
70
+ if (claims.providerSandboxId !== request.providerSandboxId
71
+ || claims.sessionId !== request.sessionId
72
+ || claims.sessionSandboxId !== request.sessionSandboxId
73
+ || claims.connectionGeneration !== request.connectionGeneration
74
+ || claims.runtimeConnectionAttemptId !== request.runtimeConnectionAttemptId
75
+ || claims.eventAckFloor !== request.eventAckFloor) {
76
+ throw new ControlAuthorityAdmissionError({ reason: 'context-mismatch' })
77
+ }
78
+ return claims
79
+ }
80
+ }
81
+ catch (cause) {
82
+ if (cause instanceof ControlAuthorityConfigurationError)
83
+ throw cause
84
+ throw new ControlAuthorityConfigurationError({ cause })
85
+ }
86
+ }
87
+
88
+ export class ControlAuthorityConfigurationError extends InfrastructureError {
89
+ constructor(input: { cause: unknown }) {
90
+ super({
91
+ code: 'agent-core.control-authority-configuration-invalid',
92
+ message: 'Supervisor control-authority verification configuration is invalid.',
93
+ publicMessage: 'Supervisor control authority is unavailable.',
94
+ retryable: false,
95
+ cause: input.cause,
96
+ })
97
+ }
98
+ }
99
+
100
+ class ControlAuthorityAdmissionError extends ValidationError {
101
+ constructor(input: { reason: 'missing' | 'unverified' | 'context-mismatch', cause?: unknown }) {
102
+ super({
103
+ code: 'agent-core.control-authority-admission-denied',
104
+ message: 'Supervisor control-authority admission was denied.',
105
+ publicMessage: 'Supervisor control authority is invalid.',
106
+ details: { reason: input.reason },
107
+ cause: input.cause,
108
+ })
109
+ }
110
+ }
111
+
112
+ function requiredPath(path: string | undefined): string {
113
+ if (!path)
114
+ throw new Error('Control-authority JWKS path is required.')
115
+ return path
116
+ }
117
+
118
+ function verifyTemporalClaims(input: { claims: SandboxControlAuthorityClaims, issuer: string }): void {
119
+ const now = Math.floor(Date.now() / 1_000)
120
+ if (input.claims.iss !== input.issuer)
121
+ throw new Error('Authority assertion issuer is invalid.')
122
+ if (input.claims.iat > now + sandboxControlAuthorityClockSkewSeconds
123
+ || input.claims.nbf > now + sandboxControlAuthorityClockSkewSeconds
124
+ || input.claims.exp < now - sandboxControlAuthorityClockSkewSeconds) {
125
+ throw new Error('Authority assertion is outside its validity interval.')
126
+ }
127
+ if (input.claims.exp - input.claims.iat !== sandboxControlAuthorityAssertionLifetimeSeconds)
128
+ throw new Error('Authority assertion lifetime is invalid.')
129
+ }
130
+
131
+ function decodeBase64Url(value: string): string {
132
+ if (!/^[\w-]+$/u.test(value))
133
+ throw new Error('Authority assertion compact JWS segment is malformed.')
134
+ return Buffer.from(value, 'base64url').toString('utf8')
135
+ }
@@ -0,0 +1,25 @@
1
+ import type { Logger } from '../logger'
2
+ import type { BootstrapAdmission } from './bootstrap-binder'
3
+ import type { ResidentSupervisorConfig } from './config'
4
+ import type { SupervisorProviderFactory } from './provider-factory'
5
+ import { createResidentSupervisor } from './resident'
6
+
7
+ export interface SupervisorExtensions {
8
+ profile: { name: string, version: number, requiredRpcMethods: readonly string[] }
9
+ providerFactory: SupervisorProviderFactory
10
+ admission?: BootstrapAdmission
11
+ }
12
+
13
+ export async function createSupervisorRuntime(input: {
14
+ config: ResidentSupervisorConfig
15
+ extensions: SupervisorExtensions
16
+ logger: Logger
17
+ }) {
18
+ return await createResidentSupervisor({
19
+ config: input.config,
20
+ logger: input.logger,
21
+ providerFactory: input.extensions.providerFactory,
22
+ profile: input.extensions.profile,
23
+ admission: input.extensions.admission,
24
+ })
25
+ }
@@ -0,0 +1,24 @@
1
+ import { InfrastructureError, ValidationError } from '../errors'
2
+
3
+ export class SupervisorConfigurationError extends ValidationError {
4
+ constructor(input: { code?: string, message: string, publicMessage?: string, cause?: unknown }) {
5
+ super({
6
+ code: input.code ?? 'agent-core.supervisor-invalid-config',
7
+ message: input.message,
8
+ publicMessage: input.publicMessage ?? 'Supervisor configuration is invalid.',
9
+ cause: input.cause,
10
+ })
11
+ }
12
+ }
13
+
14
+ export class SupervisorPersistenceError extends InfrastructureError {
15
+ constructor(input: { code?: string, message: string, cause?: unknown }) {
16
+ super({
17
+ code: input.code ?? 'agent-core.supervisor-persistence-failed',
18
+ message: input.message,
19
+ publicMessage: 'Supervisor local persistence failed.',
20
+ retryable: false,
21
+ cause: input.cause,
22
+ })
23
+ }
24
+ }
@@ -0,0 +1,34 @@
1
+ export { createAgentSupervisorProviderFactory } from './agent-provider-factory'
2
+ export type { AgentProviderBindingStore, AgentSupervisorProviderFactoryOptions } from './agent-provider-factory'
3
+ export {
4
+ CLEAN_EXIT_CODE,
5
+ RECOVERABLE_ERROR_CODE,
6
+ residentSupervisorConfig,
7
+ TERMINAL_ERROR_CODE,
8
+ } from './config'
9
+ export type { ResidentSupervisorConfig } from './config'
10
+ export { createSupervisorControlAuthorityVerifier } from './control-authority-verifier'
11
+ export type { VerifySupervisorControlAuthority } from './control-authority-verifier'
12
+ export { createSupervisorRuntime } from './create-supervisor-runtime'
13
+ export type { SupervisorExtensions } from './create-supervisor-runtime'
14
+ export type {
15
+ InitializedWorkspaceRepository,
16
+ InstructionComposer,
17
+ LargePayloadStore,
18
+ MaterializedAgentInputAttachment,
19
+ ProviderCredentialsSource,
20
+ RepositorySyncAction,
21
+ SupervisorAgentTool,
22
+ SupervisorBroker,
23
+ SupervisorExtensionContext,
24
+ ToolRegistryFactory,
25
+ TurnHooks,
26
+ WorkspacePreparer,
27
+ WorkspaceSync,
28
+ WorkspaceSyncContext,
29
+ } from './ports'
30
+ export { createSupervisorProviderFactory } from './provider-factory'
31
+ export type { SupervisorAgentRuntime, SupervisorProviderFactory } from './provider-factory'
32
+ export { createResidentSupervisor } from './resident'
33
+ export type { ResidentSupervisor } from './resident'
34
+ export { SupervisorRpcClient, SupervisorRpcError } from './rpc-client'
@@ -0,0 +1,21 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { z } from 'zod'
3
+
4
+ export function canonicalJson(value: unknown): string {
5
+ return JSON.stringify(sortJsonValue(value)) ?? 'null'
6
+ }
7
+
8
+ export function sha256CanonicalJson(value: unknown): string {
9
+ return createHash('sha256').update(canonicalJson(value)).digest('hex')
10
+ }
11
+
12
+ function sortJsonValue(value: unknown): unknown {
13
+ if (Array.isArray(value))
14
+ return value.map(sortJsonValue)
15
+ const objectValue = z.record(z.string(), z.unknown()).safeParse(value)
16
+ if (!objectValue.success)
17
+ return value
18
+ return Object.fromEntries(
19
+ Object.keys(objectValue.data).sort().map(key => [key, sortJsonValue(objectValue.data[key])]),
20
+ )
21
+ }
@@ -0,0 +1,56 @@
1
+ import { readdir, stat } from 'node:fs/promises'
2
+ import { join } from 'node:path'
3
+ import { SupervisorPersistenceError } from '../errors'
4
+ import { SupervisorStore } from './supervisor-store'
5
+
6
+ export async function discoverPersistedSupervisorState(input: {
7
+ stateRoot: string
8
+ }): Promise<{ store: SupervisorStore, sessionId: string } | undefined> {
9
+ let entries
10
+ try {
11
+ entries = await readdir(input.stateRoot, { withFileTypes: true })
12
+ }
13
+ catch (error) {
14
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
15
+ return undefined
16
+ throw error
17
+ }
18
+ const stores: SupervisorStore[] = []
19
+ let selected: { store: SupervisorStore, sessionId: string } | undefined
20
+ try {
21
+ for (const entry of entries) {
22
+ if (!entry.isDirectory() || entry.isSymbolicLink())
23
+ continue
24
+ const sqlitePath = join(input.stateRoot, entry.name, 'state.sqlite')
25
+ try {
26
+ const databaseStat = await stat(sqlitePath)
27
+ if (!databaseStat.isFile())
28
+ continue
29
+ }
30
+ catch (error) {
31
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
32
+ continue
33
+ throw error
34
+ }
35
+ const store = SupervisorStore.open({ sqlitePath })
36
+ stores.push(store)
37
+ const binding = store.binding()
38
+ if (!binding)
39
+ continue
40
+ if (selected) {
41
+ throw new SupervisorPersistenceError({
42
+ code: 'agent-core.supervisor-multiple-bindings',
43
+ message: 'Resident supervisor found more than one session binding.',
44
+ })
45
+ }
46
+ selected = { store, sessionId: binding.body.sessionId }
47
+ }
48
+ return selected
49
+ }
50
+ finally {
51
+ for (const store of stores) {
52
+ if (store !== selected?.store)
53
+ store.close()
54
+ }
55
+ }
56
+ }