@finalai/final-agent-provider 0.6.2 → 0.7.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 (94) hide show
  1. package/HOSTING.md +4 -4
  2. package/README.md +94 -2
  3. package/dist/modules/authoring-final-channel.mjs +2 -2
  4. package/dist/modules/authoring-final-channel.mjs.map +2 -2
  5. package/dist/modules/channel-factories.d.mts +5 -7
  6. package/dist/modules/channel-factories.mjs +4 -50
  7. package/dist/modules/channel-factories.mjs.map +2 -2
  8. package/dist/modules/channels/channel-utils.d.mts +132 -0
  9. package/dist/modules/channels/channel-utils.mjs +445 -0
  10. package/dist/modules/channels/channel-utils.mjs.map +7 -0
  11. package/dist/modules/channels/delivery.d.mts +5 -5
  12. package/dist/modules/channels/delivery.mjs.map +1 -1
  13. package/dist/modules/channels/direct-messaging.d.mts +2 -2
  14. package/dist/modules/channels/direct-messaging.mjs.map +2 -2
  15. package/dist/modules/channels/discord-dispatch.d.mts +17 -0
  16. package/dist/modules/channels/discord-dispatch.mjs +139 -0
  17. package/dist/modules/channels/discord-dispatch.mjs.map +7 -0
  18. package/dist/modules/channels/discord-gateway.d.mts +19 -0
  19. package/dist/modules/channels/discord-gateway.mjs +233 -0
  20. package/dist/modules/channels/discord-gateway.mjs.map +7 -0
  21. package/dist/modules/channels/discord.d.mts +9 -0
  22. package/dist/modules/channels/discord.mjs +904 -0
  23. package/dist/modules/channels/discord.mjs.map +7 -0
  24. package/dist/modules/channels/fake-platform.d.mts +2 -7
  25. package/dist/modules/channels/fake-platform.mjs +2 -38
  26. package/dist/modules/channels/fake-platform.mjs.map +2 -2
  27. package/dist/modules/channels/github.d.mts +5 -0
  28. package/dist/modules/channels/github.mjs +720 -0
  29. package/dist/modules/channels/github.mjs.map +7 -0
  30. package/dist/modules/channels/group-messaging.d.mts +2 -2
  31. package/dist/modules/channels/group-messaging.mjs.map +2 -2
  32. package/dist/modules/channels/index.d.mts +7 -3
  33. package/dist/modules/channels/index.mjs +7 -3
  34. package/dist/modules/channels/index.mjs.map +2 -2
  35. package/dist/modules/channels/linear.d.mts +4 -0
  36. package/dist/modules/channels/linear.mjs +621 -0
  37. package/dist/modules/channels/linear.mjs.map +7 -0
  38. package/dist/modules/channels/messaging-channel.d.mts +3 -3
  39. package/dist/modules/channels/messaging-channel.mjs +2 -2
  40. package/dist/modules/channels/messaging-channel.mjs.map +2 -2
  41. package/dist/modules/channels/phone.d.mts +8 -0
  42. package/dist/modules/channels/phone.mjs +382 -0
  43. package/dist/modules/channels/phone.mjs.map +7 -0
  44. package/dist/modules/channels/projection.mjs.map +1 -1
  45. package/dist/modules/channels/reply-receipts.d.mts +31 -0
  46. package/dist/modules/channels/reply-receipts.mjs +63 -0
  47. package/dist/modules/channels/reply-receipts.mjs.map +7 -0
  48. package/dist/modules/channels/routing.d.mts +1 -0
  49. package/dist/modules/channels/routing.mjs +5 -1
  50. package/dist/modules/channels/routing.mjs.map +2 -2
  51. package/dist/modules/channels/slack.d.mts +7 -0
  52. package/dist/modules/channels/slack.mjs +1134 -0
  53. package/dist/modules/channels/slack.mjs.map +7 -0
  54. package/dist/modules/channels/voice-recording.d.mts +7 -0
  55. package/dist/modules/channels/voice-recording.mjs +49 -0
  56. package/dist/modules/channels/voice-recording.mjs.map +7 -0
  57. package/dist/modules/channels/voice.d.mts +33 -0
  58. package/dist/modules/channels/voice.mjs +851 -0
  59. package/dist/modules/channels/voice.mjs.map +7 -0
  60. package/dist/modules/channels/webhook.d.mts +5 -0
  61. package/dist/modules/channels/webhook.mjs +76 -0
  62. package/dist/modules/channels/webhook.mjs.map +7 -0
  63. package/dist/modules/harnesses/acp-describe.mjs +1 -1
  64. package/dist/modules/harnesses/acp-describe.mjs.map +2 -2
  65. package/dist/modules/harnesses/config-fields.d.mts +6 -1
  66. package/dist/modules/harnesses/config-fields.mjs +7 -0
  67. package/dist/modules/harnesses/config-fields.mjs.map +3 -3
  68. package/dist/modules/harnesses/fidelity.mjs +17 -17
  69. package/dist/modules/harnesses/fidelity.mjs.map +2 -2
  70. package/dist/modules/harnesses/remote-claude-code.d.mts +14 -2
  71. package/dist/modules/harnesses/remote-claude-code.mjs +5 -3
  72. package/dist/modules/harnesses/remote-claude-code.mjs.map +2 -2
  73. package/dist/modules/harnesses/remote-url.mjs.map +1 -1
  74. package/dist/modules/harnesses/serverless-nanocode-codex.d.mts +3 -1
  75. package/dist/modules/harnesses/serverless-nanocode-codex.mjs +6 -0
  76. package/dist/modules/harnesses/serverless-nanocode-codex.mjs.map +2 -2
  77. package/dist/modules/runtime/remote-host.mjs.map +1 -1
  78. package/dist/modules/sandboxes/build-scripts.mjs.map +1 -1
  79. package/dist/modules/sandboxes/paths.mjs.map +1 -1
  80. package/dist/modules/testing/harness.mjs +2 -2
  81. package/dist/modules/testing/harness.mjs.map +1 -1
  82. package/package.json +45 -19
  83. package/dist/modules/channels/address-context.d.mts +0 -7
  84. package/dist/modules/channels/address-context.mjs +0 -80
  85. package/dist/modules/channels/address-context.mjs.map +0 -7
  86. package/dist/modules/channels/agent-events.d.mts +0 -103
  87. package/dist/modules/channels/agent-events.mjs +0 -341
  88. package/dist/modules/channels/agent-events.mjs.map +0 -7
  89. package/dist/modules/channels/agent-schedules.d.mts +0 -25
  90. package/dist/modules/channels/agent-schedules.mjs +0 -96
  91. package/dist/modules/channels/agent-schedules.mjs.map +0 -7
  92. package/dist/modules/channels/service-input.d.mts +0 -22
  93. package/dist/modules/channels/service-input.mjs +0 -32
  94. package/dist/modules/channels/service-input.mjs.map +0 -7
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/channels/voice.ts"],
4
+ "sourcesContent": ["import {\n defineChannel,\n packageRef,\n principalRefSchema,\n type ChannelReceiveContextIface,\n type ChannelSocketIface,\n type JsonObject,\n type JsonValue,\n type PlaceRef,\n type PrincipalRef,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { bytesToBase64 } from '@finalai/agent-provider/sandbox/bytes';\nimport { recordingRawLimit, recordingWav } from \"./voice-recording.mjs\";\nimport {\n abortable,\n channelBaseUrl,\n confirmOAuth,\n createQueue,\n decisionChoices,\n decisionSummary,\n decisionAnswer,\n textOf,\n turnStatus,\n type DecisionChoiceIface,\n parseJson,\n personFor,\n responseJson,\n startOAuth,\n takeOAuth,\n} from \"./channel-utils.mjs\";\n\nconst configSchema = z.object({\n baseUrl: z.string().url().optional(),\n oauthAuthorizeUrl: z.string().url().optional(),\n oauthTokenUrl: z.string().url().optional(),\n oauthUserInfoUrl: z.string().url().optional(),\n oauthClientId: z.string().url().optional(),\n oauthResource: z.string().url().optional(),\n voice: z.string().optional(),\n});\nexport type VoiceConfig = z.infer<typeof configSchema>;\nconst userInfoSchema = z\n .object({ sub: z.string(), organizationId: z.string(), displayName: z.string() })\n .transform((value) => ({\n id: value.sub,\n tenant: value.organizationId,\n displayName: value.displayName,\n }));\nconst startSchema = z.object({\n type: z.literal('start'),\n encoding: z.literal('linear16'),\n sampleRate: z.literal(16000),\n principal: principalRefSchema,\n recording: z.boolean().default(false),\n});\nexport interface VoiceConnectionOptionsIface<Config> {\n ctx: ChannelReceiveContextIface<Config>;\n socket: ChannelSocketIface;\n principal: PrincipalRef;\n place: PlaceRef;\n encoding: string;\n sampleRate: number;\n voice?: string;\n recording?: boolean;\n}\n// A single channel owns transcription, posting, observation and synthesis on every transport.\nexport const runVoiceConnection = async <Config>(\n options: VoiceConnectionOptionsIface<Config>,\n): Promise<void> => {\n const { ctx, socket } = options;\n const failed = new AbortController();\n const signal = AbortSignal.any([socket.signal, failed.signal]);\n const send = (data: string | Uint8Array): void => {\n if (!signal.aborted) socket.send(data);\n };\n const connectionKey = crypto.randomUUID();\n const trace = (\n stage: string,\n detail: { utterance?: string; turnId?: string; at?: number } = {},\n ) => {\n const metadata = { connectionId: connectionKey, at: Date.now(), ...detail };\n send(JSON.stringify({ type: 'trace', stage, ...metadata }));\n ctx.log(`voice.${stage}`, metadata);\n };\n let activeSpeech: AbortController | null = null;\n let activeRefusal: AbortController | null = null;\n let refusalPlayback: Promise<void> | null = null;\n let playbackGeneration = 0;\n const speakRefusal = async (message: string, refusalSignal: AbortSignal = signal) => {\n const preceding = refusalPlayback;\n const finished = Promise.withResolvers<void>();\n refusalPlayback = finished.promise;\n const speech = new AbortController();\n activeRefusal?.abort();\n activeRefusal = speech;\n activeSpeech?.abort();\n const playbackVersion = ++playbackGeneration;\n send(JSON.stringify({ type: 'speech.start' }));\n const outputSignal = AbortSignal.any([refusalSignal, speech.signal]);\n try {\n await preceding;\n const text = async function* () {\n yield message;\n };\n for await (const frame of abortable(\n ctx.media.synthesize(text(), {\n voice: options.voice,\n encoding: options.encoding,\n sampleRate: options.sampleRate,\n signal: outputSignal,\n }),\n outputSignal,\n )) {\n if (playbackVersion !== playbackGeneration || outputSignal.aborted) break;\n send(frame);\n }\n } finally {\n speech.abort();\n if (activeRefusal === speech) activeRefusal = null;\n finished.resolve();\n if (refusalPlayback === finished.promise) refusalPlayback = null;\n }\n };\n const person = await personFor(ctx, options.principal);\n const route = await ctx.places.resolve(options.place);\n if (\n typeof person !== 'string' &&\n (person.refused !== 'unlinked' ||\n route.kind !== 'connected' ||\n route.policy.audience !== 'anyone')\n ) {\n send(JSON.stringify({ type: 'linked', linkUrl: person.linkUrl, message: person.message }));\n await speakRefusal(person.message);\n socket.close(1008, 'Account link required');\n return;\n }\n const from = typeof person === 'string' ? person : undefined;\n const conversation = await (async () => {\n try {\n return route.kind === 'connected'\n ? route.conversation\n : route.defaults == null || from == null\n ? null\n : await ctx.places.connect(options.place, { by: from, create: route.defaults.create });\n } catch {\n return null;\n }\n })();\n if (conversation == null) {\n const message = 'This call could not connect to a chat. Check your access in Final.';\n send(JSON.stringify({ type: 'notice', message }));\n await speakRefusal(message, AbortSignal.any([signal, AbortSignal.timeout(10_000)]));\n send(JSON.stringify({ type: 'speech.end', final: true }));\n socket.close(1000);\n return;\n }\n const recordingEnabled = options.recording !== false;\n const recordingLimit = recordingEnabled ? recordingRawLimit(options.encoding) : null;\n if (recordingEnabled)\n send(\n JSON.stringify({\n type: 'recording.notice',\n message: 'Your transcript and recording are saved to this chat.',\n }),\n );\n const audio = createQueue<Uint8Array>();\n const transcriptionStopped = new AbortController();\n const transcriptionSignal = AbortSignal.any([signal, transcriptionStopped.signal]);\n let terminalRefusal = false;\n let microphoneInputClosed = false;\n const closeAudio = () => {\n microphoneInputClosed = true;\n audio.close();\n };\n const microphoneEnded = new AbortController();\n const microphoneLifecycle: { onEnd: (() => void) | null; stopObservation: (() => void) | null } =\n { onEnd: null, stopObservation: null };\n const utterances = createQueue<{ text: string; key: string; finalAt: number }>();\n let queuedAudioBytes = 0;\n const transcriptionAudio = async function* (): AsyncGenerator<Uint8Array> {\n for await (const frame of audio.stream) {\n queuedAudioBytes -= frame.byteLength;\n yield frame;\n }\n };\n let recording: Uint8Array[] = [];\n let recordingSize = 0;\n let segment = 0;\n let generation = 0;\n let activeTurn = false;\n const turnLifecycle: { accepting: { interrupted: boolean } | null; activeId: string | null } = {\n accepting: null,\n activeId: null,\n };\n let audioStarted = false;\n let userSpeaking = false;\n let utteranceNumber = 0;\n let decision: { id: string; choices: DecisionChoiceIface[] } | null = null;\n const pendingDecisions = new Map<string, { id: string; choices: DecisionChoiceIface[] }>();\n const clearDecisions = () => {\n pendingDecisions.clear();\n decision = null;\n };\n const fail = (cause: unknown): void => {\n if (signal.aborted) return;\n ctx.log('voice connection failed', {\n error: cause instanceof Error ? cause.message : 'stream failed',\n });\n send(\n JSON.stringify({ type: 'error', message: 'The voice connection failed. Please reconnect.' }),\n );\n socket.close(1011, 'Voice connection failed');\n failed.abort();\n closeAudio();\n utterances.close();\n };\n interface RecordingSegmentIface {\n chunks: Uint8Array[];\n bytes: number;\n index: number;\n encoded: string | null;\n }\n let upload: {\n segment: RecordingSegmentIface;\n result: Promise<{ ok: true } | { error: unknown }>;\n } | null = null;\n const attachRecording = async (\n part: RecordingSegmentIface,\n deadline?: AbortSignal,\n ): Promise<void> => {\n deadline?.throwIfAborted();\n if (part.encoded == null) {\n part.encoded = bytesToBase64(\n recordingWav({\n chunks: part.chunks,\n bytes: part.bytes,\n encoding: options.encoding,\n sampleRate: options.sampleRate,\n }),\n );\n // Retries reuse the same payload without retaining its raw copy.\n part.chunks = [];\n }\n const result = await ctx.conversation(conversation).attach({\n from,\n label: `Voice recording, part ${part.index}`,\n origin: { place: options.place },\n idempotencyKey: `${options.place.id}:${connectionKey}:recording:${part.index}`,\n content: [{ type: 'audio', data: part.encoded, mimeType: 'audio/wav' }],\n });\n if ('refused' in result) throw new Error(result.message);\n };\n const beginRecordingUpload = (deadline?: AbortSignal): void => {\n if (recordingSize === 0) return;\n const part: RecordingSegmentIface = {\n chunks: recording,\n bytes: recordingSize,\n index: ++segment,\n encoded: null,\n };\n recording = [];\n recordingSize = 0;\n upload = {\n segment: part,\n result: attachRecording(part, deadline).then(\n () => ({ ok: true }),\n (error: unknown) => ({ error }),\n ),\n };\n };\n const settleRecordingUpload = async (retry: boolean, deadline?: AbortSignal): Promise<void> => {\n const pending = upload;\n if (pending == null) return;\n const stop = deadline ?? signal;\n const interrupted = Promise.withResolvers<never>();\n const abortUpload = () =>\n interrupted.reject(\n stop.reason instanceof Error ? stop.reason : new Error('Recording upload interrupted.'),\n );\n stop.addEventListener('abort', abortUpload, { once: true });\n if (stop.aborted) abortUpload();\n let result: { ok: true } | { error: unknown };\n try {\n result = await Promise.race([pending.result, interrupted.promise]);\n if ('error' in result) {\n if (!retry) throw result.error;\n await Promise.race([attachRecording(pending.segment, deadline), interrupted.promise]);\n }\n } finally {\n stop.removeEventListener('abort', abortUpload);\n }\n if (upload === pending) upload = null;\n };\n const rotateRecording = async (): Promise<void> => {\n // At most one segment uploads while the next accumulates; only a second full segment waits.\n await settleRecordingUpload(true);\n signal.throwIfAborted();\n beginRecordingUpload();\n };\n const finishRecording = async (): Promise<void> => {\n const deadline = new AbortController();\n const expired = Promise.withResolvers<never>();\n const timer = setTimeout(() => {\n const cause = new Error('Recording cleanup timed out.');\n deadline.abort(cause);\n expired.reject(cause);\n }, 10_000);\n const finish = async () => {\n let failure: Error | null = null;\n try {\n await settleRecordingUpload(true, deadline.signal);\n } catch (cause) {\n failure = cause instanceof Error ? cause : new Error('Recording attachment failed.');\n upload = null;\n }\n if (recordingSize > 0 && !deadline.signal.aborted) {\n try {\n beginRecordingUpload(deadline.signal);\n await settleRecordingUpload(true, deadline.signal);\n } catch (cause) {\n failure ??= cause instanceof Error ? cause : new Error('Recording attachment failed.');\n }\n }\n if (failure != null) throw failure;\n };\n try {\n await Promise.race([finish(), expired.promise]);\n } finally {\n clearTimeout(timer);\n deadline.abort();\n }\n };\n const reportRefusal = async (\n message: string,\n options: { recoverable?: boolean } = {},\n ): Promise<void> => {\n if (terminalRefusal) return;\n const recoverable =\n options.recoverable !== false &&\n (from == null ||\n (await ctx.people.identify(from).then(\n (principal) => principal != null,\n () => false,\n )));\n if (terminalRefusal) return;\n if (recoverable) {\n send(JSON.stringify({ type: 'error', message, recoverable: true }));\n await speakRefusal(message);\n return;\n }\n terminalRefusal = true;\n closeAudio();\n transcriptionStopped.abort();\n utterances.close();\n activeSpeech?.abort();\n microphoneLifecycle.stopObservation?.();\n send(JSON.stringify({ type: 'notice', message }));\n await speakRefusal(message, AbortSignal.any([signal, AbortSignal.timeout(10_000)]));\n };\n const requestCancellation = async (turnId: string): Promise<void> => {\n try {\n const result = await ctx.turns.cancel({ conversation, by: from, turnId });\n if ('refused' in result) await reportRefusal(result.message);\n else if (!result.accepted)\n await reportRefusal(\n 'No running turn could be interrupted from this connection. Check Final if work is still running.',\n );\n } catch {\n await reportRefusal('The turn could not be interrupted. Try stopping it in Final.');\n }\n };\n const cancel = async (withdrawDecision = false) => {\n playbackGeneration += 1;\n activeSpeech?.abort();\n send(JSON.stringify({ type: 'speech.start' }));\n if (turnLifecycle.accepting != null) {\n turnLifecycle.accepting.interrupted = true;\n generation += 1;\n return;\n }\n if (activeTurn && (decision == null || withdrawDecision)) {\n clearDecisions();\n generation += 1;\n microphoneLifecycle.stopObservation?.();\n const target = turnLifecycle.activeId;\n if (target != null) await requestCancellation(target);\n }\n };\n const answerDecision = async (text: string): Promise<boolean> => {\n if (decision == null) return false;\n const normalized = text\n .trim()\n .toLowerCase()\n .replace(/[.!?]$/g, '');\n const isDecisionAnswer = ['yes', 'no', 'approve', 'deny'].includes(normalized);\n if (pendingDecisions.size > 1) {\n if (\n isDecisionAnswer ||\n [...pendingDecisions.values()].some(\n (pending) => decisionAnswer(pending.choices, normalized) != null,\n )\n ) {\n await speakRefusal('Multiple actions need approval. Answer them in Final.');\n return true;\n }\n return false;\n }\n\n if (from == null) {\n if (!isDecisionAnswer) return false;\n await speakRefusal('This action needs approval in Final.');\n return true;\n }\n const choice = decisionAnswer(decision.choices, normalized);\n if (choice == null) {\n if (!['yes', 'no', 'approve', 'deny'].includes(normalized)) return false;\n await speakRefusal('Choose the exact option in Final.');\n return true;\n }\n const decisionId = decision.id;\n try {\n const result = await ctx.decisions.resolve({\n decisionId,\n outcome: choice.outcome,\n by: from,\n });\n if ('refused' in result) await reportRefusal(result.message);\n else {\n pendingDecisions.delete(decisionId);\n decision = pendingDecisions.values().next().value ?? null;\n if (!result.resolved) await reportRefusal('This decision is no longer waiting in Final.');\n }\n } catch {\n await reportRefusal(\n 'The approval could not be answered. Please try again or answer in Final.',\n );\n }\n return true;\n };\n const speak = async (\n text: AsyncIterable<string>,\n version: number,\n correlation: { utterance: string; turnId: string },\n ) => {\n let firstAudio = true;\n for await (const sentence of abortable(text, signal)) {\n while (refusalPlayback != null) await refusalPlayback;\n if (version !== generation || signal.aborted) break;\n const playbackVersion = playbackGeneration;\n const single = async function* () {\n yield sentence;\n };\n const speech = new AbortController();\n activeSpeech = speech;\n const speechSignal = AbortSignal.any([signal, speech.signal]);\n try {\n for await (const frame of abortable(\n ctx.media.synthesize(single(), {\n voice: options.voice,\n encoding: options.encoding,\n sampleRate: options.sampleRate,\n signal: speechSignal,\n }),\n speechSignal,\n )) {\n if (version !== generation || playbackVersion !== playbackGeneration) break;\n if (firstAudio) {\n firstAudio = false;\n trace('first.audio.out', correlation);\n }\n send(frame);\n }\n } catch (cause) {\n if (!speechSignal.aborted) throw cause;\n } finally {\n speech.abort();\n if (activeSpeech === speech) activeSpeech = null;\n }\n }\n };\n const work = (async () => {\n for await (const utterance of abortable(utterances.stream, signal)) {\n if (terminalRefusal) break;\n const version = ++generation;\n const { text, key, finalAt } = utterance;\n const origin = {\n place: options.place,\n ref: {\n externalKey: key,\n connectionId: connectionKey,\n utterance: key,\n utteranceFinalAt: finalAt,\n },\n };\n const accepting = { interrupted: false };\n turnLifecycle.accepting = accepting;\n const posted =\n from == null\n ? await ctx.conversation(conversation).input({\n content: [{ type: 'text', text }],\n origin,\n idempotencyKey: key,\n waitForAcceptance: true,\n principal: options.principal,\n label: `From ${options.principal.displayName ?? options.principal.id} in ${options.place.title ?? options.place.kind}`,\n })\n : await ctx.conversation(conversation).post({\n from,\n content: [{ type: 'text', text }],\n origin,\n idempotencyKey: key,\n waitForAcceptance: true,\n });\n if (turnLifecycle.accepting === accepting) turnLifecycle.accepting = null;\n if (signal.aborted || terminalRefusal) return;\n if (accepting.interrupted || version !== generation) {\n if (!('refused' in posted) && posted.turnId != null) {\n trace('post.accepted', { utterance: key, turnId: posted.turnId });\n await requestCancellation(posted.turnId);\n }\n continue;\n }\n if ('refused' in posted) {\n await reportRefusal(posted.message, { recoverable: false });\n continue;\n }\n if (posted.turnId == null) {\n const message = \"I couldn't start a voice reply for this request. Check the chat in Final.\";\n await reportRefusal(message);\n continue;\n }\n trace('post.accepted', { utterance: key, turnId: posted.turnId });\n activeTurn = true;\n turnLifecycle.activeId = posted.turnId;\n const sentences = createQueue<string>();\n const output = speak(sentences.stream, version, {\n utterance: key,\n turnId: posted.turnId,\n }).catch(fail);\n const observation = new AbortController();\n const observationSignal = AbortSignal.any([signal, observation.signal]);\n const stopObservation = () => observation.abort();\n microphoneLifecycle.stopObservation = stopObservation;\n const microphoneEnd = () => {\n if (decision == null) return;\n sentences.push('Continue this approval in Final.');\n observation.abort();\n };\n microphoneLifecycle.onEnd = microphoneEnd;\n let hasReply = false;\n let buffer = '';\n let first = true;\n const streamed = new Set<string>();\n const completed = new Set<string>();\n try {\n for await (const event of abortable(\n ctx.observe(conversation, { turnId: posted.turnId, signal: observationSignal }),\n observationSignal,\n )) {\n if (version !== generation) break;\n if (event.type === 'message.delta') {\n if (first) {\n first = false;\n trace('first.delta', { utterance: key, turnId: posted.turnId });\n }\n if (event.data.delta.type !== 'text' || typeof event.data.delta.text !== 'string')\n continue;\n if (event.data.delta.text.length > 0) streamed.add(event.data.messageId);\n if (event.data.delta.text.trim().length > 0) hasReply = true;\n buffer += event.data.delta.text;\n let boundary: RegExpExecArray | null;\n while ((boundary = /[!?](?:\\s|$)|(?<!\\d)\\.(?:\\s|$)|\\.\\s/.exec(buffer)) != null) {\n const end = boundary.index + boundary[0].length;\n sentences.push(buffer.slice(0, end));\n buffer = buffer.slice(end);\n }\n } else if (event.type === 'message.completed') {\n const id = event.data.message.id;\n if (!completed.has(id)) {\n if (!streamed.has(id)) buffer += textOf(event.data.message.content);\n if (buffer.trim().length > 0) {\n hasReply = true;\n sentences.push(buffer);\n }\n buffer = '';\n completed.add(id);\n }\n } else if (event.type === 'decision.created') {\n const choices =\n from == null || microphoneEnded.signal.aborted\n ? []\n : decisionChoices(event.data.request);\n decision = { id: event.data.decisionId, choices };\n pendingDecisions.set(decision.id, decision);\n sentences.push(\n `${decisionSummary(event.data.request)} ${\n pendingDecisions.size > 1\n ? 'Multiple actions need approval. Answer them in Final.'\n : from == null\n ? 'This action needs approval in Final.'\n : choices.length === 0\n ? \"I've sent that to you in Final.\"\n : choices.filter((choice) => choice.answer === 'approve').length === 1 &&\n choices.filter((choice) => choice.answer === 'deny').length <= 1\n ? `Your options are ${choices.map((choice) => choice.label).join(' or ')}. Do you approve this action? Say yes or no.`\n : 'Choose an option in Final.'\n }`,\n );\n if (microphoneEnded.signal.aborted) break;\n } else if (event.type === 'decision.resolved') {\n pendingDecisions.delete(event.data.decisionId);\n decision = pendingDecisions.values().next().value ?? null;\n } else if (event.type === 'turn.completed') {\n turnLifecycle.activeId = null;\n for (const message of event.data.messages ?? []) {\n if (!streamed.has(message.id) && !completed.has(message.id)) {\n const text = textOf(message.content);\n if (text.trim().length > 0) {\n hasReply = true;\n sentences.push(text);\n }\n completed.add(message.id);\n }\n }\n if (streamed.size === 0 && completed.size === 0 && event.data.content != null) {\n const text = textOf(event.data.content);\n if (text.trim().length > 0) {\n hasReply = true;\n sentences.push(text);\n }\n }\n if (buffer.trim().length > 0) {\n sentences.push(buffer);\n buffer = '';\n }\n const status = turnStatus(event.data);\n if (status != null) sentences.push(status);\n else if (!hasReply)\n sentences.push('The turn finished without a spoken reply. Open Final for details.');\n clearDecisions();\n break;\n }\n }\n if (version === generation && buffer.trim().length > 0) sentences.push(buffer);\n } finally {\n clearDecisions();\n observation.abort();\n if (microphoneLifecycle.stopObservation === stopObservation)\n microphoneLifecycle.stopObservation = null;\n if (microphoneLifecycle.onEnd === microphoneEnd) microphoneLifecycle.onEnd = null;\n sentences.close();\n await output;\n activeTurn = false;\n if (turnLifecycle.activeId === posted.turnId) turnLifecycle.activeId = null;\n send(JSON.stringify({ type: 'speech.end', final: false }));\n }\n }\n })().catch(fail);\n const transcription = (async () => {\n try {\n for await (const transcript of abortable(\n ctx.media.transcribe(transcriptionAudio(), {\n encoding: options.encoding,\n sampleRate: options.sampleRate,\n endpointing: true,\n signal: transcriptionSignal,\n }),\n transcriptionSignal,\n )) {\n send(JSON.stringify({ type: 'transcript', ...transcript }));\n if (!transcript.final && transcript.text.trim().length > 0 && !userSpeaking) {\n userSpeaking = true;\n await cancel();\n }\n if (transcript.final && transcript.text.trim().length === 0) userSpeaking = false;\n if (transcript.final && transcript.text.trim().length > 0) {\n const key = `${options.place.id}:${connectionKey}:${++utteranceNumber}`;\n const finalAt = Date.now();\n trace('utterance.final', { utterance: key, at: finalAt });\n if (!userSpeaking && (activeTurn || turnLifecycle.accepting != null) && decision == null)\n await cancel();\n userSpeaking = false;\n if (!(await answerDecision(transcript.text)) && !terminalRefusal) {\n if (decision != null) await cancel(true);\n utterances.push({ text: transcript.text, key, finalAt });\n }\n }\n }\n } finally {\n utterances.close();\n if (!microphoneInputClosed && !signal.aborted)\n fail(new Error('The transcription stream ended unexpectedly.'));\n microphoneEnded.abort();\n microphoneLifecycle.onEnd?.();\n }\n })().catch(fail);\n const aborted = Promise.withResolvers<void>();\n const abort = () => {\n aborted.resolve();\n closeAudio();\n utterances.close();\n generation += 1;\n };\n signal.addEventListener('abort', abort, { once: true });\n if (signal.aborted) abort();\n let cleanupFailure: Error | null = null;\n try {\n for await (const frame of abortable(\n socket.messages,\n AbortSignal.any([signal, microphoneEnded.signal]),\n )) {\n if (terminalRefusal) break;\n if (frame instanceof Uint8Array) {\n if (queuedAudioBytes + frame.byteLength > 2 * 1024 * 1024) {\n fail(new Error('Microphone audio exceeded the pending transcription limit.'));\n break;\n }\n if (recordingLimit != null) {\n for (let offset = 0; offset < frame.byteLength; ) {\n const length = Math.min(frame.byteLength - offset, recordingLimit - recordingSize);\n recording.push(frame.slice(offset, offset + length));\n recordingSize += length;\n offset += length;\n if (recordingSize === recordingLimit) await rotateRecording();\n }\n }\n if (!audioStarted) {\n audioStarted = true;\n trace('audio.in');\n }\n queuedAudioBytes += frame.byteLength;\n audio.push(frame);\n continue;\n }\n const control = z.object({ type: z.string() }).safeParse(parseJson(frame));\n if (control.success && control.data.type === 'cancel') await cancel(true);\n if (control.success && control.data.type === 'stop') {\n closeAudio();\n break;\n }\n }\n closeAudio();\n await Promise.race([transcription, aborted.promise]);\n await Promise.race([work, aborted.promise]);\n } catch (cause) {\n fail(cause);\n } finally {\n signal.removeEventListener('abort', abort);\n abort();\n if (signal.aborted) {\n await Promise.race([Promise.all([transcription, work]), aborted.promise]);\n } else await Promise.all([transcription, work]);\n try {\n await finishRecording();\n } catch (cause) {\n if (signal.aborted)\n cleanupFailure = cause instanceof Error ? cause : new Error('Recording attachment failed.');\n else fail(cause);\n }\n if (!signal.aborted) {\n send(JSON.stringify({ type: 'speech.end', final: true }));\n socket.close(1000);\n }\n }\n if (cleanupFailure != null) throw cleanupFailure;\n};\n\nconst oauthClient = async (\n ctx: ChannelReceiveContextIface<VoiceConfig>,\n config: VoiceConfig,\n): Promise<string> => {\n if (config.oauthClientId != null) return config.oauthClientId;\n const saved = z\n .string()\n .url()\n .safeParse(await ctx.store.get('voice-oauth-client'));\n if (saved.success) return saved.data;\n const endpoint = new URL(\n '/oauth2/register',\n config.oauthAuthorizeUrl ?? 'https://api.final.ai/oauth2/authorize',\n );\n const result = z.object({ client_id: z.string().url() }).parse(\n await responseJson(\n await ctx.credentials.fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n client_name: 'Final Voice Channel',\n redirect_uris: [`${channelBaseUrl(config)}/b/${ctx.binding.id}/oauth/callback`],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n }),\n }),\n ),\n );\n await ctx.store.set('voice-oauth-client', result.client_id);\n return result.client_id;\n};\nexport const voiceChannel = (options: JsonObject = {}) => {\n const config = configSchema.parse(options);\n return defineChannel<VoiceConfig, JsonValue, JsonValue>({\n name: 'voice',\n config,\n installed: packageRef('@finalai/final-agent-provider/channels/voice'),\n credentials: { app: null },\n identity: {\n kind: 'redirect',\n start: async (args, ctx) =>\n startOAuth(\n {\n ...args,\n authorizeUrl: config.oauthAuthorizeUrl ?? 'https://api.final.ai/oauth2/authorize',\n clientId: await oauthClient(ctx, config),\n redirectUri: `${channelBaseUrl(config)}/b/${ctx.binding.id}/oauth/callback`,\n scope: 'offline_access',\n pkce: true,\n extra: { resource: config.oauthResource ?? 'https://api.final.ai/v1/connectors/mcp' },\n },\n ctx,\n ),\n },\n places: {\n kinds: ['live'],\n defaults: () => ({ create: 'direct-with-agent', replies: 'origin', audience: 'members' }),\n },\n receive: async () => ({ ignored: true, reason: 'voice-uses-stream' }),\n routes: [\n {\n method: 'GET',\n path: '/oauth/callback',\n handler: async (ctx) => {\n const saved = await takeOAuth(ctx.request, ctx);\n if (saved == null)\n return new Response('Invalid or expired link request', { status: 400 });\n const token = z.object({ access_token: z.string() }).parse(\n await responseJson(\n await ctx.credentials.fetch(\n config.oauthTokenUrl ?? 'https://api.final.ai/oauth2/token',\n {\n method: 'POST',\n body: new URLSearchParams({\n client_id: await oauthClient(ctx, config),\n resource: config.oauthResource ?? 'https://api.final.ai/v1/connectors/mcp',\n grant_type: 'authorization_code',\n code: saved.code,\n redirect_uri: saved.redirectUri,\n ...(saved.verifier == null ? {} : { code_verifier: saved.verifier }),\n }),\n },\n ),\n ),\n );\n const principal = userInfoSchema.parse(\n await responseJson(\n await ctx.credentials.fetch(\n config.oauthUserInfoUrl ?? 'https://api.final.ai/oauth2/userinfo',\n {\n headers: { authorization: `Bearer ${token.access_token}` },\n },\n ),\n ),\n );\n return confirmOAuth(\n { ticket: saved.ticket, expected: saved.principal, actual: principal },\n ctx,\n );\n },\n },\n {\n method: 'WS',\n path: '/stream',\n handler: async (ctx) => {\n const token =\n ctx.request.headers.get('authorization')?.replace(/^Bearer /, '') ??\n new URL(ctx.request.url).searchParams.get('access_token');\n if (token == null && ctx.authenticatedPrincipal == null)\n return new Response('A Final OAuth token is required.', { status: 401 });\n let authenticated = ctx.authenticatedPrincipal;\n if (authenticated == null && token != null) {\n try {\n authenticated = userInfoSchema.parse(\n await responseJson(\n await ctx.credentials.fetch(\n config.oauthUserInfoUrl ?? 'https://api.final.ai/oauth2/userinfo',\n {\n headers: { authorization: `Bearer ${token}` },\n },\n ),\n ),\n );\n } catch {\n return new Response('Invalid Final identity', { status: 401 });\n }\n }\n const principal = principalRefSchema.safeParse(authenticated);\n if (!principal.success) return new Response('Invalid Final identity', { status: 401 });\n ctx.socket.accept();\n const iterator = ctx.socket.messages[Symbol.asyncIterator]();\n const initial = await iterator.next();\n const start = startSchema.safeParse(\n typeof initial.value === 'string' ? parseJson(initial.value) : null,\n );\n if (\n !start.success ||\n start.data.principal.id !== principal.data.id ||\n start.data.principal.tenant !== principal.data.tenant\n ) {\n ctx.socket.close(1008, 'The speaker does not match the authenticated account.');\n return;\n }\n const remaining: AsyncIterable<string | Uint8Array> = {\n [Symbol.asyncIterator]: () => iterator,\n };\n await runVoiceConnection({\n ctx,\n socket: {\n ...ctx.socket,\n signal: ctx.socket.signal,\n messages: remaining,\n accept: (args) => ctx.socket.accept(args),\n send: (data) => ctx.socket.send(data),\n close: (code, reason) => ctx.socket.close(code, reason),\n },\n principal: principal.data,\n place: {\n kind: 'live',\n id: crypto.randomUUID(),\n ...(principal.data.tenant == null ? {} : { tenant: principal.data.tenant }),\n parent: {\n kind: 'person',\n id: principal.data.id,\n ...(principal.data.tenant == null ? {} : { tenant: principal.data.tenant }),\n },\n },\n encoding: start.data.encoding,\n sampleRate: start.data.sampleRate,\n voice: config.voice,\n recording: start.data.recording,\n });\n },\n },\n ],\n });\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["options", "text"]
7
+ }
@@ -0,0 +1,5 @@
1
+ import { type JsonObject, type JsonValue } from '@finalai/agent-provider';
2
+ export declare const webhookChannel: (options?: JsonObject) => import("@finalai/agent-provider").ChannelDefinitionIface<{
3
+ secret: string;
4
+ signatureHeader: string;
5
+ }, JsonValue, JsonValue>;
@@ -0,0 +1,76 @@
1
+ import {
2
+ defineChannel,
3
+ jsonObjectSchema,
4
+ jsonValueSchema,
5
+ packageRef,
6
+ placeRefSchema
7
+ } from "@finalai/agent-provider";
8
+ import * as z from "zod";
9
+ import { contentBlocksOf } from "./content.mjs";
10
+ import { parseJson, receipt, verifyHmac } from "./channel-utils.mjs";
11
+ const configSchema = z.object({
12
+ secret: z.string().min(1).default("webhook-signing-secret"),
13
+ signatureHeader: z.string().default("x-final-signature")
14
+ });
15
+ const inputSchema = z.object({
16
+ place: placeRefSchema,
17
+ content: z.array(jsonObjectSchema).min(1),
18
+ label: z.string().min(1),
19
+ idempotencyKey: z.string().min(1),
20
+ context: z.array(z.string()).optional()
21
+ });
22
+ const webhookChannel = (options = {}) => {
23
+ const config = configSchema.parse(options);
24
+ return defineChannel({
25
+ name: "webhook",
26
+ config,
27
+ installed: packageRef("@finalai/final-agent-provider/channels/webhook"),
28
+ credentials: { app: null, secrets: [config.secret] },
29
+ identity: { kind: "none" },
30
+ places: { kinds: ["webhook"] },
31
+ routes: [
32
+ {
33
+ method: "POST",
34
+ path: "/webhook",
35
+ handler: async (ctx) => {
36
+ const body = await ctx.request.text();
37
+ const secret = await ctx.credentials.secret(config.secret);
38
+ const signature = ctx.request.headers.get(config.signatureHeader);
39
+ if (secret == null || signature == null || !await verifyHmac({ secret, body, signature: signature.replace(/^sha256=/, "") }))
40
+ return new Response(null, { status: 401 });
41
+ const parsed = inputSchema.safeParse(parseJson(body));
42
+ if (!parsed.success) return new Response("Invalid webhook input", { status: 400 });
43
+ const result = await ctx.receive(jsonValueSchema.parse(parsed.data));
44
+ return Response.json(result, {
45
+ status: "accepted" in result && !result.accepted ? 403 : 202
46
+ });
47
+ }
48
+ }
49
+ ],
50
+ receive: async (input, ctx) => {
51
+ const parsed = inputSchema.safeParse(input);
52
+ if (!parsed.success) return { ignored: true, reason: "invalid-input" };
53
+ const route = await ctx.places.resolve(parsed.data.place);
54
+ if (route.kind !== "connected")
55
+ return {
56
+ accepted: false,
57
+ refusal: {
58
+ refused: "unconnected",
59
+ connectUrl: route.connectUrl,
60
+ message: "Connect this webhook to a chat in Final."
61
+ }
62
+ };
63
+ return receipt(
64
+ await ctx.conversation(route.conversation).input({
65
+ ...parsed.data,
66
+ content: contentBlocksOf(parsed.data.content),
67
+ origin: { place: parsed.data.place }
68
+ })
69
+ );
70
+ }
71
+ });
72
+ };
73
+ export {
74
+ webhookChannel
75
+ };
76
+ //# sourceMappingURL=webhook.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/channels/webhook.ts"],
4
+ "sourcesContent": ["import {\n defineChannel,\n jsonObjectSchema,\n jsonValueSchema,\n packageRef,\n placeRefSchema,\n type JsonObject,\n type JsonValue,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { contentBlocksOf } from \"./content.mjs\";\nimport { parseJson, receipt, verifyHmac } from \"./channel-utils.mjs\";\n\nconst configSchema = z.object({\n secret: z.string().min(1).default('webhook-signing-secret'),\n signatureHeader: z.string().default('x-final-signature'),\n});\nconst inputSchema = z.object({\n place: placeRefSchema,\n content: z.array(jsonObjectSchema).min(1),\n label: z.string().min(1),\n idempotencyKey: z.string().min(1),\n context: z.array(z.string()).optional(),\n});\nexport const webhookChannel = (options: JsonObject = {}) => {\n const config = configSchema.parse(options);\n return defineChannel({\n name: 'webhook',\n config,\n installed: packageRef('@finalai/final-agent-provider/channels/webhook'),\n credentials: { app: null, secrets: [config.secret] },\n identity: { kind: 'none' },\n places: { kinds: ['webhook'] },\n routes: [\n {\n method: 'POST',\n path: '/webhook',\n handler: async (ctx) => {\n const body = await ctx.request.text();\n const secret = await ctx.credentials.secret(config.secret);\n const signature = ctx.request.headers.get(config.signatureHeader);\n if (\n secret == null ||\n signature == null ||\n !(await verifyHmac({ secret, body, signature: signature.replace(/^sha256=/, '') }))\n )\n return new Response(null, { status: 401 });\n const parsed = inputSchema.safeParse(parseJson(body));\n if (!parsed.success) return new Response('Invalid webhook input', { status: 400 });\n const result = await ctx.receive(jsonValueSchema.parse(parsed.data));\n return Response.json(result, {\n status: 'accepted' in result && !result.accepted ? 403 : 202,\n });\n },\n },\n ],\n receive: async (input: JsonValue, ctx) => {\n const parsed = inputSchema.safeParse(input);\n if (!parsed.success) return { ignored: true, reason: 'invalid-input' };\n const route = await ctx.places.resolve(parsed.data.place);\n if (route.kind !== 'connected')\n return {\n accepted: false,\n refusal: {\n refused: 'unconnected',\n connectUrl: route.connectUrl,\n message: 'Connect this webhook to a chat in Final.',\n },\n };\n return receipt(\n await ctx.conversation(route.conversation).input({\n ...parsed.data,\n content: contentBlocksOf(parsed.data.content),\n origin: { place: parsed.data.place },\n }),\n );\n },\n });\n};\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,YAAY,OAAO;AACnB,SAAS,uBAAuB;AAChC,SAAS,WAAW,SAAS,kBAAkB;AAE/C,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,wBAAwB;AAAA,EAC1D,iBAAiB,EAAE,OAAO,EAAE,QAAQ,mBAAmB;AACzD,CAAC;AACD,MAAM,cAAc,EAAE,OAAO;AAAA,EAC3B,OAAO;AAAA,EACP,SAAS,EAAE,MAAM,gBAAgB,EAAE,IAAI,CAAC;AAAA,EACxC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAChC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AACxC,CAAC;AACM,MAAM,iBAAiB,CAAC,UAAsB,CAAC,MAAM;AAC1D,QAAM,SAAS,aAAa,MAAM,OAAO;AACzC,SAAO,cAAc;AAAA,IACnB,MAAM;AAAA,IACN;AAAA,IACA,WAAW,WAAW,gDAAgD;AAAA,IACtE,aAAa,EAAE,KAAK,MAAM,SAAS,CAAC,OAAO,MAAM,EAAE;AAAA,IACnD,UAAU,EAAE,MAAM,OAAO;AAAA,IACzB,QAAQ,EAAE,OAAO,CAAC,SAAS,EAAE;AAAA,IAC7B,QAAQ;AAAA,MACN;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAAS,OAAO,QAAQ;AACtB,gBAAM,OAAO,MAAM,IAAI,QAAQ,KAAK;AACpC,gBAAM,SAAS,MAAM,IAAI,YAAY,OAAO,OAAO,MAAM;AACzD,gBAAM,YAAY,IAAI,QAAQ,QAAQ,IAAI,OAAO,eAAe;AAChE,cACE,UAAU,QACV,aAAa,QACb,CAAE,MAAM,WAAW,EAAE,QAAQ,MAAM,WAAW,UAAU,QAAQ,YAAY,EAAE,EAAE,CAAC;AAEjF,mBAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAC3C,gBAAM,SAAS,YAAY,UAAU,UAAU,IAAI,CAAC;AACpD,cAAI,CAAC,OAAO,QAAS,QAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,IAAI,CAAC;AACjF,gBAAM,SAAS,MAAM,IAAI,QAAQ,gBAAgB,MAAM,OAAO,IAAI,CAAC;AACnE,iBAAO,SAAS,KAAK,QAAQ;AAAA,YAC3B,QAAQ,cAAc,UAAU,CAAC,OAAO,WAAW,MAAM;AAAA,UAC3D,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,OAAO,OAAkB,QAAQ;AACxC,YAAM,SAAS,YAAY,UAAU,KAAK;AAC1C,UAAI,CAAC,OAAO,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,gBAAgB;AACrE,YAAM,QAAQ,MAAM,IAAI,OAAO,QAAQ,OAAO,KAAK,KAAK;AACxD,UAAI,MAAM,SAAS;AACjB,eAAO;AAAA,UACL,UAAU;AAAA,UACV,SAAS;AAAA,YACP,SAAS;AAAA,YACT,YAAY,MAAM;AAAA,YAClB,SAAS;AAAA,UACX;AAAA,QACF;AACF,aAAO;AAAA,QACL,MAAM,IAAI,aAAa,MAAM,YAAY,EAAE,MAAM;AAAA,UAC/C,GAAG,OAAO;AAAA,UACV,SAAS,gBAAgB,OAAO,KAAK,OAAO;AAAA,UAC5C,QAAQ,EAAE,OAAO,OAAO,KAAK,MAAM;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -21,7 +21,7 @@ const sandboxWireOf = {
21
21
  [AdvertisedSandboxWire.HandleRpc]: SandboxWire.HandleRpc,
22
22
  [AdvertisedSandboxWire.Mcp]: SandboxWire.Mcp
23
23
  };
