@meistrari/agent-core 0.2.0-experimental.0 → 0.2.0-experimental.2
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 +82 -0
- package/docs/consumer-capability-matrix.md +374 -0
- package/package.json +17 -10
- package/scripts/generate-codex-protocol.ts +711 -0
- package/src/agents/agent-operation.ts +8 -0
- package/src/agents/agent-provider.ts +3 -0
- package/src/agents/agent-run.ts +14 -2
- package/src/agents/agent-runtime-error.ts +28 -0
- package/src/agents/agent-session-events.ts +33 -0
- package/src/agents/agent-tool-runner.ts +12 -11
- package/src/agents/agent-tool.ts +12 -4
- package/src/agents/author-context.ts +1 -1
- package/src/agents/claude/claude-auth.ts +40 -0
- package/src/agents/claude/claude-browser-turn-metadata.ts +70 -0
- package/src/agents/claude/claude-code-process.ts +98 -0
- package/src/agents/claude/claude-command-mapper.ts +63 -3
- package/src/agents/claude/claude-desktop.ts +55 -0
- package/src/agents/claude/claude-event-mapper.ts +876 -124
- package/src/agents/claude/claude-file-change.ts +128 -0
- package/src/agents/claude/claude-provider.ts +344 -29
- package/src/agents/claude/claude-run.ts +922 -91
- package/src/agents/claude/claude-selected-repository-instructions.ts +91 -0
- package/src/agents/claude/claude-skill-catalog.ts +75 -0
- package/src/agents/claude/claude-steered-notifications.ts +180 -0
- package/src/agents/claude/claude-tool-mapper.ts +81 -2
- package/src/agents/claude/claude-workspace-skills.ts +87 -0
- package/src/agents/claude/index.ts +2 -0
- package/src/agents/codex/codex-auth-mapper.ts +27 -0
- package/src/agents/codex/codex-auth.ts +19 -0
- package/src/agents/codex/codex-browser-auth-broker.ts +320 -0
- package/src/agents/codex/codex-browser-auth-status.ts +55 -0
- package/src/agents/codex/codex-command-mapper.ts +38 -3
- package/src/agents/codex/codex-event-mapper.ts +375 -64
- package/src/agents/codex/codex-json-rpc-client.ts +66 -21
- package/src/agents/codex/codex-provider.ts +118 -236
- package/src/agents/codex/codex-run-auth.ts +113 -0
- package/src/agents/codex/codex-run.ts +428 -48
- package/src/agents/codex/codex-tool-mapper.ts +2 -2
- package/src/agents/codex/codex.errors.ts +8 -0
- package/src/agents/codex/generated/meta.gen.ts +144 -6
- package/src/agents/codex/generated/namespaces.gen.ts +92 -3
- package/src/agents/codex/generated/schema.gen.ts +24698 -15638
- package/src/agents/codex/lazy-codex-run-auth.ts +47 -0
- package/src/agents/index.ts +5 -0
- package/src/agents/input-attachment-preparation.ts +13 -0
- package/src/agents/mcp-tool-content.ts +82 -0
- package/src/agents/model-rebinding-run.ts +14 -3
- package/src/agents/selected-repository-instructions.ts +202 -0
- package/src/agents/session-context.ts +41 -0
- package/src/agents/subscription-token-refresh.ts +73 -0
- package/src/agents/user-input-request.ts +19 -20
- package/src/errors/index.ts +1 -1
- package/src/errors/validation-error.ts +6 -0
- package/src/protocol/agent-catalog.ts +159 -0
- package/src/protocol/agent-command.ts +54 -7
- package/src/protocol/agent-content.ts +36 -16
- package/src/protocol/agent-event.ts +210 -73
- package/src/protocol/agent-identity.ts +29 -0
- package/src/protocol/agent-json.ts +122 -8
- package/src/protocol/agent-metadata.ts +2 -2
- package/src/protocol/agent-model.ts +13 -1
- package/src/protocol/agent-notification.ts +110 -0
- package/src/protocol/agent-presentation.ts +71 -20
- package/src/protocol/agent-tool.ts +66 -10
- package/src/protocol/agent-usage.ts +4 -1
- package/src/protocol/agent-user-input.ts +4 -4
- package/src/protocol/agent-work.ts +12 -10
- package/src/protocol/index.ts +2 -0
- package/src/protocol/rejected-keys.ts +11 -0
- package/src/provenance.gen.ts +3 -3
- package/src/steps/contract.ts +4 -1
- package/src/steps/projector.ts +17 -1
- package/src/supervisor/agent-provider-factory.ts +60 -5
- package/src/supervisor/bootstrap-binder.ts +3 -2
- package/src/supervisor/index.ts +1 -1
- package/src/supervisor/persistence/supervisor-store.ts +22 -8
- package/src/supervisor/runtime-handler.ts +30 -2
- package/src/supervisor-protocol/agent-event-wrapper.ts +30 -0
- package/src/supervisor-protocol/bootstrap.ts +4 -1
- package/src/supervisor-protocol/command-body.ts +4 -1
- package/src/supervisor-protocol/envelopes/supervisor-to-control-plane.ts +1 -0
- package/src/testing/in-memory-runtime-control-plane.ts +118 -12
- package/src/testing/index.ts +1 -1
- package/src/worker-runtime-client/command-pump.ts +85 -10
- package/src/worker-runtime-client/connection-attempt.ts +95 -20
- package/src/worker-runtime-client/frame-processor.ts +242 -58
- package/src/worker-runtime-client/index.ts +8 -2
- package/src/worker-runtime-client/ports.ts +34 -2
- package/src/worker-runtime-client/rpc-request-manager.ts +152 -107
- package/src/worker-runtime-client/sandbox-connection-runtime.ts +72 -35
|
@@ -13,14 +13,128 @@ export interface JsonObject { readonly [key: string]: JsonValue }
|
|
|
13
13
|
export type JsonArray = readonly JsonValue[]
|
|
14
14
|
export type JsonValue = JsonPrimitive | JsonObject | JsonArray
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const jsonWireValueSchema = z.json()
|
|
17
|
+
type JsonWireValue = z.infer<typeof jsonWireValueSchema>
|
|
18
|
+
const jsonWireObjectSchema = z.record(z.string(), jsonWireValueSchema)
|
|
19
|
+
const jsonWireArraySchema = z.array(jsonWireValueSchema)
|
|
20
|
+
|
|
21
|
+
export const jsonValueSchema: ZodType<JsonValue> = z
|
|
22
|
+
.preprocess(encodeJsonObjectKeys, jsonWireValueSchema)
|
|
23
|
+
.overwrite(decodeJsonObjectKeys)
|
|
24
|
+
|
|
25
|
+
export const jsonObjectSchema: ZodType<JsonObject> = z
|
|
26
|
+
.preprocess(encodeJsonObjectKeys, jsonWireObjectSchema)
|
|
27
|
+
.overwrite(decodeJsonObject)
|
|
28
|
+
|
|
29
|
+
export const jsonArraySchema: ZodType<JsonArray> = z
|
|
30
|
+
.preprocess(encodeJsonObjectKeys, jsonWireArraySchema)
|
|
31
|
+
.overwrite(values => values.map(decodeJsonObjectKeys))
|
|
32
|
+
|
|
33
|
+
const JSON_VALIDATION_KEY_PREFIX = '$'
|
|
34
|
+
const invalidJsonValue = Symbol('invalid canonical JSON value')
|
|
35
|
+
|
|
36
|
+
function encodeJsonObjectKeys(value: unknown): unknown {
|
|
37
|
+
return encodeJsonValue(value, new WeakSet())
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function encodeJsonValue(value: unknown, ancestors: WeakSet<object>): unknown {
|
|
41
|
+
if (Array.isArray(value))
|
|
42
|
+
return encodeJsonArray(value, ancestors)
|
|
43
|
+
if (typeof value !== 'object' || value === null)
|
|
44
|
+
return value
|
|
45
|
+
if (!isPlainObject(value))
|
|
46
|
+
return invalidJsonValue
|
|
47
|
+
return encodeJsonObject(value, ancestors)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function encodeJsonArray(value: unknown[], ancestors: WeakSet<object>): unknown {
|
|
51
|
+
if (ancestors.has(value))
|
|
52
|
+
return invalidJsonValue
|
|
53
|
+
ancestors.add(value)
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const encoded: unknown[] = []
|
|
57
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
58
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index))
|
|
59
|
+
if (!descriptor?.enumerable || !('value' in descriptor))
|
|
60
|
+
return invalidJsonValue
|
|
61
|
+
const entry = encodeJsonValue(descriptor.value, ancestors)
|
|
62
|
+
if (entry === invalidJsonValue)
|
|
63
|
+
return invalidJsonValue
|
|
64
|
+
encoded.push(entry)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
68
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key)
|
|
69
|
+
if (!descriptor || !descriptor.enumerable)
|
|
70
|
+
continue
|
|
71
|
+
if (typeof key !== 'string' || !isArrayIndex(key, value.length))
|
|
72
|
+
return invalidJsonValue
|
|
73
|
+
}
|
|
74
|
+
return encoded
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
ancestors.delete(value)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function encodeJsonObject(value: object, ancestors: WeakSet<object>): unknown {
|
|
82
|
+
if (ancestors.has(value))
|
|
83
|
+
return invalidJsonValue
|
|
84
|
+
ancestors.add(value)
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const entries: Array<[string, unknown]> = []
|
|
88
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
89
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key)
|
|
90
|
+
if (!descriptor || !descriptor.enumerable)
|
|
91
|
+
continue
|
|
92
|
+
if (typeof key !== 'string' || !('value' in descriptor))
|
|
93
|
+
return invalidJsonValue
|
|
94
|
+
const entry = encodeJsonValue(descriptor.value, ancestors)
|
|
95
|
+
if (entry === invalidJsonValue)
|
|
96
|
+
return invalidJsonValue
|
|
97
|
+
entries.push([encodeJsonKey(key), entry])
|
|
98
|
+
}
|
|
99
|
+
return Object.fromEntries(entries)
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
ancestors.delete(value)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function decodeJsonObjectKeys(value: JsonWireValue): JsonWireValue {
|
|
107
|
+
if (Array.isArray(value))
|
|
108
|
+
return value.map(decodeJsonObjectKeys)
|
|
109
|
+
if (typeof value !== 'object' || value === null)
|
|
110
|
+
return value
|
|
111
|
+
return decodeJsonObject(value)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function decodeJsonObject(value: Record<string, JsonWireValue>): Record<string, JsonWireValue> {
|
|
115
|
+
const entries: Array<[string, JsonWireValue]> = []
|
|
116
|
+
for (const [key, entry] of Object.entries(value))
|
|
117
|
+
entries.push([decodeJsonKey(key), decodeJsonObjectKeys(entry)])
|
|
118
|
+
return Object.fromEntries(entries)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function isPlainObject(value: object): boolean {
|
|
122
|
+
const prototype = Object.getPrototypeOf(value)
|
|
123
|
+
return prototype === Object.prototype || prototype === null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isArrayIndex(value: string, length: number): boolean {
|
|
127
|
+
const index = Number(value)
|
|
128
|
+
return Number.isInteger(index) && index >= 0 && index < length && String(index) === value
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function encodeJsonKey(value: string): string {
|
|
132
|
+
return `${JSON_VALIDATION_KEY_PREFIX}${value}`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function decodeJsonKey(value: string): string {
|
|
136
|
+
return value.slice(JSON_VALIDATION_KEY_PREFIX.length)
|
|
137
|
+
}
|
|
24
138
|
|
|
25
139
|
const utf8Encoder = new TextEncoder()
|
|
26
140
|
|
|
@@ -12,13 +12,13 @@ export const codexAgentRunMetadataSchema = z.object({
|
|
|
12
12
|
provider: z.literal('codex'),
|
|
13
13
|
...metadataShape,
|
|
14
14
|
model: codexModelIdSchema.optional(),
|
|
15
|
-
})
|
|
15
|
+
})
|
|
16
16
|
|
|
17
17
|
export const claudeAgentRunMetadataSchema = z.object({
|
|
18
18
|
provider: z.literal('claude'),
|
|
19
19
|
...metadataShape,
|
|
20
20
|
model: claudeModelIdSchema.optional(),
|
|
21
|
-
})
|
|
21
|
+
})
|
|
22
22
|
|
|
23
23
|
export const agentRunMetadataSchema = z.discriminatedUnion('provider', [
|
|
24
24
|
codexAgentRunMetadataSchema,
|
|
@@ -8,15 +8,27 @@ import z from 'zod'
|
|
|
8
8
|
* schema that carries a model id accepts any non-empty string.
|
|
9
9
|
*/
|
|
10
10
|
export const codexModelIds = [
|
|
11
|
+
'gpt-6-astra',
|
|
11
12
|
'gpt-5.6-sol',
|
|
13
|
+
'gpt-5.6-terra',
|
|
14
|
+
'gpt-5.6-luna',
|
|
12
15
|
'gpt-5.5',
|
|
13
16
|
'gpt-5.4',
|
|
14
17
|
'gpt-5.4-mini',
|
|
15
|
-
'gpt-5.3-codex',
|
|
16
18
|
'gpt-5.2',
|
|
17
19
|
] as const
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Every Claude model id the wire accepts, including historical ids retained so stored
|
|
23
|
+
* `session.started` metadata keeps parsing. Add new ids; never remove one. The ids
|
|
24
|
+
* users can select live in `agent-catalog.ts`.
|
|
25
|
+
*/
|
|
19
26
|
export const claudeModelIds = [
|
|
27
|
+
'claude-opus-5-5',
|
|
28
|
+
'claude-sonnet-5',
|
|
29
|
+
'claude-fable-5-1',
|
|
30
|
+
'claude-opus-5',
|
|
31
|
+
'claude-fable-5',
|
|
20
32
|
'sonnet',
|
|
21
33
|
'claude-opus-4-8',
|
|
22
34
|
'opus',
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { JsonValue } from './agent-json'
|
|
2
|
+
import z from 'zod'
|
|
3
|
+
import { jsonValueSchema } from './agent-json'
|
|
4
|
+
|
|
5
|
+
export const agentNotificationSchema = jsonValueSchema
|
|
6
|
+
export const agentNotificationsSchema = z.array(agentNotificationSchema).min(1).max(20)
|
|
7
|
+
export const agentNotificationInstructionSchema = z.string().trim().min(1).max(4_096)
|
|
8
|
+
|
|
9
|
+
export const agentNotificationToolOutputMaxBytes = 64 * 1024
|
|
10
|
+
|
|
11
|
+
const notificationTransportEnvelopeType = 'coding_agent.notification_command.v1'
|
|
12
|
+
const textEncoder = new TextEncoder()
|
|
13
|
+
|
|
14
|
+
export type AgentNotification = JsonValue
|
|
15
|
+
export type AgentNotifications = z.infer<typeof agentNotificationsSchema>
|
|
16
|
+
export type AgentNotificationInstruction = z.infer<typeof agentNotificationInstructionSchema>
|
|
17
|
+
export interface AgentNotificationCommandPayload {
|
|
18
|
+
instruction: AgentNotificationInstruction | null
|
|
19
|
+
notifications: AgentNotifications
|
|
20
|
+
}
|
|
21
|
+
export type AgentNotificationToolOutput = AgentNotificationCommandPayload & {
|
|
22
|
+
commandId: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface AgentNotificationToolOutputInput {
|
|
26
|
+
commandId: string
|
|
27
|
+
instruction: AgentNotificationInstruction | null
|
|
28
|
+
notifications: readonly AgentNotification[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The supervisor wire command keeps its historical JSON-array shape so a newer control plane can
|
|
32
|
+
// still deliver notifications to image-baked older sandboxes. The generated command id prevents an
|
|
33
|
+
// observation value from masquerading as the trusted envelope before the command exists.
|
|
34
|
+
const notificationTransportEnvelopeSchema = z.object({
|
|
35
|
+
type: z.literal(notificationTransportEnvelopeType),
|
|
36
|
+
commandId: z.string().min(1),
|
|
37
|
+
instruction: agentNotificationInstructionSchema.nullable(),
|
|
38
|
+
notifications: agentNotificationsSchema,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
function notificationTransportEnvelope(input: AgentNotificationToolOutputInput) {
|
|
42
|
+
return {
|
|
43
|
+
type: notificationTransportEnvelopeType,
|
|
44
|
+
commandId: input.commandId,
|
|
45
|
+
instruction: input.instruction,
|
|
46
|
+
notifications: [...input.notifications],
|
|
47
|
+
} as const
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function encodeAgentNotificationCommandPayloadForTransport(
|
|
51
|
+
input: AgentNotificationToolOutputInput,
|
|
52
|
+
): AgentNotifications {
|
|
53
|
+
return [notificationTransportEnvelopeSchema.parse(notificationTransportEnvelope(input))]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function decodeAgentNotificationCommandPayloadFromTransport(input: {
|
|
57
|
+
commandId: string
|
|
58
|
+
notifications: AgentNotifications
|
|
59
|
+
}): AgentNotificationCommandPayload {
|
|
60
|
+
if (input.notifications.length === 1) {
|
|
61
|
+
const envelope = notificationTransportEnvelopeSchema.safeParse(input.notifications[0])
|
|
62
|
+
if (envelope.success && envelope.data.commandId === input.commandId) {
|
|
63
|
+
return {
|
|
64
|
+
instruction: envelope.data.instruction,
|
|
65
|
+
notifications: envelope.data.notifications,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
instruction: null,
|
|
72
|
+
notifications: input.notifications,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isAgentNotificationPublicPayloadWithinSizeLimit(
|
|
77
|
+
input: Pick<AgentNotificationToolOutputInput, 'commandId' | 'notifications'>,
|
|
78
|
+
): boolean {
|
|
79
|
+
return textEncoder.encode(JSON.stringify({
|
|
80
|
+
commandId: input.commandId,
|
|
81
|
+
notifications: input.notifications,
|
|
82
|
+
})).byteLength <= agentNotificationToolOutputMaxBytes
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function isAgentNotificationToolOutputWithinSizeLimit(input: AgentNotificationToolOutputInput): boolean {
|
|
86
|
+
const canonicalBytes = textEncoder.encode(JSON.stringify(input)).byteLength
|
|
87
|
+
const compatibilityBytes = textEncoder.encode(JSON.stringify({
|
|
88
|
+
commandId: input.commandId,
|
|
89
|
+
notifications: [notificationTransportEnvelope(input)],
|
|
90
|
+
})).byteLength
|
|
91
|
+
return Math.max(canonicalBytes, compatibilityBytes) <= agentNotificationToolOutputMaxBytes
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const agentNotificationToolOutputSchema: z.ZodType<AgentNotificationToolOutput> = z.object({
|
|
95
|
+
commandId: z.string().min(1),
|
|
96
|
+
instruction: agentNotificationInstructionSchema.nullable(),
|
|
97
|
+
notifications: agentNotificationsSchema,
|
|
98
|
+
}).strict().superRefine((output, context) => {
|
|
99
|
+
if (isAgentNotificationToolOutputWithinSizeLimit(output))
|
|
100
|
+
return
|
|
101
|
+
context.addIssue({
|
|
102
|
+
code: 'custom',
|
|
103
|
+
path: ['notifications'],
|
|
104
|
+
message: `Serialized notification tool output exceeds ${agentNotificationToolOutputMaxBytes} bytes.`,
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
export function serializeAgentNotificationToolOutput(input: AgentNotificationToolOutput): string {
|
|
109
|
+
return JSON.stringify(agentNotificationToolOutputSchema.parse(input))
|
|
110
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SelectableClaudeModelId } from './agent-catalog'
|
|
1
2
|
import type { AgentReasoningEffort } from './agent-command'
|
|
2
3
|
import type { KnownCodexModelId } from './agent-model'
|
|
3
4
|
|
|
@@ -6,11 +7,13 @@ import type { KnownCodexModelId } from './agent-model'
|
|
|
6
7
|
* or effort added to the wire unions cannot ship without its presentation: the
|
|
7
8
|
* `Record` types below fail to compile until every identifier is covered.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Labels, descriptions, and image support follow the non-hidden `model/list`
|
|
11
|
+
* catalog observed through Codex 0.153.4. Context windows use its model metadata's
|
|
12
|
+
* default `context_window`, not the opt-in `max_context_window`.
|
|
13
|
+
* Refresh alongside the model registry; the live catalog can change without a CLI
|
|
14
|
+
* upgrade. Relative cost weights are product-owned, not provider-reported prices.
|
|
15
|
+
* Upstream defines efforts by description only — no per-effort reasoning-token
|
|
16
|
+
* budget exists, so none is invented here.
|
|
14
17
|
*
|
|
15
18
|
* This is UI copy and relative sizing only. Billing, pricing, and cost estimation
|
|
16
19
|
* stay out of protocol (docs/agents-protocol.md) — `relativeCost` is a 1–5 picker
|
|
@@ -29,43 +32,55 @@ export interface AgentModelPresentation {
|
|
|
29
32
|
const CODEX_CONTEXT_WINDOW = 272_000
|
|
30
33
|
|
|
31
34
|
export const codexModelPresentation: Record<KnownCodexModelId, AgentModelPresentation> = {
|
|
35
|
+
'gpt-6-astra': {
|
|
36
|
+
label: 'GPT 6.0 Astra',
|
|
37
|
+
description: 'Our most capable model for complex, demanding work.',
|
|
38
|
+
relativeCost: 5,
|
|
39
|
+
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
40
|
+
isMultiModal: true,
|
|
41
|
+
},
|
|
32
42
|
'gpt-5.6-sol': {
|
|
33
|
-
label: 'GPT
|
|
34
|
-
description: '
|
|
43
|
+
label: 'GPT 5.6 Sol',
|
|
44
|
+
description: 'Reliable agentic workhorse for everyday tasks.',
|
|
35
45
|
relativeCost: 5,
|
|
36
46
|
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
37
47
|
isMultiModal: true,
|
|
38
48
|
},
|
|
49
|
+
'gpt-5.6-terra': {
|
|
50
|
+
label: 'GPT 5.6 Terra',
|
|
51
|
+
description: 'Balanced agentic coding model for everyday work.',
|
|
52
|
+
relativeCost: 3,
|
|
53
|
+
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
54
|
+
isMultiModal: true,
|
|
55
|
+
},
|
|
56
|
+
'gpt-5.6-luna': {
|
|
57
|
+
label: 'GPT 5.6 Luna',
|
|
58
|
+
description: 'Fast and affordable agentic coding model.',
|
|
59
|
+
relativeCost: 2,
|
|
60
|
+
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
61
|
+
isMultiModal: true,
|
|
62
|
+
},
|
|
39
63
|
'gpt-5.5': {
|
|
40
|
-
label: 'GPT
|
|
41
|
-
description: '
|
|
64
|
+
label: 'GPT 5.5',
|
|
65
|
+
description: 'Proven previous-generation model for coding and general work.',
|
|
42
66
|
relativeCost: 4,
|
|
43
67
|
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
44
68
|
isMultiModal: true,
|
|
45
69
|
},
|
|
46
70
|
'gpt-5.4': {
|
|
47
|
-
label: 'GPT
|
|
71
|
+
label: 'GPT 5.4',
|
|
48
72
|
description: 'Strong model for everyday coding.',
|
|
49
73
|
relativeCost: 3,
|
|
50
74
|
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
51
75
|
isMultiModal: true,
|
|
52
76
|
},
|
|
53
77
|
'gpt-5.4-mini': {
|
|
54
|
-
label: 'GPT
|
|
78
|
+
label: 'GPT 5.4 Mini',
|
|
55
79
|
description: 'Small, fast, and cost-efficient model for simpler coding tasks.',
|
|
56
80
|
relativeCost: 2,
|
|
57
81
|
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
58
82
|
isMultiModal: true,
|
|
59
83
|
},
|
|
60
|
-
/* Absent from the 0.145.0 upstream catalog; retained in our registry, so the
|
|
61
|
-
copy below is ours. */
|
|
62
|
-
'gpt-5.3-codex': {
|
|
63
|
-
label: 'GPT-5.3-Codex',
|
|
64
|
-
description: 'Code-tuned model for focused engineering tasks.',
|
|
65
|
-
relativeCost: 3,
|
|
66
|
-
maxInputTokens: CODEX_CONTEXT_WINDOW,
|
|
67
|
-
isMultiModal: true,
|
|
68
|
-
},
|
|
69
84
|
'gpt-5.2': {
|
|
70
85
|
label: 'GPT-5.2',
|
|
71
86
|
description: 'Optimized for professional work and long-running agents.',
|
|
@@ -75,6 +90,42 @@ export const codexModelPresentation: Record<KnownCodexModelId, AgentModelPresent
|
|
|
75
90
|
},
|
|
76
91
|
}
|
|
77
92
|
|
|
93
|
+
/*
|
|
94
|
+
* Claude presentation covers the selectable ids only (`agent-catalog.ts`); historical wire
|
|
95
|
+
* ids render through the unknown-model fallback. Labels, context windows, output limits,
|
|
96
|
+
* and image support follow the model catalog baked into Claude Code 2.1.280, the CLI the
|
|
97
|
+
* sandbox image pins. Relative cost follows that catalog's pricing tiers on the same
|
|
98
|
+
* product-owned 1–5 scale as Codex.
|
|
99
|
+
*/
|
|
100
|
+
const CLAUDE_CONTEXT_WINDOW = 1_000_000
|
|
101
|
+
|
|
102
|
+
export const claudeModelPresentation: Record<SelectableClaudeModelId, AgentModelPresentation> = {
|
|
103
|
+
'claude-opus-5-5': {
|
|
104
|
+
label: 'Opus 5.5',
|
|
105
|
+
description: 'Best for everyday, complex tasks.',
|
|
106
|
+
relativeCost: 4,
|
|
107
|
+
maxInputTokens: CLAUDE_CONTEXT_WINDOW,
|
|
108
|
+
maxOutputTokens: 128_000,
|
|
109
|
+
isMultiModal: true,
|
|
110
|
+
},
|
|
111
|
+
'claude-sonnet-5': {
|
|
112
|
+
label: 'Sonnet 5',
|
|
113
|
+
description: 'Efficient for routine coding tasks.',
|
|
114
|
+
relativeCost: 2,
|
|
115
|
+
maxInputTokens: CLAUDE_CONTEXT_WINDOW,
|
|
116
|
+
maxOutputTokens: 64_000,
|
|
117
|
+
isMultiModal: true,
|
|
118
|
+
},
|
|
119
|
+
'claude-fable-5-1': {
|
|
120
|
+
label: 'Fable 5.1',
|
|
121
|
+
description: 'Most intelligent generally available Claude model.',
|
|
122
|
+
relativeCost: 5,
|
|
123
|
+
maxInputTokens: CLAUDE_CONTEXT_WINDOW,
|
|
124
|
+
maxOutputTokens: 64_000,
|
|
125
|
+
isMultiModal: true,
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
|
|
78
129
|
interface AgentReasoningEffortPresentation {
|
|
79
130
|
label: string
|
|
80
131
|
description: string
|
|
@@ -1,32 +1,88 @@
|
|
|
1
1
|
import z from 'zod'
|
|
2
2
|
import { jsonObjectSchema, jsonValueSchema } from './agent-json'
|
|
3
|
+
import { objectRejectingKeys } from './rejected-keys'
|
|
3
4
|
|
|
4
5
|
export const agentToolDefinitionSchema = z.object({
|
|
5
6
|
name: z.string().regex(/^[\w-]{1,128}$/),
|
|
6
7
|
description: z.string().min(1),
|
|
7
8
|
inputSchema: jsonObjectSchema,
|
|
8
|
-
})
|
|
9
|
+
})
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
// Provider-private metadata containers are rejected, not stripped, at every content boundary.
|
|
12
|
+
const privateMetadataKeys = ['_meta', 'metadata'] as const
|
|
13
|
+
|
|
14
|
+
export const agentToolTextContentSchema = objectRejectingKeys({
|
|
11
15
|
type: z.literal('text'),
|
|
12
16
|
text: z.string(),
|
|
13
|
-
})
|
|
17
|
+
}, privateMetadataKeys)
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
// An image is either embedded data or a URI reference, never both.
|
|
20
|
+
export const agentToolImageContentSchema = objectRejectingKeys({
|
|
16
21
|
type: z.literal('image'),
|
|
17
22
|
data: z.string().min(1),
|
|
18
23
|
mimeType: z.string().min(1),
|
|
19
|
-
})
|
|
24
|
+
}, ['uri', ...privateMetadataKeys])
|
|
25
|
+
|
|
26
|
+
const observedContentMetadata = {
|
|
27
|
+
annotations: jsonObjectSchema.optional(),
|
|
28
|
+
extras: jsonObjectSchema.optional(),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const agentToolResourceLinkContentSchema = objectRejectingKeys({
|
|
32
|
+
type: z.literal('resource_link'),
|
|
33
|
+
name: z.string(),
|
|
34
|
+
uri: z.string(),
|
|
35
|
+
mimeType: z.string().optional(),
|
|
36
|
+
description: z.string().optional(),
|
|
37
|
+
title: z.string().optional(),
|
|
38
|
+
size: z.number().nonnegative().optional(),
|
|
39
|
+
...observedContentMetadata,
|
|
40
|
+
}, privateMetadataKeys)
|
|
41
|
+
|
|
42
|
+
const resourceMetadata = {
|
|
43
|
+
uri: z.string(),
|
|
44
|
+
mimeType: z.string().optional(),
|
|
45
|
+
extras: jsonObjectSchema.optional(),
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const agentToolResourceContentSchema = objectRejectingKeys({
|
|
49
|
+
type: z.literal('resource'),
|
|
50
|
+
// An embedded resource is either text or blob, never both.
|
|
51
|
+
resource: z.union([
|
|
52
|
+
objectRejectingKeys({ ...resourceMetadata, text: z.string() }, ['blob']),
|
|
53
|
+
objectRejectingKeys({ ...resourceMetadata, blob: z.string() }, ['text']),
|
|
54
|
+
]),
|
|
55
|
+
...observedContentMetadata,
|
|
56
|
+
}, privateMetadataKeys)
|
|
57
|
+
|
|
58
|
+
const agentToolAudioContentSchema = objectRejectingKeys({
|
|
59
|
+
type: z.literal('audio'),
|
|
60
|
+
data: z.string().min(1),
|
|
61
|
+
mimeType: z.string().min(1),
|
|
62
|
+
...observedContentMetadata,
|
|
63
|
+
}, privateMetadataKeys)
|
|
64
|
+
|
|
65
|
+
const agentToolJsonContentSchema = objectRejectingKeys({
|
|
66
|
+
type: z.literal('json'),
|
|
67
|
+
value: jsonValueSchema,
|
|
68
|
+
}, privateMetadataKeys)
|
|
20
69
|
|
|
21
|
-
export const agentToolContentSchema = z.
|
|
22
|
-
agentToolTextContentSchema,
|
|
23
|
-
agentToolImageContentSchema,
|
|
70
|
+
export const agentToolContentSchema = z.union([
|
|
71
|
+
agentToolTextContentSchema.extend(observedContentMetadata),
|
|
72
|
+
agentToolImageContentSchema.extend(observedContentMetadata),
|
|
73
|
+
objectRejectingKeys({ type: z.literal('image'), uri: z.string().min(1), ...observedContentMetadata }, ['data', ...privateMetadataKeys]),
|
|
74
|
+
agentToolAudioContentSchema,
|
|
75
|
+
agentToolResourceContentSchema,
|
|
76
|
+
agentToolResourceLinkContentSchema,
|
|
77
|
+
agentToolJsonContentSchema,
|
|
24
78
|
])
|
|
25
79
|
|
|
26
|
-
export const agentToolResultSchema =
|
|
80
|
+
export const agentToolResultSchema = objectRejectingKeys({
|
|
27
81
|
success: z.boolean(),
|
|
28
82
|
content: z.array(agentToolContentSchema),
|
|
29
|
-
|
|
83
|
+
structuredContent: jsonValueSchema.optional(),
|
|
84
|
+
reportedSuccess: z.boolean().optional(),
|
|
85
|
+
}, privateMetadataKeys)
|
|
30
86
|
|
|
31
87
|
export const agentToolCallStatusSchema = z.enum(['completed', 'failed', 'cancelled'])
|
|
32
88
|
|
|
@@ -9,7 +9,8 @@ export const agentUsageSchema = z.object({
|
|
|
9
9
|
cacheWriteTokens: tokenCountSchema.optional(),
|
|
10
10
|
reasoningOutputTokens: tokenCountSchema.optional(),
|
|
11
11
|
totalTokens: tokenCountSchema.optional(),
|
|
12
|
-
|
|
12
|
+
webSearchRequests: tokenCountSchema.optional(),
|
|
13
|
+
})
|
|
13
14
|
|
|
14
15
|
export type AgentUsage = z.infer<typeof agentUsageSchema>
|
|
15
16
|
|
|
@@ -26,3 +27,5 @@ export const agentUsageAccountingSchema = z.object({
|
|
|
26
27
|
model: z.string().min(1).optional(),
|
|
27
28
|
models: z.record(z.string(), agentUsageSchema).optional(),
|
|
28
29
|
}).strict()
|
|
30
|
+
|
|
31
|
+
export type AgentUsageAccounting = z.infer<typeof agentUsageAccountingSchema>
|
|
@@ -5,24 +5,24 @@ export const agentUserInputOptionSchema = z.object({
|
|
|
5
5
|
value: z.string().min(1),
|
|
6
6
|
label: z.string().min(1),
|
|
7
7
|
description: z.string().min(1).optional(),
|
|
8
|
-
})
|
|
8
|
+
})
|
|
9
9
|
|
|
10
10
|
const agentUserInputQuestionBaseSchema = z.object({
|
|
11
11
|
id: z.string().min(1),
|
|
12
12
|
label: z.string().min(1),
|
|
13
13
|
description: z.string().min(1).optional(),
|
|
14
14
|
required: z.boolean().optional(),
|
|
15
|
-
})
|
|
15
|
+
})
|
|
16
16
|
|
|
17
17
|
export const agentUserInputTextQuestionSchema = agentUserInputQuestionBaseSchema.extend({
|
|
18
18
|
type: z.literal('text'),
|
|
19
19
|
placeholder: z.string().min(1).optional(),
|
|
20
|
-
})
|
|
20
|
+
})
|
|
21
21
|
|
|
22
22
|
export const agentUserInputSingleSelectQuestionSchema = agentUserInputQuestionBaseSchema.extend({
|
|
23
23
|
type: z.literal('single_select'),
|
|
24
24
|
options: z.array(agentUserInputOptionSchema).min(1),
|
|
25
|
-
})
|
|
25
|
+
})
|
|
26
26
|
|
|
27
27
|
export const agentUserInputQuestionSchema = z.discriminatedUnion('type', [
|
|
28
28
|
agentUserInputTextQuestionSchema,
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import z from 'zod'
|
|
2
|
+
import { objectRejectingKeys } from './rejected-keys'
|
|
2
3
|
|
|
3
4
|
export const agentWorkStatusSchema = z.enum(['pending', 'in_progress', 'completed'])
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
// Provider-only fields (Claude `activeForm`/`explanation`, provider tags) are rejected, not stripped.
|
|
7
|
+
export const agentWorkItemSchema = objectRejectingKeys({
|
|
6
8
|
id: z.string().min(1),
|
|
7
9
|
title: z.string().min(1),
|
|
8
10
|
status: agentWorkStatusSchema,
|
|
9
|
-
})
|
|
11
|
+
}, ['activeForm'])
|
|
10
12
|
|
|
11
|
-
const agentWorkSnapshotObservationSchema =
|
|
13
|
+
const agentWorkSnapshotObservationSchema = objectRejectingKeys({
|
|
12
14
|
kind: z.literal('snapshot'),
|
|
13
15
|
items: z.array(agentWorkItemSchema),
|
|
14
|
-
}).
|
|
16
|
+
}, ['explanation']).superRefine(({ items }, context) => {
|
|
15
17
|
const seenIds = new Set<string>()
|
|
16
18
|
|
|
17
19
|
for (const [index, item] of items.entries()) {
|
|
@@ -31,26 +33,26 @@ export const agentWorkObservationSchema = z.discriminatedUnion('kind', [
|
|
|
31
33
|
z.object({
|
|
32
34
|
kind: z.literal('item_observed'),
|
|
33
35
|
item: agentWorkItemSchema,
|
|
34
|
-
})
|
|
36
|
+
}),
|
|
35
37
|
z.object({
|
|
36
38
|
kind: z.literal('item_renamed'),
|
|
37
39
|
itemId: z.string().min(1),
|
|
38
40
|
title: z.string().min(1),
|
|
39
|
-
})
|
|
41
|
+
}),
|
|
40
42
|
z.object({
|
|
41
43
|
kind: z.literal('item_status_changed'),
|
|
42
44
|
itemId: z.string().min(1),
|
|
43
45
|
status: agentWorkStatusSchema,
|
|
44
|
-
})
|
|
46
|
+
}),
|
|
45
47
|
z.object({
|
|
46
48
|
kind: z.literal('item_removed'),
|
|
47
49
|
itemId: z.string().min(1),
|
|
48
|
-
})
|
|
50
|
+
}),
|
|
49
51
|
])
|
|
50
52
|
|
|
51
|
-
export const agentWorkStateSchema =
|
|
53
|
+
export const agentWorkStateSchema = objectRejectingKeys({
|
|
52
54
|
items: z.array(agentWorkItemSchema),
|
|
53
|
-
})
|
|
55
|
+
}, ['provider'])
|
|
54
56
|
|
|
55
57
|
export type AgentWorkStatus = z.infer<typeof agentWorkStatusSchema>
|
|
56
58
|
export type AgentWorkItem = z.infer<typeof agentWorkItemSchema>
|
package/src/protocol/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './agent-catalog'
|
|
1
2
|
export * from './agent-command'
|
|
2
3
|
export * from './agent-content'
|
|
3
4
|
export * from './agent-error'
|
|
@@ -5,6 +6,7 @@ export * from './agent-event'
|
|
|
5
6
|
export * from './agent-json'
|
|
6
7
|
export * from './agent-metadata'
|
|
7
8
|
export * from './agent-model'
|
|
9
|
+
export * from './agent-notification'
|
|
8
10
|
export * from './agent-overflow'
|
|
9
11
|
export * from './agent-presentation'
|
|
10
12
|
export * from './agent-provider'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import z from 'zod'
|
|
2
|
+
|
|
3
|
+
// Builds a strip-on-read object schema that still rejects specific known-but-forbidden keys.
|
|
4
|
+
// Additive unknown fields are stripped, but a key listed here is a semantic violation (for
|
|
5
|
+
// example a turn id on a session-scoped event) and fails validation instead of being dropped.
|
|
6
|
+
// The rejecting keys are runtime-only: a valid value can never contain them, so they are
|
|
7
|
+
// intentionally absent from the inferred output type.
|
|
8
|
+
export function objectRejectingKeys<TShape extends z.ZodRawShape>(shape: TShape, rejectedKeys: readonly string[]): z.ZodObject<TShape> {
|
|
9
|
+
const rejections: object = Object.fromEntries(rejectedKeys.map(key => [key, z.never().optional()]))
|
|
10
|
+
return z.object({ ...shape, ...rejections })
|
|
11
|
+
}
|
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.2.0-experimental.
|
|
4
|
-
sha: "
|
|
5
|
-
buildTime: "2026-09-
|
|
3
|
+
version: "0.2.0-experimental.2",
|
|
4
|
+
sha: "b808a0e0d307bcaa2cd0d47d2fd1e4112f70290c",
|
|
5
|
+
buildTime: "2026-09-25T17:58:45.916Z",
|
|
6
6
|
} as const
|