@meistrari/agent-core 0.1.12 → 0.2.0-experimental.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.
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Credential isolation: resident supervisor loopback
|
|
2
|
+
|
|
3
|
+
This regression exercises the shared worker-to-supervisor transport on the
|
|
4
|
+
0.1.13 source line. It does not change provider behavior or package contracts.
|
|
5
|
+
|
|
6
|
+
The loopback supplies independently generated synthetic credentials for initial
|
|
7
|
+
bootstrap, reconnect rotation, process-restart bootstrap, Git authentication and
|
|
8
|
+
reverse credential RPC. Assertions verify that the provider factory receives the
|
|
9
|
+
initial credential, the existing provider receives the rotated credential, and
|
|
10
|
+
the recovered supervisor receives the replacement credential. Successful reconnect
|
|
11
|
+
also verifies that changing these secrets does not change immutable binding identity.
|
|
12
|
+
|
|
13
|
+
The test scans every file in its isolated supervisor state directory while SQLite
|
|
14
|
+
is open (including WAL), after shutdown, and after restart/shutdown. It scans
|
|
15
|
+
captured trace-level logger output, durable/ephemeral event records, readiness
|
|
16
|
+
snapshots and failure records. Literal, base64 and hex representations must be
|
|
17
|
+
absent. RPC completion emits only a boolean receipt, never the returned credential.
|
|
18
|
+
|
|
19
|
+
The observed run passed 188 assertions. Synthetic values are generated only in
|
|
20
|
+
memory. Only the test-owned temporary directory is cleaned afterward; no live
|
|
21
|
+
sandbox, workspace, validation database or production resource is touched.
|
|
22
|
+
|
|
23
|
+
## Limits
|
|
24
|
+
|
|
25
|
+
This uses a scripted provider and an in-memory worker control plane. It is not
|
|
26
|
+
proof for native Codex persistence, Postgres staging, Vault uploads, reusable E2B
|
|
27
|
+
snapshots, arbitrary provider error messages, or encoded/exfiltrated tool output.
|
|
28
|
+
Those gates require their own evidence. The separate native-Codex canary test
|
|
29
|
+
and live credential-expiry resume evidence supplement, rather than replace, it.
|
|
30
|
+
No release publication or admission enablement is part of this regression.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meistrari/agent-core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-experimental.0",
|
|
5
5
|
"packageManager": "bun@1.3.12",
|
|
6
6
|
"description": "Shared contracts and runtime modules for Tela coding-agent sandboxes: agent protocol, supervisor wire protocol, resident supervisor, worker runtime client, and Claude/Codex harness adapters.",
|
|
7
7
|
"license": "UNLICENSED",
|
|
@@ -19,6 +19,7 @@ export class ModelRebindingRun implements AgentRun {
|
|
|
19
19
|
private workspacePrepared = false
|
|
20
20
|
private workspaceChanging = false
|
|
21
21
|
private readonly lifetime = new AbortController()
|
|
22
|
+
private readonly controls = new Set<Promise<unknown>>()
|
|
22
23
|
|
|
23
24
|
constructor(run: AgentRun, private readonly reopen: (model: string, signal: AbortSignal) => Promise<AgentRun>, private readonly rootAdded?: (root: string) => void) {
|
|
24
25
|
this.run = run
|
|
@@ -41,11 +42,11 @@ export class ModelRebindingRun implements AgentRun {
|
|
|
41
42
|
})
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
respondUserInput: AgentRun['respondUserInput'] = async (command, options) => await this.run.respondUserInput(command, options)
|
|
45
|
-
interrupt: AgentRun['interrupt'] = async (command, options) => await this.run.interrupt(command, options)
|
|
45
|
+
respondUserInput: AgentRun['respondUserInput'] = async (command, options) => await this.withControl(signal => this.run.respondUserInput(command, { ...options, signal }), options)
|
|
46
|
+
interrupt: AgentRun['interrupt'] = async (command, options) => await this.withControl(signal => this.run.interrupt(command, { ...options, signal }), options)
|
|
46
47
|
|
|
47
48
|
async sendPrompt(command: SendPromptCommand, options: AgentOperationOptions = {}): Promise<AgentPromptAcceptance> {
|
|
48
|
-
if (this.dispatching || this.workspaceChanging)
|
|
49
|
+
if (this.dispatching || this.workspaceChanging || this.controls.size)
|
|
49
50
|
throw new AgentPromptDeferredError({ message: 'A prompt admission is already in progress.' })
|
|
50
51
|
const task = this.dispatchPrompt(command, options)
|
|
51
52
|
this.dispatching = task
|
|
@@ -112,6 +113,7 @@ export class ModelRebindingRun implements AgentRun {
|
|
|
112
113
|
throw new AgentRunStateError({ message: 'Stop does not target the bound run.' })
|
|
113
114
|
this.stopped = true
|
|
114
115
|
this.lifetime.abort()
|
|
116
|
+
await Promise.allSettled([...this.controls])
|
|
115
117
|
await this.run.stop(command, options)
|
|
116
118
|
await this.dispatching?.catch(() => undefined)
|
|
117
119
|
await this.pump
|
|
@@ -122,6 +124,23 @@ export class ModelRebindingRun implements AgentRun {
|
|
|
122
124
|
return { provider: this.metadata.provider, sessionId: this.metadata.sessionId, providerSessionId: this.metadata.providerSessionId }
|
|
123
125
|
}
|
|
124
126
|
|
|
127
|
+
private async withControl<T>(operation: (signal: AbortSignal) => Promise<T>, options: AgentOperationOptions = {}): Promise<T> {
|
|
128
|
+
if (this.stopped)
|
|
129
|
+
throw new AgentRunStateError({ message: 'The run stopped.' })
|
|
130
|
+
if (this.changing || this.needsRebind)
|
|
131
|
+
throw new AgentPromptDeferredError({ message: 'The provider model is being rebound.' })
|
|
132
|
+
const signal = AbortSignal.any([this.lifetime.signal, ...(options.signal ? [options.signal] : [])])
|
|
133
|
+
const task = Promise.resolve().then(async () => {
|
|
134
|
+
signal.throwIfAborted()
|
|
135
|
+
return await operation(signal)
|
|
136
|
+
})
|
|
137
|
+
this.controls.add(task)
|
|
138
|
+
try {
|
|
139
|
+
return await task
|
|
140
|
+
}
|
|
141
|
+
finally { this.controls.delete(task) }
|
|
142
|
+
}
|
|
143
|
+
|
|
125
144
|
private async withWorkspaceChange(operation: () => Promise<void>): Promise<void> {
|
|
126
145
|
if (this.stopped)
|
|
127
146
|
throw new AgentRunStateError({ message: 'The run stopped.' })
|
package/src/provenance.gen.ts
CHANGED
|
@@ -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.
|
|
4
|
-
sha: "
|
|
5
|
-
buildTime: "2026-09-
|
|
3
|
+
version: "0.2.0-experimental.0",
|
|
4
|
+
sha: "da33c4f2db2875602c75e8ad3fde2d01d8ea7a94",
|
|
5
|
+
buildTime: "2026-09-22T18:15:52.470Z",
|
|
6
6
|
} as const
|