24
- const FINAL_CLIENT_INFO = { name: "final-agent-session-service", version: "1.0.0" };
24
+ const FINAL_CLIENT_INFO = { name: "final-agent-sdk", version: "1.0.0" };
25
25
  const DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
26
26
  const describeFromInitialize = (args) => {
27
27
  const session = args.response.capabilities?.session;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/harnesses/acp-describe.ts"],
4
- "sourcesContent": ["import {\n client,\n methods,\n PROTOCOL_VERSION,\n type InitializeResponse,\n type Stream,\n} from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n advertisedFinalExtensions,\n AdvertisedSandboxWire,\n requireProtocolV2,\n watchInitializeVersion,\n} from '@finalai/acp-session';\nimport {\n CredentialDelivery,\n DEFAULT_PROMPT_WHILE_RUNNING,\n DEFAULT_SESSION_SURVIVES_DISCONNECT,\n InferenceCredentialKind,\n McpTransportKind,\n SandboxWire,\n type AcpTransport,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\n\n// Describes an arbitrary ACP v2 agent from its `initialize` response: MCP\n// transports from `capabilities.session.mcp`, fork from\n// `capabilities.session.fork`, and Final's optional extensions from\n// `_meta[\"final.ai\"].supports`. A plain agent with no Final extension still\n// gets a complete description (\"a harness that implements no Final\n// extension works completely\"). The sandbox wires are `_meta[\"final.ai\"].consumes`\n// when the agent declares them, else the MCP projection whenever it takes MCP\n// servers.\n\nconst sandboxWireOf = {\n [AdvertisedSandboxWire.HandleRpc]: SandboxWire.HandleRpc,\n [AdvertisedSandboxWire.Mcp]: SandboxWire.Mcp,\n} satisfies Record<AdvertisedSandboxWire, SandboxWire>;\n\nexport const FINAL_CLIENT_INFO = { name: 'final-agent-session-service', version: '1.0.0' };\nexport const DEFAULT_CONNECT_TIMEOUT_MS = 10_000;\n\nexport const describeFromInitialize = (args: {\n response: InitializeResponse;\n transports: AcpTransport[];\n configSchema: JsonSchema;\n}): HarnessDescriptionIface => {\n const session = args.response.capabilities?.session;\n const mcpCapabilities = session?.mcp;\n const mcp: McpTransportKind[] = [];\n if (mcpCapabilities?.acp != null) mcp.push(McpTransportKind.Acp);\n if (mcpCapabilities?.http != null) mcp.push(McpTransportKind.Http);\n if (mcpCapabilities?.stdio != null) mcp.push(McpTransportKind.Stdio);\n const supports = advertisedFinalExtensions(args.response);\n return {\n configSchema: args.configSchema,\n acp: { transports: args.transports, mcp },\n // Native tools of an unknown program are its own business; bound targets\n // reach it only as the sandbox MCP projection.\n baseTools: {},\n consumes:\n supports.consumes == null\n ? mcp.length > 0\n ? [SandboxWire.Mcp]\n : []\n : // The projection is an MCP server: it needs an MCP transport to arrive.\n [...new Set(supports.consumes.map((wire) => sandboxWireOf[wire]))].filter(\n (wire) => wire !== SandboxWire.Mcp || mcp.length > 0,\n ),\n inference: {\n vendors: [],\n kinds: [InferenceCredentialKind.HarnessOwned],\n delivery: CredentialDelivery.AtOpen,\n },\n supports: {\n observe: supports.observe,\n // session/resume with replayFrom is base ACP v2; an agent can opt out through _meta.\n resumeReplay: supports.resumeReplay ?? true,\n fork: session?.fork != null,\n authorMeta: supports.authorMeta,\n },\n // Nothing in a plain ACP v2 `initialize` declares these; assume the\n // conservative profile.\n promptWhileRunning: DEFAULT_PROMPT_WHILE_RUNNING,\n sessionSurvivesDisconnect: DEFAULT_SESSION_SURVIVES_DISCONNECT,\n };\n};\n\n// Static description used before the remote has been reached (Build's config\n// form): nothing about the remote is known yet.\nexport const unprobedDescription = (args: {\n transports: AcpTransport[];\n configSchema: JsonSchema;\n}): HarnessDescriptionIface => ({\n configSchema: args.configSchema,\n acp: { transports: args.transports, mcp: [] },\n baseTools: {},\n consumes: [],\n inference: {\n vendors: [],\n kinds: [InferenceCredentialKind.HarnessOwned],\n delivery: CredentialDelivery.AtOpen,\n },\n supports: { observe: false, resumeReplay: false, fork: false, authorMeta: false },\n promptWhileRunning: DEFAULT_PROMPT_WHILE_RUNNING,\n sessionSurvivesDisconnect: DEFAULT_SESSION_SURVIVES_DISCONNECT,\n});\n\n// Runs `initialize` over a fresh stream and closes the connection. Any reply\n// but ACP v2 is `unsupported_protocol_version`: nothing in the plane\n// negotiates or converts v1.\nexport const initializeOver = async (args: {\n stream: Stream;\n timeoutMs: number;\n}): Promise<InitializeResponse> => {\n const watch = watchInitializeVersion(args.stream);\n const connection = client().connect(watch.stream);\n const timeout = Promise.withResolvers<never>();\n const timer = setTimeout(\n () => timeout.reject(new Error(`initialize did not complete within ${args.timeoutMs} ms`)),\n args.timeoutMs,\n );\n try {\n return await Promise.race([\n requireProtocolV2({\n watch,\n initialize: connection.agent.request(methods.agent.initialize, {\n protocolVersion: PROTOCOL_VERSION,\n info: FINAL_CLIENT_INFO,\n capabilities: {},\n }),\n }),\n timeout.promise,\n ]);\n } finally {\n clearTimeout(timer);\n connection.close();\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n client,\n methods,\n PROTOCOL_VERSION,\n type InitializeResponse,\n type Stream,\n} from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n advertisedFinalExtensions,\n AdvertisedSandboxWire,\n requireProtocolV2,\n watchInitializeVersion,\n} from '@finalai/acp-session';\nimport {\n CredentialDelivery,\n DEFAULT_PROMPT_WHILE_RUNNING,\n DEFAULT_SESSION_SURVIVES_DISCONNECT,\n InferenceCredentialKind,\n McpTransportKind,\n SandboxWire,\n type AcpTransport,\n type HarnessDescriptionIface,\n type JsonSchema,\n} from '@finalai/agent-provider';\n\n// Describes an arbitrary ACP v2 agent from its `initialize` response: MCP\n// transports from `capabilities.session.mcp`, fork from\n// `capabilities.session.fork`, and Final's optional extensions from\n// `_meta[\"final.ai\"].supports`. A plain agent with no Final extension still\n// gets a complete description (\"a harness that implements no Final\n// extension works completely\"). The sandbox wires are `_meta[\"final.ai\"].consumes`\n// when the agent declares them, else the MCP projection whenever it takes MCP\n// servers.\n\nconst sandboxWireOf = {\n [AdvertisedSandboxWire.HandleRpc]: SandboxWire.HandleRpc,\n [AdvertisedSandboxWire.Mcp]: SandboxWire.Mcp,\n} satisfies Record<AdvertisedSandboxWire, SandboxWire>;\n\nexport const FINAL_CLIENT_INFO = { name: 'final-agent-sdk', version: '1.0.0' };\nexport const DEFAULT_CONNECT_TIMEOUT_MS = 10_000;\n\nexport const describeFromInitialize = (args: {\n response: InitializeResponse;\n transports: AcpTransport[];\n configSchema: JsonSchema;\n}): HarnessDescriptionIface => {\n const session = args.response.capabilities?.session;\n const mcpCapabilities = session?.mcp;\n const mcp: McpTransportKind[] = [];\n if (mcpCapabilities?.acp != null) mcp.push(McpTransportKind.Acp);\n if (mcpCapabilities?.http != null) mcp.push(McpTransportKind.Http);\n if (mcpCapabilities?.stdio != null) mcp.push(McpTransportKind.Stdio);\n const supports = advertisedFinalExtensions(args.response);\n return {\n configSchema: args.configSchema,\n acp: { transports: args.transports, mcp },\n // Native tools of an unknown program are its own business; bound targets\n // reach it only as the sandbox MCP projection.\n baseTools: {},\n consumes:\n supports.consumes == null\n ? mcp.length > 0\n ? [SandboxWire.Mcp]\n : []\n : // The projection is an MCP server: it needs an MCP transport to arrive.\n [...new Set(supports.consumes.map((wire) => sandboxWireOf[wire]))].filter(\n (wire) => wire !== SandboxWire.Mcp || mcp.length > 0,\n ),\n inference: {\n vendors: [],\n kinds: [InferenceCredentialKind.HarnessOwned],\n delivery: CredentialDelivery.AtOpen,\n },\n supports: {\n observe: supports.observe,\n // session/resume with replayFrom is base ACP v2; an agent can opt out through _meta.\n resumeReplay: supports.resumeReplay ?? true,\n fork: session?.fork != null,\n authorMeta: supports.authorMeta,\n },\n // Nothing in a plain ACP v2 `initialize` declares these; assume the\n // conservative profile.\n promptWhileRunning: DEFAULT_PROMPT_WHILE_RUNNING,\n sessionSurvivesDisconnect: DEFAULT_SESSION_SURVIVES_DISCONNECT,\n };\n};\n\n// Static description used before the remote has been reached (Build's config\n// form): nothing about the remote is known yet.\nexport const unprobedDescription = (args: {\n transports: AcpTransport[];\n configSchema: JsonSchema;\n}): HarnessDescriptionIface => ({\n configSchema: args.configSchema,\n acp: { transports: args.transports, mcp: [] },\n baseTools: {},\n consumes: [],\n inference: {\n vendors: [],\n kinds: [InferenceCredentialKind.HarnessOwned],\n delivery: CredentialDelivery.AtOpen,\n },\n supports: { observe: false, resumeReplay: false, fork: false, authorMeta: false },\n promptWhileRunning: DEFAULT_PROMPT_WHILE_RUNNING,\n sessionSurvivesDisconnect: DEFAULT_SESSION_SURVIVES_DISCONNECT,\n});\n\n// Runs `initialize` over a fresh stream and closes the connection. Any reply\n// but ACP v2 is `unsupported_protocol_version`: nothing in the plane\n// negotiates or converts v1.\nexport const initializeOver = async (args: {\n stream: Stream;\n timeoutMs: number;\n}): Promise<InitializeResponse> => {\n const watch = watchInitializeVersion(args.stream);\n const connection = client().connect(watch.stream);\n const timeout = Promise.withResolvers<never>();\n const timer = setTimeout(\n () => timeout.reject(new Error(`initialize did not complete within ${args.timeoutMs} ms`)),\n args.timeoutMs,\n );\n try {\n return await Promise.race([\n requireProtocolV2({\n watch,\n initialize: connection.agent.request(methods.agent.initialize, {\n protocolVersion: PROTOCOL_VERSION,\n info: FINAL_CLIENT_INFO,\n capabilities: {},\n }),\n }),\n timeout.promise,\n ]);\n } finally {\n clearTimeout(timer);\n connection.close();\n }\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -18,7 +18,8 @@ export declare enum ClaudePermissionMode {
18
18
  Default = "default",
19
19
  AcceptEdits = "accept-edits",
20
20
  Plan = "plan",
21
- Bypass = "bypass"
21
+ Bypass = "bypass",
22
+ Auto = "auto"
22
23
  }
23
24
  export declare enum CodexApprovalPolicy {
24
25
  Untrusted = "untrusted",
@@ -26,6 +27,10 @@ export declare enum CodexApprovalPolicy {
26
27
  OnFailure = "on-failure",
27
28
  Never = "never"
28
29
  }
30
+ export declare enum CodexApprovalsReviewer {
31
+ User = "user",
32
+ AutoReview = "auto-review"
33
+ }
29
34
  export declare enum CodexSandboxMode {
30
35
  ReadOnly = "read-only",
31
36
  WorkspaceWrite = "workspace-write",
@@ -30,6 +30,7 @@ var ClaudePermissionMode = /* @__PURE__ */ ((ClaudePermissionMode2) => {
30
30
  ClaudePermissionMode2["AcceptEdits"] = "accept-edits";
31
31
  ClaudePermissionMode2["Plan"] = "plan";
32
32
  ClaudePermissionMode2["Bypass"] = "bypass";
33
+ ClaudePermissionMode2["Auto"] = "auto";
33
34
  return ClaudePermissionMode2;
34
35
  })(ClaudePermissionMode || {});
35
36
  var CodexApprovalPolicy = /* @__PURE__ */ ((CodexApprovalPolicy2) => {
@@ -39,6 +40,11 @@ var CodexApprovalPolicy = /* @__PURE__ */ ((CodexApprovalPolicy2) => {
39
40
  CodexApprovalPolicy2["Never"] = "never";
40
41
  return CodexApprovalPolicy2;
41
42
  })(CodexApprovalPolicy || {});
43
+ var CodexApprovalsReviewer = /* @__PURE__ */ ((CodexApprovalsReviewer2) => {
44
+ CodexApprovalsReviewer2["User"] = "user";
45
+ CodexApprovalsReviewer2["AutoReview"] = "auto-review";
46
+ return CodexApprovalsReviewer2;
47
+ })(CodexApprovalsReviewer || {});
42
48
  var CodexSandboxMode = /* @__PURE__ */ ((CodexSandboxMode2) => {
43
49
  CodexSandboxMode2["ReadOnly"] = "read-only";
44
50
  CodexSandboxMode2["WorkspaceWrite"] = "workspace-write";
@@ -118,6 +124,7 @@ const harnessBinding = (specifier, config) => ({
118
124
  export {
119
125
  ClaudePermissionMode,
120
126
  CodexApprovalPolicy,
127
+ CodexApprovalsReviewer,
121
128
  CodexSandboxMode,
122
129
  MODEL_REFERENCE_PATTERN2 as MODEL_REFERENCE_PATTERN,
123
130
  PiPermissionMode,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/harnesses/config-fields.ts"],
4
- "sourcesContent": ["import { MODEL_REFERENCE_PATTERN } from \"./model-reference.mjs\";\nimport {\n credentialPolicySchema,\n instructionFragmentSchema,\n jsonObjectSchema,\n jsonValueSchema,\n packageRef,\n SCHEMA_IDS,\n skillBundleSchema,\n type CredentialPolicyIface,\n type DynamicSlotIface,\n type InstructionFragmentIface,\n type JsonObject,\n type JsonSchema,\n type JsonValue,\n type PackageProviderRefIface,\n type SkillBundleIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\n\nexport { MODEL_REFERENCE_PATTERN } from \"./model-reference.mjs\";\n\n// Config-schema building blocks shared by the harness modules. Each harness\n// writes its JSON Schema (what Build renders, $ref-ing the shared\n// final://schemas/* fragments) and a zod mirror (what open() validates the\n// resolved config with) from these, and a test keeps the two aligned.\n\n// Mirrors the final://schemas/reasoning fragment's enum.\nexport enum ReasoningLevel {\n None = 'none',\n Minimal = 'minimal',\n Low = 'low',\n Medium = 'medium',\n High = 'high',\n Max = 'max',\n}\n\n// Pi and the Final harness.\nexport enum PiPermissionMode {\n Auto = 'auto',\n Ask = 'ask',\n Readonly = 'readonly',\n}\n\n// Claude Code and the nanocode Claude engine.\nexport enum ClaudePermissionMode {\n Default = 'default',\n AcceptEdits = 'accept-edits',\n Plan = 'plan',\n Bypass = 'bypass',\n}\n\n// Codex and the nanocode Codex engine.\nexport enum CodexApprovalPolicy {\n Untrusted = 'untrusted',\n OnRequest = 'on-request',\n OnFailure = 'on-failure',\n Never = 'never',\n}\n\n// The Codex CLI's OS sandbox on a host you run.\nexport enum CodexSandboxMode {\n ReadOnly = 'read-only',\n WorkspaceWrite = 'workspace-write',\n DangerFullAccess = 'danger-full-access',\n}\n\nexport interface SecretRefIface {\n secretKey: string;\n}\n\nexport type InstructionInput = InstructionFragmentIface | DynamicSlotIface;\nexport type SkillInput = SkillBundleIface | DynamicSlotIface;\n\nexport const configObjectJson = (args: {\n title: string;\n properties: Record<string, JsonSchema>;\n required?: string[];\n}): JsonSchema => ({\n type: 'object',\n title: args.title,\n additionalProperties: false,\n properties: args.properties,\n required: args.required ?? [],\n});\n\n// Hosted harnesses leave choices and defaults to the platform; explicit lists stay restricted.\nexport const modelJson = (ids?: readonly string[], defaultId?: string): JsonSchema => ({\n $ref: SCHEMA_IDS.modelPicker,\n type: 'string',\n ...(ids == null\n ? { minLength: 1, maxLength: 200, pattern: MODEL_REFERENCE_PATTERN }\n : { enum: [...ids] }),\n ...(defaultId == null ? {} : { default: defaultId }),\n});\n\nexport const reasoningJson = (levels: readonly ReasoningLevel[]): JsonSchema => ({\n $ref: SCHEMA_IDS.reasoning,\n enum: [...levels],\n});\n\nexport const credentialsJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.credentialPolicy });\n\nexport const permissionModeJson = (modes: readonly string[], defaultMode?: string): JsonSchema => {\n const schema: JsonSchema = { $ref: SCHEMA_IDS.permissionMode, enum: [...modes] };\n if (defaultMode != null) schema.default = defaultMode;\n return schema;\n};\n\nexport const instructionsJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.instructions });\nexport const skillsJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.skills });\nexport const secretRefJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.secretRef });\n\nexport const urlJson = (title: string, schemes: readonly string[]): JsonSchema => ({\n type: 'string',\n title,\n format: 'uri',\n pattern: `^(${schemes.join('|')})://`,\n});\n\nexport const absolutePathJson = (title: string): JsonSchema => ({\n type: 'string',\n title,\n pattern: '^/',\n});\n\nexport const modelZod = (ids?: readonly string[]) => {\n if (ids != null)\n return z.string().refine((id) => ids.includes(id), {\n message: `model must be one of: ${ids.join(', ')}`,\n });\n const pattern = new RegExp(MODEL_REFERENCE_PATTERN);\n return z.string().min(1).max(200).regex(pattern, {\n message: 'model must be a printable ASCII reference without empty path segments',\n });\n};\n\nexport const reasoningZod = (levels: readonly ReasoningLevel[]) =>\n z.nativeEnum(ReasoningLevel).refine((level) => levels.includes(level), {\n message: `reasoning must be one of: ${levels.join(', ')}`,\n });\n\nexport const credentialsZod = () => credentialPolicySchema;\nexport const instructionsZod = () => z.array(instructionFragmentSchema).default([]);\nexport const skillsZod = () => z.array(skillBundleSchema).default([]);\nexport const secretRefZod = () => z.object({ secretKey: z.string().min(1) });\n\nexport const urlZod = (schemes: readonly string[]) =>\n z\n .string()\n .url()\n .refine((value) => schemes.some((scheme) => value.startsWith(`${scheme}://`)), {\n message: `url must use one of: ${schemes.join(', ')}`,\n });\n\nexport const absolutePathZod = () => z.string().startsWith('/');\n\n// Throws a readable error naming the harness; open() surfaces it as the\n// session's open failure.\nexport const parseHarnessConfig = <T extends z.ZodType>(args: {\n specifier: string;\n schema: T;\n config: JsonValue;\n}): z.output<T> => {\n const parsed = args.schema.safeParse(args.config);\n if (parsed.success) return parsed.data;\n const issues = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`)\n .join('; ');\n throw new Error(`invalid config for ${args.specifier}: ${issues}`);\n};\n\n// Authoring input and provider-private payloads are typed objects; a JSON\n// round trip drops undefined fields and the schema proves the result is JSON.\nexport const toJsonValue = <Value>(value: Value): JsonValue =>\n jsonValueSchema.parse(JSON.parse(JSON.stringify(value)));\n\nexport const toJsonObject = <Value>(value: Value): JsonObject =>\n jsonObjectSchema.parse(JSON.parse(JSON.stringify(value)));\n\nexport type CredentialsInput = CredentialPolicyIface;\n\n// What an authoring helper (`serverlessPi({...})`) returns: the manifest's\n// harness binding.\nexport interface HarnessBindingOutputIface {\n harness: PackageProviderRefIface;\n config: object;\n}\n\nexport const harnessBinding = <Config extends object>(\n specifier: string,\n config: Config,\n): HarnessBindingOutputIface => ({\n harness: packageRef(specifier),\n config: { ...config },\n});\n"],
5
- "mappings": "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",
6
- "names": ["MODEL_REFERENCE_PATTERN", "ReasoningLevel", "PiPermissionMode", "ClaudePermissionMode", "CodexApprovalPolicy", "CodexSandboxMode"]
4
+ "sourcesContent": ["import { MODEL_REFERENCE_PATTERN } from \"./model-reference.mjs\";\nimport {\n credentialPolicySchema,\n instructionFragmentSchema,\n jsonObjectSchema,\n jsonValueSchema,\n packageRef,\n SCHEMA_IDS,\n skillBundleSchema,\n type CredentialPolicyIface,\n type DynamicSlotIface,\n type InstructionFragmentIface,\n type JsonObject,\n type JsonSchema,\n type JsonValue,\n type PackageProviderRefIface,\n type SkillBundleIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\n\nexport { MODEL_REFERENCE_PATTERN } from \"./model-reference.mjs\";\n\n// Config-schema building blocks shared by the harness modules. Each harness\n// writes its JSON Schema (what Build renders, $ref-ing the shared\n// final://schemas/* fragments) and a zod mirror (what open() validates the\n// resolved config with) from these, and a test keeps the two aligned.\n\n// Mirrors the final://schemas/reasoning fragment's enum.\nexport enum ReasoningLevel {\n None = 'none',\n Minimal = 'minimal',\n Low = 'low',\n Medium = 'medium',\n High = 'high',\n Max = 'max',\n}\n\n// Pi and the Final harness.\nexport enum PiPermissionMode {\n Auto = 'auto',\n Ask = 'ask',\n Readonly = 'readonly',\n}\n\n// Claude Code and the nanocode Claude engine.\nexport enum ClaudePermissionMode {\n Default = 'default',\n AcceptEdits = 'accept-edits',\n Plan = 'plan',\n Bypass = 'bypass',\n // The nanocode Claude engine only: a reviewer model answers what `default` would ask,\n // as Claude Code's auto mode does.\n Auto = 'auto',\n}\n\n// Codex and the nanocode Codex engine.\nexport enum CodexApprovalPolicy {\n Untrusted = 'untrusted',\n OnRequest = 'on-request',\n OnFailure = 'on-failure',\n Never = 'never',\n}\n\n// Who answers what the nanocode Codex engine's approval policy would ask, as the Codex\n// CLI's approvals_reviewer: the person, or a reviewer model.\nexport enum CodexApprovalsReviewer {\n User = 'user',\n AutoReview = 'auto-review',\n}\n\n// The Codex CLI's OS sandbox on a host you run.\nexport enum CodexSandboxMode {\n ReadOnly = 'read-only',\n WorkspaceWrite = 'workspace-write',\n DangerFullAccess = 'danger-full-access',\n}\n\nexport interface SecretRefIface {\n secretKey: string;\n}\n\nexport type InstructionInput = InstructionFragmentIface | DynamicSlotIface;\nexport type SkillInput = SkillBundleIface | DynamicSlotIface;\n\nexport const configObjectJson = (args: {\n title: string;\n properties: Record<string, JsonSchema>;\n required?: string[];\n}): JsonSchema => ({\n type: 'object',\n title: args.title,\n additionalProperties: false,\n properties: args.properties,\n required: args.required ?? [],\n});\n\n// Hosted harnesses leave choices and defaults to the platform; explicit lists stay restricted.\nexport const modelJson = (ids?: readonly string[], defaultId?: string): JsonSchema => ({\n $ref: SCHEMA_IDS.modelPicker,\n type: 'string',\n ...(ids == null\n ? { minLength: 1, maxLength: 200, pattern: MODEL_REFERENCE_PATTERN }\n : { enum: [...ids] }),\n ...(defaultId == null ? {} : { default: defaultId }),\n});\n\nexport const reasoningJson = (levels: readonly ReasoningLevel[]): JsonSchema => ({\n $ref: SCHEMA_IDS.reasoning,\n enum: [...levels],\n});\n\nexport const credentialsJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.credentialPolicy });\n\nexport const permissionModeJson = (modes: readonly string[], defaultMode?: string): JsonSchema => {\n const schema: JsonSchema = { $ref: SCHEMA_IDS.permissionMode, enum: [...modes] };\n if (defaultMode != null) schema.default = defaultMode;\n return schema;\n};\n\nexport const instructionsJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.instructions });\nexport const skillsJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.skills });\nexport const secretRefJson = (): JsonSchema => ({ $ref: SCHEMA_IDS.secretRef });\n\nexport const urlJson = (title: string, schemes: readonly string[]): JsonSchema => ({\n type: 'string',\n title,\n format: 'uri',\n pattern: `^(${schemes.join('|')})://`,\n});\n\nexport const absolutePathJson = (title: string): JsonSchema => ({\n type: 'string',\n title,\n pattern: '^/',\n});\n\nexport const modelZod = (ids?: readonly string[]) => {\n if (ids != null)\n return z.string().refine((id) => ids.includes(id), {\n message: `model must be one of: ${ids.join(', ')}`,\n });\n const pattern = new RegExp(MODEL_REFERENCE_PATTERN);\n return z.string().min(1).max(200).regex(pattern, {\n message: 'model must be a printable ASCII reference without empty path segments',\n });\n};\n\nexport const reasoningZod = (levels: readonly ReasoningLevel[]) =>\n z.nativeEnum(ReasoningLevel).refine((level) => levels.includes(level), {\n message: `reasoning must be one of: ${levels.join(', ')}`,\n });\n\nexport const credentialsZod = () => credentialPolicySchema;\nexport const instructionsZod = () => z.array(instructionFragmentSchema).default([]);\nexport const skillsZod = () => z.array(skillBundleSchema).default([]);\nexport const secretRefZod = () => z.object({ secretKey: z.string().min(1) });\n\nexport const urlZod = (schemes: readonly string[]) =>\n z\n .string()\n .url()\n .refine((value) => schemes.some((scheme) => value.startsWith(`${scheme}://`)), {\n message: `url must use one of: ${schemes.join(', ')}`,\n });\n\nexport const absolutePathZod = () => z.string().startsWith('/');\n\n// Throws a readable error naming the harness; open() surfaces it as the\n// session's open failure.\nexport const parseHarnessConfig = <T extends z.ZodType>(args: {\n specifier: string;\n schema: T;\n config: JsonValue;\n}): z.output<T> => {\n const parsed = args.schema.safeParse(args.config);\n if (parsed.success) return parsed.data;\n const issues = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`)\n .join('; ');\n throw new Error(`invalid config for ${args.specifier}: ${issues}`);\n};\n\n// Authoring input and provider-private payloads are typed objects; a JSON\n// round trip drops undefined fields and the schema proves the result is JSON.\nexport const toJsonValue = <Value>(value: Value): JsonValue =>\n jsonValueSchema.parse(JSON.parse(JSON.stringify(value)));\n\nexport const toJsonObject = <Value>(value: Value): JsonObject =>\n jsonObjectSchema.parse(JSON.parse(JSON.stringify(value)));\n\nexport type CredentialsInput = CredentialPolicyIface;\n\n// What an authoring helper (`serverlessPi({...})`) returns: the manifest's\n// harness binding.\nexport interface HarnessBindingOutputIface {\n harness: PackageProviderRefIface;\n config: object;\n}\n\nexport const harnessBinding = <Config extends object>(\n specifier: string,\n config: Config,\n): HarnessBindingOutputIface => ({\n harness: packageRef(specifier),\n config: { ...config },\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["MODEL_REFERENCE_PATTERN", "ReasoningLevel", "PiPermissionMode", "ClaudePermissionMode", "CodexApprovalPolicy", "CodexApprovalsReviewer", "CodexSandboxMode"]
7
7
  }
@@ -6,12 +6,12 @@ var NanocodeEngine = /* @__PURE__ */ ((NanocodeEngine2) => {
6
6
  const MCP_HTTP_REASON = "Serverless harnesses reach MCP servers over HTTP; stdio servers need a host.";
7
7
  const BACKGROUND_REASON = "Background commands stop when the session goes idle and parks, or when it is cancelled.";
8
8
  const SUBAGENT_REASON = "Serverless sessions run one agent; there is no subagent runtime.";
9
- const IMAGE_REASON = "Images attached to a message are not sent to the serverless engines yet; image tool results are.";
9
+ const IMAGE_REASON = "The engines take JPEG, PNG, GIF and WebP.";
10
10
  const NANOCODE_FIDELITY = {
11
11
  ["codex" /* Codex */]: [
12
12
  {
13
13
  feature: "Plan mode",
14
- nanocode: "`update_plan` is always offered and shown as the session plan.",
14
+ nanocode: "`update_plan` is always offered and shown as the session plan, whose steps are the steps of a Goal when the session is its working chat.",
15
15
  remoteOnly: "Codex's own plan and collaboration modes, as your CLI configures them.",
16
16
  gone: {
17
17
  what: "Plan mode (read-only planning, plan-mode questions).",
@@ -82,7 +82,7 @@ const NANOCODE_FIDELITY = {
82
82
  },
83
83
  {
84
84
  feature: "Approval policies",
85
- nanocode: "When the definition's tool policy is silent, `untrusted` asks before `exec_command` and `apply_patch`; `on-request`, `on-failure` and `never` run without asking.",
85
+ nanocode: "When the definition's tool policy is silent, `untrusted` asks before `exec_command` and `apply_patch`; `on-request`, `on-failure` and `never` run without asking. With `approvalsReviewer: 'auto-review'`, a reviewer model (`codex-auto-review` on a ChatGPT plan, `gpt-6-luna` otherwise, falling back to the session's model) answers what `untrusted` would ask: low and medium risk run, a rejected action goes to the person with the reviewer's reason, and a critical one is denied with codex-rs's rejection. The reviewer sees the person's messages, earlier tool calls, the definition's instructions and AGENTS.md, and `git status` before a command that could discard work. After 3 denials in a row or 10 of the last 50, the session asks the person until they allow a call, where Codex ends the turn.",
86
86
  remoteOnly: "The app-server's own policies together with `sandboxMode`.",
87
87
  gone: {
88
88
  what: "Escalation on failure and sandbox modes.",
@@ -92,10 +92,10 @@ const NANOCODE_FIDELITY = {
92
92
  },
93
93
  {
94
94
  feature: "Images in prompts",
95
- nanocode: "Not supported (`prompt.image` is absent); `view_image` and MCP image results reach the model.",
95
+ nanocode: "A message's JPEG, PNG, GIF and WebP images go to Codex as image input, a message sent while a turn runs joining that turn as Codex's does, as do `view_image` and MCP image results.",
96
96
  remoteOnly: "Prompt images, passed to Codex as image input.",
97
- gone: { what: "Images attached to a message.", reason: IMAGE_REASON },
98
- evidence: 'nanocode codex.test.ts "fidelity" (initialize capabilities)'
97
+ gone: { what: "Other image types.", reason: IMAGE_REASON },
98
+ evidence: 'nanocode codex.test.ts "fidelity" (advertises prompt images and sends them; moves an image prompt that arrives during a turn into it)'
99
99
  },
100
100
  {
101
101
  feature: "Compaction",
@@ -109,8 +109,8 @@ const NANOCODE_FIDELITY = {
109
109
  },
110
110
  {
111
111
  feature: "Native tool set",
112
- nanocode: "`exec_command`, `write_stdin` (shell), `apply_patch`, `view_image` (files) and `update_plan`, on the bound sandbox.",
113
- remoteOnly: "Codex's full tool set on your host (code mode, web search, its MCP and plugins).",
112
+ nanocode: "`exec_command`, `write_stdin` (shell), `apply_patch`, `view_image` (files) and `update_plan`, on the bound sandbox; `web__run`, OpenAI's web search, paid by the session's credential; and the workspace's AGENTS.md files as project instructions, from `$CODEX_HOME` and the repository root down to the working directory.",
113
+ remoteOnly: "Codex's full tool set on your host (code mode, image generation, its MCP and plugins).",
114
114
  gone: {
115
115
  what: "Every other Codex tool.",
116
116
  reason: "Serverless Codex has a fixed tool set that runs on the session's sandbox."
@@ -195,7 +195,7 @@ const NANOCODE_FIDELITY = {
195
195
  },
196
196
  {
197
197
  feature: "Permission modes",
198
- nanocode: "When the definition's tool policy is silent, `default` and `plan` ask before `Write` and `Bash`; `accept-edits` asks before `Bash` only; `bypass` never asks.",
198
+ nanocode: "When the definition's tool policy is silent, `default` and `plan` ask before `Write` and `Bash`; `accept-edits` asks before `Bash` only; `bypass` never asks; `auto` has a reviewer model (`claude-sonnet-5-5`, falling back to the session's model) judge every `Write` and `Bash`: low and medium risk run, a rejected action goes to the person with the reviewer's reason, and a critical one is denied with its reason. The reviewer sees the person's messages, earlier tool calls, the definition's instructions and CLAUDE.md, and `git status` before a command that could discard work. After 3 denials in a row or 20 in all, the session asks the person until they allow a call.",
199
199
  remoteOnly: "Claude Code's permission modes and the allow and deny rules in your settings.",
200
200
  gone: {
201
201
  what: "Allow and deny rules from Claude Code settings.",
@@ -205,10 +205,10 @@ const NANOCODE_FIDELITY = {
205
205
  },
206
206
  {
207
207
  feature: "Images in prompts",
208
- nanocode: "Not supported (`prompt.image` is absent); MCP image results reach the model.",
208
+ nanocode: "A message's JPEG, PNG, GIF and WebP images go to Claude, as do `Read` of an image and MCP image results.",
209
209
  remoteOnly: "Prompt images, passed to Claude Code.",
210
- gone: { what: "Images attached to a message.", reason: IMAGE_REASON },
211
- evidence: 'nanocode claude.test.ts "fidelity" (initialize capabilities)'
210
+ gone: { what: "Other image types.", reason: IMAGE_REASON },
211
+ evidence: 'nanocode claude.test.ts "fidelity" (advertises prompt images and sends them)'
212
212
  },
213
213
  {
214
214
  feature: "Compaction",
@@ -222,13 +222,13 @@ const NANOCODE_FIDELITY = {
222
222
  },
223
223
  {
224
224
  feature: "Native tool set",
225
- nanocode: "`Bash`, `BashOutput` (shell), `Read`, `Write` (files), on the bound sandbox.",
226
- remoteOnly: "Claude Code's full tool set on your host (`Edit`, `Glob`, `Grep`, `Task`, `WebFetch`, `WebSearch`, \u2026).",
225
+ nanocode: "`Bash`, `BashOutput` (shell); Claude Code's own `Read`, `Edit` and `Write` (files), with its rule that `Edit` and an overwriting `Write` need the file read first; Claude Code's own `TaskCreate`, `TaskGet`, `TaskList` and `TaskUpdate`, a task list kept across invocations and shown as the session plan, whose steps are the steps of a Goal when the session is its working chat; `WebSearch`, Anthropic's, paid by the session's credential; and CLAUDE.md files as project instructions, from `~/.claude` and each directory down to the working directory. Like Claude Code since 2.1.283, it searches through `Bash`: no `Glob` or `Grep`.",
226
+ remoteOnly: "Claude Code's full tool set on your host (`TaskStop`, `WebFetch`, `NotebookEdit`, Bash's persistent working directory and background tasks, \u2026).",
227
227
  gone: {
228
- what: "`Edit`, `Glob`, `Grep`, `Task`, `TodoWrite`, `WebFetch`, `WebSearch`, `NotebookEdit`.",
229
- reason: "Serverless Claude has a minimal tool set; it searches and edits through the shell."
228
+ what: "`TaskStop`, `WebFetch`, `NotebookEdit`; Bash keeping its working directory between calls.",
229
+ reason: "Serverless Claude keeps Claude Code's core tools: it fetches pages through the shell, and each Bash command starts in the workspace."
230
230
  },
231
- evidence: 'nanocode claude.test.ts "runs Bash on the shell capability and asks under default" (exact list)'
231
+ evidence: 'nanocode claude.test.ts "runs Bash on the shell capability and asks under default" (exact list), "Read, Edit and Write", "keeps the task list as the session plan"'
232
232
  }
233
233
  ]
234
234
  };