@meistrari/agent-core 0.2.0-experimental.9 → 0.3.1-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.
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.3.1-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",
|
|
@@ -57,6 +57,9 @@ export interface CodexEventMapperState {
|
|
|
57
57
|
readonly endedSubagentIds: Set<string>
|
|
58
58
|
readonly subagentByThreadId: Map<string, CodexSubagentRef>
|
|
59
59
|
readonly subagentById: Map<string, CodexSubagentRef>
|
|
60
|
+
readonly ownerTurnIdBySubagentId: Map<string, string>
|
|
61
|
+
readonly draftsAwaitingOwnerByActorId: Map<string, AgentEventDraft[]>
|
|
62
|
+
readonly unreportedEndedSubagentsByParent: Map<string, Map<string, string>>
|
|
60
63
|
readonly subagentNameByThreadId: Map<string, string>
|
|
61
64
|
readonly pendingDraftsByThreadId: Map<string, CodexUnownedTurnEventDraft[]>
|
|
62
65
|
readonly turnErrorsById: Map<string, AgentError>
|
|
@@ -80,6 +83,9 @@ export function createCodexEventMapperState(): CodexEventMapperState {
|
|
|
80
83
|
endedSubagentIds: new Set(),
|
|
81
84
|
subagentByThreadId: new Map(),
|
|
82
85
|
subagentById: new Map(),
|
|
86
|
+
ownerTurnIdBySubagentId: new Map(),
|
|
87
|
+
draftsAwaitingOwnerByActorId: new Map(),
|
|
88
|
+
unreportedEndedSubagentsByParent: new Map(),
|
|
83
89
|
subagentNameByThreadId: new Map(),
|
|
84
90
|
pendingDraftsByThreadId: new Map(),
|
|
85
91
|
turnErrorsById: new Map(),
|
|
@@ -106,6 +112,52 @@ export function cacheCodexThreadMetadata(thread: CodexThreadMetadata, state: Cod
|
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
export function mapCodexNotification(notification: CodexNotification, state: CodexEventMapperState): AgentEventDraft[] {
|
|
115
|
+
return attributeSubagentDraftsToOwnerTurn(mapNotificationDrafts(notification, state), state)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function attributeSubagentDraftsToOwnerTurn(drafts: AgentEventDraft[], state: CodexEventMapperState): AgentEventDraft[] {
|
|
119
|
+
return drafts.flatMap(draft => attributeSubagentDraft(draft, state))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function attributeSubagentDraft(draft: AgentEventDraft, state: CodexEventMapperState): AgentEventDraft[] {
|
|
123
|
+
if (!('actor' in draft) || draft.actor.type !== 'subagent')
|
|
124
|
+
return [draft]
|
|
125
|
+
const { subagentId, parentActorId } = draft.actor
|
|
126
|
+
if (draft.type === 'turn.started' || draft.type === 'turn.ended')
|
|
127
|
+
return []
|
|
128
|
+
let ownerTurnId = state.ownerTurnIdBySubagentId.get(subagentId)
|
|
129
|
+
if (!ownerTurnId && draft.type === 'subagent.started') {
|
|
130
|
+
ownerTurnId = parentActorId === mainActor.actorId ? draft.turnId : state.ownerTurnIdBySubagentId.get(parentActorId)
|
|
131
|
+
if (ownerTurnId)
|
|
132
|
+
state.ownerTurnIdBySubagentId.set(subagentId, ownerTurnId)
|
|
133
|
+
else
|
|
134
|
+
return awaitOwner(parentActorId, draft, state)
|
|
135
|
+
}
|
|
136
|
+
if (!ownerTurnId && parentActorId === mainActor.actorId)
|
|
137
|
+
ownerTurnId = state.currentMainTurn.status === 'open' ? state.currentMainTurn.turnId : draft.turnId
|
|
138
|
+
if (!ownerTurnId)
|
|
139
|
+
return awaitOwner(subagentId, draft, state)
|
|
140
|
+
if (draft.type === 'subagent.ended') {
|
|
141
|
+
const pending = state.unreportedEndedSubagentsByParent.get(parentActorId) ?? new Map<string, string>()
|
|
142
|
+
pending.set(subagentId, draft.payload.status)
|
|
143
|
+
state.unreportedEndedSubagentsByParent.set(parentActorId, pending)
|
|
144
|
+
}
|
|
145
|
+
const attributed: AgentEventDraft = { ...draft, turnId: ownerTurnId }
|
|
146
|
+
if (draft.type !== 'subagent.started')
|
|
147
|
+
return [attributed]
|
|
148
|
+
const awaiting = state.draftsAwaitingOwnerByActorId.get(subagentId) ?? []
|
|
149
|
+
state.draftsAwaitingOwnerByActorId.delete(subagentId)
|
|
150
|
+
return [attributed, ...attributeSubagentDraftsToOwnerTurn(awaiting, state)]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function awaitOwner(actorId: string, draft: AgentEventDraft, state: CodexEventMapperState): AgentEventDraft[] {
|
|
154
|
+
const awaiting = state.draftsAwaitingOwnerByActorId.get(actorId) ?? []
|
|
155
|
+
awaiting.push(draft)
|
|
156
|
+
state.draftsAwaitingOwnerByActorId.set(actorId, awaiting)
|
|
157
|
+
return []
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function mapNotificationDrafts(notification: CodexNotification, state: CodexEventMapperState): AgentEventDraft[] {
|
|
109
161
|
// Codex has many app-server notifications; the runtime maps the subset that has a provider-neutral AgentEvent.
|
|
110
162
|
|
|
111
163
|
switch (notification.method) {
|
|
@@ -265,11 +317,11 @@ function toolCallStart(item: CodexStartedItem): { toolName: string, input: JsonV
|
|
|
265
317
|
return undefined
|
|
266
318
|
|
|
267
319
|
if (item.type === 'commandExecution')
|
|
268
|
-
return { toolName, input: toJsonObject({ command: Array.isArray(item.command) ? item.command.join(' ') : String(item.command ?? ''), cwd: item.cwd }) }
|
|
320
|
+
return { toolName, input: toJsonObject({ command: unwrapShellCommand(Array.isArray(item.command) ? item.command.join(' ') : String(item.command ?? '')), cwd: item.cwd }) }
|
|
269
321
|
if (item.type === 'webSearch')
|
|
270
322
|
return { toolName, input: toJsonObject({ query: optionalNonEmpty(item.query) }) }
|
|
271
323
|
if (item.type === 'fileChange')
|
|
272
|
-
return { toolName, input: jsonInput({ files: item.changes.map(change => removeUndefined({ path: change.path, kind: change.kind?.type })) }) }
|
|
324
|
+
return { toolName, input: jsonInput({ file_path: item.changes.map(change => change.path).join(', '), files: item.changes.map(change => removeUndefined({ path: change.path, kind: change.kind?.type })) }) }
|
|
273
325
|
if (item.type === 'imageView')
|
|
274
326
|
return { toolName, input: toJsonObject({ path: item.path }) }
|
|
275
327
|
if (item.type === 'imageGeneration')
|
|
@@ -283,6 +335,17 @@ function toolCallStart(item: CodexStartedItem): { toolName: string, input: JsonV
|
|
|
283
335
|
return undefined
|
|
284
336
|
}
|
|
285
337
|
|
|
338
|
+
const SHELL_WRAPPER = /^(?:\/(?:usr\/)?bin\/)?(?:ba|z)?sh -l?c (?:'((?:[^']|'\\'')*)'|"((?:[^"\\]|\\.)*)")$/s
|
|
339
|
+
|
|
340
|
+
export function unwrapShellCommand(command: string): string {
|
|
341
|
+
const match = SHELL_WRAPPER.exec(command.trim())
|
|
342
|
+
if (!match)
|
|
343
|
+
return command
|
|
344
|
+
if (match[1] !== undefined)
|
|
345
|
+
return match[1].replaceAll(`'\\''`, `'`)
|
|
346
|
+
return match[2]!.replace(/\\([\\"$`])/g, '$1')
|
|
347
|
+
}
|
|
348
|
+
|
|
286
349
|
function toolNameForItem(item: CodexStartedItem | CodexCompletedItem): string | undefined {
|
|
287
350
|
if (item.type === 'commandExecution')
|
|
288
351
|
return CANONICAL_TOOL.bash
|
|
@@ -586,6 +649,7 @@ function mapCollabAgentToolCompleted({ turnId, threadId, item, mapperState }: {
|
|
|
586
649
|
toolCallId: item.id,
|
|
587
650
|
toolName: item.tool,
|
|
588
651
|
status: item.status === 'failed' ? 'failed' as const : 'completed' as const,
|
|
652
|
+
output: item.status === 'failed' ? undefined : collabToolOutput(collabToolSummary(item, mapperState)),
|
|
589
653
|
error: item.status === 'failed' ? { message: `Codex ${item.tool} failed.` } : undefined,
|
|
590
654
|
}),
|
|
591
655
|
},
|
|
@@ -666,7 +730,7 @@ function mapSubAgentActivityCompleted(input: { turnId: string, threadId: string,
|
|
|
666
730
|
state.subagentById.set(item.agentThreadId, actor)
|
|
667
731
|
return [
|
|
668
732
|
...emitOrBufferByThread({ draft: { type: 'tool.call.started', turnId, payload: { toolCallId: item.id, toolName: 'spawnAgent' } }, threadId, state }),
|
|
669
|
-
...emitOrBufferByThread({ draft: { type: 'tool.call.completed', turnId, payload: { toolCallId: item.id, toolName: 'spawnAgent', status: 'completed' } }, threadId, state }),
|
|
733
|
+
...emitOrBufferByThread({ draft: { type: 'tool.call.completed', turnId, payload: { toolCallId: item.id, toolName: 'spawnAgent', status: 'completed', output: collabToolOutput(item.agentPath) } }, threadId, state }),
|
|
670
734
|
{
|
|
671
735
|
type: 'subagent.started',
|
|
672
736
|
turnId,
|
|
@@ -680,7 +744,7 @@ function mapSubAgentActivityCompleted(input: { turnId: string, threadId: string,
|
|
|
680
744
|
if (item.kind === 'interacted') {
|
|
681
745
|
return [
|
|
682
746
|
...emitOrBufferByThread({ draft: { type: 'tool.call.started', turnId, payload: { toolCallId: item.id, toolName: 'sendInput' } }, threadId, state }),
|
|
683
|
-
...emitOrBufferByThread({ draft: { type: 'tool.call.completed', turnId, payload: { toolCallId: item.id, toolName: 'sendInput', status: 'completed' } }, threadId, state }),
|
|
747
|
+
...emitOrBufferByThread({ draft: { type: 'tool.call.completed', turnId, payload: { toolCallId: item.id, toolName: 'sendInput', status: 'completed', output: collabToolOutput(item.agentPath) } }, threadId, state }),
|
|
684
748
|
]
|
|
685
749
|
}
|
|
686
750
|
|
|
@@ -703,6 +767,26 @@ function mapSubAgentActivityCompleted(input: { turnId: string, threadId: string,
|
|
|
703
767
|
}]
|
|
704
768
|
}
|
|
705
769
|
|
|
770
|
+
function collabToolSummary(item: CodexCollabAgentToolCompletedItem, state: CodexEventMapperState): string {
|
|
771
|
+
const name = (threadId: string) => state.subagentByThreadId.get(threadId)?.name ?? state.subagentNameByThreadId.get(threadId) ?? threadId
|
|
772
|
+
const parentActorId = item.senderThreadId === state.mainThreadId ? mainActor.actorId : item.senderThreadId
|
|
773
|
+
const unreported = state.unreportedEndedSubagentsByParent.get(parentActorId)
|
|
774
|
+
const states = Object.entries(item.agentsStates).map(([threadId, agentState]) => {
|
|
775
|
+
unreported?.delete(threadId)
|
|
776
|
+
return `${name(threadId)}: ${agentState.status}`
|
|
777
|
+
})
|
|
778
|
+
if (states.length)
|
|
779
|
+
return states.join('\n')
|
|
780
|
+
if (item.receiverThreadIds.length)
|
|
781
|
+
return item.receiverThreadIds.map(name).join('\n')
|
|
782
|
+
state.unreportedEndedSubagentsByParent.delete(parentActorId)
|
|
783
|
+
return [...unreported ?? []].map(([threadId, status]) => `${name(threadId)}: ${status}`).join('\n') || item.tool
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
function collabToolOutput(text: string): AgentToolResult {
|
|
787
|
+
return { success: true, content: [{ type: 'text', text }] }
|
|
788
|
+
}
|
|
789
|
+
|
|
706
790
|
function mapChildTurnCompleted(input: {
|
|
707
791
|
threadId: string
|
|
708
792
|
turnId: string
|
|
@@ -853,10 +937,9 @@ function subagentPayloadRef(actor: CodexSubagentRef): Pick<CodexSubagentRef, 'ac
|
|
|
853
937
|
|
|
854
938
|
function collabToolInput(item: CodexCollabAgentToolStartedItem): JsonObject {
|
|
855
939
|
return toJsonObject({
|
|
856
|
-
|
|
857
|
-
receiverThreadIds: item.receiverThreadIds.join(','),
|
|
858
|
-
|
|
859
|
-
model: item.model,
|
|
940
|
+
prompt: optionalNonEmpty(item.prompt),
|
|
941
|
+
receiverThreadIds: optionalNonEmpty(item.receiverThreadIds.join(',')),
|
|
942
|
+
model: optionalNonEmpty(item.model),
|
|
860
943
|
reasoningEffort: typeof item.reasoningEffort === 'string' ? item.reasoningEffort : undefined,
|
|
861
944
|
})
|
|
862
945
|
}
|
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-10-
|
|
3
|
+
version: "0.3.1-experimental.0",
|
|
4
|
+
sha: "0fe0d37e1a4d2965fb8da08b3160ac676f1229e1",
|
|
5
|
+
buildTime: "2026-10-26T12:38:01.769Z",
|
|
6
6
|
} as const
|
package/src/steps/projector.ts
CHANGED
|
@@ -152,14 +152,16 @@ export class DurableStepProjector {
|
|
|
152
152
|
: event.type.startsWith('reasoning.') ? 'reasoning' : undefined
|
|
153
153
|
if (!kind || !('turnId' in event)) {
|
|
154
154
|
const frames: WireEventBody[] = []
|
|
155
|
-
if (event.type === 'turn.ended' || event.type === 'session.ended') {
|
|
155
|
+
if (event.type === 'turn.ended' || event.type === 'session.ended' || event.type === 'subagent.ended') {
|
|
156
156
|
for (const row of this.db.query<{ body: string, last_event_id: string | null }, []>('select body, last_event_id from steps').all()) {
|
|
157
157
|
const step = JSON.parse(row.body) as StepDetailV1
|
|
158
158
|
if (step.sessionId !== event.sessionId || step.providerSessionId !== event.providerSessionId)
|
|
159
159
|
continue
|
|
160
160
|
if ((step.status !== 'running' && row.last_event_id !== event.eventId) || (event.type === 'turn.ended' && (step.turnId !== event.turnId || step.actor.actorId !== event.actor.actorId)))
|
|
161
161
|
continue
|
|
162
|
-
|
|
162
|
+
if (event.type === 'subagent.ended' && step.actor.actorId !== event.actor.actorId)
|
|
163
|
+
continue
|
|
164
|
+
step.status = event.type !== 'session.ended' && event.payload.status === 'failed' ? 'failed' : 'interrupted'
|
|
163
165
|
step.incomplete = true
|
|
164
166
|
step.endedAt = event.timestamp
|
|
165
167
|
frames.push(...await this.finish(step))
|
|
@@ -75,9 +75,10 @@ export async function createResidentSupervisor(input: {
|
|
|
75
75
|
credentials: activation.envelope.credentials,
|
|
76
76
|
gitToken: activation.envelope.gitToken,
|
|
77
77
|
logger: input.logger,
|
|
78
|
-
onFatal: error =>
|
|
79
|
-
error
|
|
80
|
-
|
|
78
|
+
onFatal: (error) => {
|
|
79
|
+
input.logger.error({ err: error }, 'Supervisor agent runtime failed')
|
|
80
|
+
requestShutdown(error instanceof SupervisorConfigurationError ? TERMINAL_ERROR_CODE : RECOVERABLE_ERROR_CODE)
|
|
81
|
+
},
|
|
81
82
|
})
|
|
82
83
|
}
|
|
83
84
|
else {
|