@mariozechner/pi-agent-core 0.13.1 → 0.14.1
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/dist/agent.d.ts.map +1 -1
- package/dist/agent.js.map +1 -1
- package/dist/transports/types.d.ts +2 -2
- package/dist/transports/types.d.ts.map +1 -1
- package/dist/transports/types.js.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
package/dist/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAA8B,MAAM,qBAAqB,CAAC;AAE7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAiDhG,MAAM,WAAW,YAAY;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,SAAS,EAAE,cAAc,CAAC;IAE1B,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEhF,SAAS,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC;CACpC;AAED,qBAAa,KAAK;IACjB,OAAO,CAAC,MAAM,CAUZ;IACF,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,kBAAkB,CAA6D;IACvF,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,oBAAoB,CAAC,CAAa;IAE1C,YAAY,IAAI,EAAE,YAAY,EAK7B;IAED,IAAI,KAAK,IAAI,UAAU,CAEtB;IAED,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAGjD;IAGD,eAAe,CAAC,CAAC,EAAE,MAAM,QAExB;IAED,QAAQ,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAEnC;IAED,gBAAgB,CAAC,CAAC,EAAE,aAAa,QAEhC;IAED,YAAY,CAAC,IAAI,EAAE,KAAK,GAAG,eAAe,QAEzC;IAED,YAAY,IAAI,KAAK,GAAG,eAAe,CAEtC;IAED,QAAQ,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAEnC;IAED,eAAe,CAAC,EAAE,EAAE,UAAU,EAAE,QAE/B;IAED,aAAa,CAAC,CAAC,EAAE,UAAU,QAE1B;IAEK,YAAY,CAAC,CAAC,EAAE,UAAU,iBAO/B;IAED,iBAAiB,SAEhB;IAED,aAAa,SAEZ;IAED,KAAK,SAEJ;IAED;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;IAED;;OAEG;IACH,KAAK,SAOJ;IAEK,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,iBAwLrD;IAED,OAAO,CAAC,IAAI;CAKZ","sourcesContent":["import type { ImageContent, Message, QueuedMessage, TextContent } from \"@mariozechner/pi-ai\";\nimport { getModel } from \"@mariozechner/pi-ai\";\nimport type { AgentTransport } from \"./transports/types.js\";\nimport type { AgentEvent, AgentState, AppMessage, Attachment, ThinkingLevel } from \"./types.js\";\n\n/**\n * Default message transformer: Keep only LLM-compatible messages, strip app-specific fields.\n * Converts attachments to proper content blocks (images → ImageContent, documents → TextContent).\n */\nfunction defaultMessageTransformer(messages: AppMessage[]): Message[] {\n\treturn messages\n\t\t.filter((m) => {\n\t\t\t// Only keep standard LLM message roles\n\t\t\treturn m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\";\n\t\t})\n\t\t.map((m) => {\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst { attachments, ...rest } = m as any;\n\n\t\t\t\t// If no attachments, return as-is\n\t\t\t\tif (!attachments || attachments.length === 0) {\n\t\t\t\t\treturn rest as Message;\n\t\t\t\t}\n\n\t\t\t\t// Convert attachments to content blocks\n\t\t\t\tconst content = Array.isArray(rest.content) ? [...rest.content] : [{ type: \"text\", text: rest.content }];\n\n\t\t\t\tfor (const attachment of attachments as Attachment[]) {\n\t\t\t\t\t// Add image blocks for image attachments\n\t\t\t\t\tif (attachment.type === \"image\") {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tdata: attachment.content,\n\t\t\t\t\t\t\tmimeType: attachment.mimeType,\n\t\t\t\t\t\t} as ImageContent);\n\t\t\t\t\t}\n\t\t\t\t\t// Add text blocks for documents with extracted text\n\t\t\t\t\telse if (attachment.type === \"document\" && attachment.extractedText) {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `\\n\\n[Document: ${attachment.fileName}]\\n${attachment.extractedText}`,\n\t\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t\t} as TextContent);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { ...rest, content } as Message;\n\t\t\t}\n\t\t\treturn m as Message;\n\t\t});\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\ttransport: AgentTransport;\n\t// Transform app messages to LLM-compatible messages before sending to transport\n\tmessageTransformer?: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\t// Queue mode: \"all\" = send all queued messages at once, \"one-at-a-time\" = send one queued message per turn\n\tqueueMode?: \"all\" | \"one-at-a-time\";\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate transport: AgentTransport;\n\tprivate messageTransformer: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\tprivate messageQueue: Array<QueuedMessage<AppMessage>> = [];\n\tprivate queueMode: \"all\" | \"one-at-a-time\";\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\n\tconstructor(opts: AgentOptions) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.transport = opts.transport;\n\t\tthis.messageTransformer = opts.messageTransformer || defaultMessageTransformer;\n\t\tthis.queueMode = opts.queueMode || \"one-at-a-time\";\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators - update internal state without emitting events\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: typeof this._state.model) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetQueueMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.queueMode = mode;\n\t}\n\n\tgetQueueMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.queueMode;\n\t}\n\n\tsetTools(t: typeof this._state.tools) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AppMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AppMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\tasync queueMessage(m: AppMessage) {\n\t\t// Transform message and queue it for injection at next turn\n\t\tconst transformed = await this.messageTransformer([m]);\n\t\tthis.messageQueue.push({\n\t\t\toriginal: m,\n\t\t\tllm: transformed[0], // undefined if filtered out\n\t\t});\n\t}\n\n\tclearMessageQueue() {\n\t\tthis.messageQueue = [];\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\t/**\n\t * Returns a promise that resolves when the current prompt completes.\n\t * Returns immediately resolved promise if no prompt is running.\n\t */\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\t/**\n\t * Clear all messages and state. Call abort() first if a prompt is in flight.\n\t */\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.messageQueue = [];\n\t}\n\n\tasync prompt(input: string, attachments?: Attachment[]) {\n\t\tconst model = this._state.model;\n\t\tif (!model) {\n\t\t\tthrow new Error(\"No model configured\");\n\t\t}\n\n\t\t// Set up running prompt tracking\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\t// Build user message with attachments\n\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\tif (attachments?.length) {\n\t\t\tfor (const a of attachments) {\n\t\t\t\tif (a.type === \"image\") {\n\t\t\t\t\tcontent.push({ type: \"image\", data: a.content, mimeType: a.mimeType });\n\t\t\t\t} else if (a.type === \"document\" && a.extractedText) {\n\t\t\t\t\tcontent.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `\\n\\n[Document: ${a.fileName}]\\n${a.extractedText}`,\n\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t} as TextContent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst userMessage: AppMessage = {\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\tattachments: attachments?.length ? attachments : undefined,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning =\n\t\t\tthis._state.thinkingLevel === \"off\"\n\t\t\t\t? undefined\n\t\t\t\t: this._state.thinkingLevel === \"minimal\"\n\t\t\t\t\t? \"low\"\n\t\t\t\t\t: this._state.thinkingLevel;\n\n\t\tconst cfg = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\ttools: this._state.tools,\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tgetQueuedMessages: async <T>() => {\n\t\t\t\t// Return queued messages based on queue mode\n\t\t\t\tif (this.queueMode === \"one-at-a-time\") {\n\t\t\t\t\t// Return only first message\n\t\t\t\t\tif (this.messageQueue.length > 0) {\n\t\t\t\t\t\tconst first = this.messageQueue[0];\n\t\t\t\t\t\tthis.messageQueue = this.messageQueue.slice(1);\n\t\t\t\t\t\treturn [first] as QueuedMessage<T>[];\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t} else {\n\t\t\t\t\t// Return all queued messages at once\n\t\t\t\t\tconst queued = this.messageQueue.slice();\n\t\t\t\t\tthis.messageQueue = [];\n\t\t\t\t\treturn queued as QueuedMessage<T>[];\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\n\t\t// Track all messages generated in this prompt\n\t\tconst generatedMessages: AppMessage[] = [];\n\n\t\ttry {\n\t\t\tlet partial: Message | null = null;\n\n\t\t\t// Transform app messages to LLM-compatible messages (initial set)\n\t\t\tconst llmMessages = await this.messageTransformer(this._state.messages);\n\n\t\t\tfor await (const ev of this.transport.run(\n\t\t\t\tllmMessages,\n\t\t\t\tuserMessage as Message,\n\t\t\t\tcfg,\n\t\t\t\tthis.abortController.signal,\n\t\t\t)) {\n\t\t\t\t// Pass through all events directly\n\t\t\t\tthis.emit(ev as AgentEvent);\n\n\t\t\t\t// Update internal state as needed\n\t\t\t\tswitch (ev.type) {\n\t\t\t\t\tcase \"message_start\": {\n\t\t\t\t\t\t// Track streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_update\": {\n\t\t\t\t\t\t// Update streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_end\": {\n\t\t\t\t\t\t// Add completed message to state\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(ev.message as AppMessage);\n\t\t\t\t\t\tgeneratedMessages.push(ev.message as AppMessage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_start\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.add(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_end\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.delete(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"turn_end\": {\n\t\t\t\t\t\t// Capture error from turn_end event\n\t\t\t\t\t\tif (ev.message.role === \"assistant\" && ev.message.errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = ev.message.errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"agent_end\": {\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial as AppMessage);\n\t\t\t\t\tgeneratedMessages.push(partial as AppMessage);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst msg: Message = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: {\n\t\t\t\t\tinput: 0,\n\t\t\t\t\toutput: 0,\n\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t},\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis.appendMessage(msg as AppMessage);\n\t\t\tgeneratedMessages.push(msg as AppMessage);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAA+C,MAAM,qBAAqB,CAAC;AAE9G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAiDhG,MAAM,WAAW,YAAY;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,SAAS,EAAE,cAAc,CAAC;IAE1B,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEhF,SAAS,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC;CACpC;AAED,qBAAa,KAAK;IACjB,OAAO,CAAC,MAAM,CAUZ;IACF,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,kBAAkB,CAA6D;IACvF,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,oBAAoB,CAAC,CAAa;IAE1C,YAAY,IAAI,EAAE,YAAY,EAK7B;IAED,IAAI,KAAK,IAAI,UAAU,CAEtB;IAED,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAGjD;IAGD,eAAe,CAAC,CAAC,EAAE,MAAM,QAExB;IAED,QAAQ,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAEnC;IAED,gBAAgB,CAAC,CAAC,EAAE,aAAa,QAEhC;IAED,YAAY,CAAC,IAAI,EAAE,KAAK,GAAG,eAAe,QAEzC;IAED,YAAY,IAAI,KAAK,GAAG,eAAe,CAEtC;IAED,QAAQ,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAEnC;IAED,eAAe,CAAC,EAAE,EAAE,UAAU,EAAE,QAE/B;IAED,aAAa,CAAC,CAAC,EAAE,UAAU,QAE1B;IAEK,YAAY,CAAC,CAAC,EAAE,UAAU,iBAO/B;IAED,iBAAiB,SAEhB;IAED,aAAa,SAEZ;IAED,KAAK,SAEJ;IAED;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;IAED;;OAEG;IACH,KAAK,SAOJ;IAEK,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,iBAwLrD;IAED,OAAO,CAAC,IAAI;CAKZ","sourcesContent":["import type { ImageContent, Message, QueuedMessage, ReasoningEffort, TextContent } from \"@mariozechner/pi-ai\";\nimport { getModel } from \"@mariozechner/pi-ai\";\nimport type { AgentTransport } from \"./transports/types.js\";\nimport type { AgentEvent, AgentState, AppMessage, Attachment, ThinkingLevel } from \"./types.js\";\n\n/**\n * Default message transformer: Keep only LLM-compatible messages, strip app-specific fields.\n * Converts attachments to proper content blocks (images → ImageContent, documents → TextContent).\n */\nfunction defaultMessageTransformer(messages: AppMessage[]): Message[] {\n\treturn messages\n\t\t.filter((m) => {\n\t\t\t// Only keep standard LLM message roles\n\t\t\treturn m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\";\n\t\t})\n\t\t.map((m) => {\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst { attachments, ...rest } = m as any;\n\n\t\t\t\t// If no attachments, return as-is\n\t\t\t\tif (!attachments || attachments.length === 0) {\n\t\t\t\t\treturn rest as Message;\n\t\t\t\t}\n\n\t\t\t\t// Convert attachments to content blocks\n\t\t\t\tconst content = Array.isArray(rest.content) ? [...rest.content] : [{ type: \"text\", text: rest.content }];\n\n\t\t\t\tfor (const attachment of attachments as Attachment[]) {\n\t\t\t\t\t// Add image blocks for image attachments\n\t\t\t\t\tif (attachment.type === \"image\") {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tdata: attachment.content,\n\t\t\t\t\t\t\tmimeType: attachment.mimeType,\n\t\t\t\t\t\t} as ImageContent);\n\t\t\t\t\t}\n\t\t\t\t\t// Add text blocks for documents with extracted text\n\t\t\t\t\telse if (attachment.type === \"document\" && attachment.extractedText) {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `\\n\\n[Document: ${attachment.fileName}]\\n${attachment.extractedText}`,\n\t\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t\t} as TextContent);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { ...rest, content } as Message;\n\t\t\t}\n\t\t\treturn m as Message;\n\t\t});\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\ttransport: AgentTransport;\n\t// Transform app messages to LLM-compatible messages before sending to transport\n\tmessageTransformer?: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\t// Queue mode: \"all\" = send all queued messages at once, \"one-at-a-time\" = send one queued message per turn\n\tqueueMode?: \"all\" | \"one-at-a-time\";\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate transport: AgentTransport;\n\tprivate messageTransformer: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\tprivate messageQueue: Array<QueuedMessage<AppMessage>> = [];\n\tprivate queueMode: \"all\" | \"one-at-a-time\";\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\n\tconstructor(opts: AgentOptions) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.transport = opts.transport;\n\t\tthis.messageTransformer = opts.messageTransformer || defaultMessageTransformer;\n\t\tthis.queueMode = opts.queueMode || \"one-at-a-time\";\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators - update internal state without emitting events\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: typeof this._state.model) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetQueueMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.queueMode = mode;\n\t}\n\n\tgetQueueMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.queueMode;\n\t}\n\n\tsetTools(t: typeof this._state.tools) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AppMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AppMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\tasync queueMessage(m: AppMessage) {\n\t\t// Transform message and queue it for injection at next turn\n\t\tconst transformed = await this.messageTransformer([m]);\n\t\tthis.messageQueue.push({\n\t\t\toriginal: m,\n\t\t\tllm: transformed[0], // undefined if filtered out\n\t\t});\n\t}\n\n\tclearMessageQueue() {\n\t\tthis.messageQueue = [];\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\t/**\n\t * Returns a promise that resolves when the current prompt completes.\n\t * Returns immediately resolved promise if no prompt is running.\n\t */\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\t/**\n\t * Clear all messages and state. Call abort() first if a prompt is in flight.\n\t */\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.messageQueue = [];\n\t}\n\n\tasync prompt(input: string, attachments?: Attachment[]) {\n\t\tconst model = this._state.model;\n\t\tif (!model) {\n\t\t\tthrow new Error(\"No model configured\");\n\t\t}\n\n\t\t// Set up running prompt tracking\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\t// Build user message with attachments\n\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\tif (attachments?.length) {\n\t\t\tfor (const a of attachments) {\n\t\t\t\tif (a.type === \"image\") {\n\t\t\t\t\tcontent.push({ type: \"image\", data: a.content, mimeType: a.mimeType });\n\t\t\t\t} else if (a.type === \"document\" && a.extractedText) {\n\t\t\t\t\tcontent.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `\\n\\n[Document: ${a.fileName}]\\n${a.extractedText}`,\n\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t} as TextContent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst userMessage: AppMessage = {\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\tattachments: attachments?.length ? attachments : undefined,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning: ReasoningEffort | undefined =\n\t\t\tthis._state.thinkingLevel === \"off\"\n\t\t\t\t? undefined\n\t\t\t\t: this._state.thinkingLevel === \"minimal\"\n\t\t\t\t\t? \"low\"\n\t\t\t\t\t: this._state.thinkingLevel;\n\n\t\tconst cfg = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\ttools: this._state.tools,\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tgetQueuedMessages: async <T>() => {\n\t\t\t\t// Return queued messages based on queue mode\n\t\t\t\tif (this.queueMode === \"one-at-a-time\") {\n\t\t\t\t\t// Return only first message\n\t\t\t\t\tif (this.messageQueue.length > 0) {\n\t\t\t\t\t\tconst first = this.messageQueue[0];\n\t\t\t\t\t\tthis.messageQueue = this.messageQueue.slice(1);\n\t\t\t\t\t\treturn [first] as QueuedMessage<T>[];\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t} else {\n\t\t\t\t\t// Return all queued messages at once\n\t\t\t\t\tconst queued = this.messageQueue.slice();\n\t\t\t\t\tthis.messageQueue = [];\n\t\t\t\t\treturn queued as QueuedMessage<T>[];\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\n\t\t// Track all messages generated in this prompt\n\t\tconst generatedMessages: AppMessage[] = [];\n\n\t\ttry {\n\t\t\tlet partial: Message | null = null;\n\n\t\t\t// Transform app messages to LLM-compatible messages (initial set)\n\t\t\tconst llmMessages = await this.messageTransformer(this._state.messages);\n\n\t\t\tfor await (const ev of this.transport.run(\n\t\t\t\tllmMessages,\n\t\t\t\tuserMessage as Message,\n\t\t\t\tcfg,\n\t\t\t\tthis.abortController.signal,\n\t\t\t)) {\n\t\t\t\t// Pass through all events directly\n\t\t\t\tthis.emit(ev as AgentEvent);\n\n\t\t\t\t// Update internal state as needed\n\t\t\t\tswitch (ev.type) {\n\t\t\t\t\tcase \"message_start\": {\n\t\t\t\t\t\t// Track streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_update\": {\n\t\t\t\t\t\t// Update streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_end\": {\n\t\t\t\t\t\t// Add completed message to state\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(ev.message as AppMessage);\n\t\t\t\t\t\tgeneratedMessages.push(ev.message as AppMessage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_start\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.add(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_end\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.delete(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"turn_end\": {\n\t\t\t\t\t\t// Capture error from turn_end event\n\t\t\t\t\t\tif (ev.message.role === \"assistant\" && ev.message.errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = ev.message.errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"agent_end\": {\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial as AppMessage);\n\t\t\t\t\tgeneratedMessages.push(partial as AppMessage);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst msg: Message = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: {\n\t\t\t\t\tinput: 0,\n\t\t\t\t\toutput: 0,\n\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t},\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis.appendMessage(msg as AppMessage);\n\t\t\tgeneratedMessages.push(msg as AppMessage);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
|
package/dist/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, Message, QueuedMessage, TextContent } from \"@mariozechner/pi-ai\";\nimport { getModel } from \"@mariozechner/pi-ai\";\nimport type { AgentTransport } from \"./transports/types.js\";\nimport type { AgentEvent, AgentState, AppMessage, Attachment, ThinkingLevel } from \"./types.js\";\n\n/**\n * Default message transformer: Keep only LLM-compatible messages, strip app-specific fields.\n * Converts attachments to proper content blocks (images → ImageContent, documents → TextContent).\n */\nfunction defaultMessageTransformer(messages: AppMessage[]): Message[] {\n\treturn messages\n\t\t.filter((m) => {\n\t\t\t// Only keep standard LLM message roles\n\t\t\treturn m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\";\n\t\t})\n\t\t.map((m) => {\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst { attachments, ...rest } = m as any;\n\n\t\t\t\t// If no attachments, return as-is\n\t\t\t\tif (!attachments || attachments.length === 0) {\n\t\t\t\t\treturn rest as Message;\n\t\t\t\t}\n\n\t\t\t\t// Convert attachments to content blocks\n\t\t\t\tconst content = Array.isArray(rest.content) ? [...rest.content] : [{ type: \"text\", text: rest.content }];\n\n\t\t\t\tfor (const attachment of attachments as Attachment[]) {\n\t\t\t\t\t// Add image blocks for image attachments\n\t\t\t\t\tif (attachment.type === \"image\") {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tdata: attachment.content,\n\t\t\t\t\t\t\tmimeType: attachment.mimeType,\n\t\t\t\t\t\t} as ImageContent);\n\t\t\t\t\t}\n\t\t\t\t\t// Add text blocks for documents with extracted text\n\t\t\t\t\telse if (attachment.type === \"document\" && attachment.extractedText) {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `\\n\\n[Document: ${attachment.fileName}]\\n${attachment.extractedText}`,\n\t\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t\t} as TextContent);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { ...rest, content } as Message;\n\t\t\t}\n\t\t\treturn m as Message;\n\t\t});\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\ttransport: AgentTransport;\n\t// Transform app messages to LLM-compatible messages before sending to transport\n\tmessageTransformer?: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\t// Queue mode: \"all\" = send all queued messages at once, \"one-at-a-time\" = send one queued message per turn\n\tqueueMode?: \"all\" | \"one-at-a-time\";\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate transport: AgentTransport;\n\tprivate messageTransformer: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\tprivate messageQueue: Array<QueuedMessage<AppMessage>> = [];\n\tprivate queueMode: \"all\" | \"one-at-a-time\";\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\n\tconstructor(opts: AgentOptions) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.transport = opts.transport;\n\t\tthis.messageTransformer = opts.messageTransformer || defaultMessageTransformer;\n\t\tthis.queueMode = opts.queueMode || \"one-at-a-time\";\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators - update internal state without emitting events\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: typeof this._state.model) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetQueueMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.queueMode = mode;\n\t}\n\n\tgetQueueMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.queueMode;\n\t}\n\n\tsetTools(t: typeof this._state.tools) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AppMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AppMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\tasync queueMessage(m: AppMessage) {\n\t\t// Transform message and queue it for injection at next turn\n\t\tconst transformed = await this.messageTransformer([m]);\n\t\tthis.messageQueue.push({\n\t\t\toriginal: m,\n\t\t\tllm: transformed[0], // undefined if filtered out\n\t\t});\n\t}\n\n\tclearMessageQueue() {\n\t\tthis.messageQueue = [];\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\t/**\n\t * Returns a promise that resolves when the current prompt completes.\n\t * Returns immediately resolved promise if no prompt is running.\n\t */\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\t/**\n\t * Clear all messages and state. Call abort() first if a prompt is in flight.\n\t */\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.messageQueue = [];\n\t}\n\n\tasync prompt(input: string, attachments?: Attachment[]) {\n\t\tconst model = this._state.model;\n\t\tif (!model) {\n\t\t\tthrow new Error(\"No model configured\");\n\t\t}\n\n\t\t// Set up running prompt tracking\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\t// Build user message with attachments\n\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\tif (attachments?.length) {\n\t\t\tfor (const a of attachments) {\n\t\t\t\tif (a.type === \"image\") {\n\t\t\t\t\tcontent.push({ type: \"image\", data: a.content, mimeType: a.mimeType });\n\t\t\t\t} else if (a.type === \"document\" && a.extractedText) {\n\t\t\t\t\tcontent.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `\\n\\n[Document: ${a.fileName}]\\n${a.extractedText}`,\n\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t} as TextContent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst userMessage: AppMessage = {\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\tattachments: attachments?.length ? attachments : undefined,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning =\n\t\t\tthis._state.thinkingLevel === \"off\"\n\t\t\t\t? undefined\n\t\t\t\t: this._state.thinkingLevel === \"minimal\"\n\t\t\t\t\t? \"low\"\n\t\t\t\t\t: this._state.thinkingLevel;\n\n\t\tconst cfg = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\ttools: this._state.tools,\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tgetQueuedMessages: async <T>() => {\n\t\t\t\t// Return queued messages based on queue mode\n\t\t\t\tif (this.queueMode === \"one-at-a-time\") {\n\t\t\t\t\t// Return only first message\n\t\t\t\t\tif (this.messageQueue.length > 0) {\n\t\t\t\t\t\tconst first = this.messageQueue[0];\n\t\t\t\t\t\tthis.messageQueue = this.messageQueue.slice(1);\n\t\t\t\t\t\treturn [first] as QueuedMessage<T>[];\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t} else {\n\t\t\t\t\t// Return all queued messages at once\n\t\t\t\t\tconst queued = this.messageQueue.slice();\n\t\t\t\t\tthis.messageQueue = [];\n\t\t\t\t\treturn queued as QueuedMessage<T>[];\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\n\t\t// Track all messages generated in this prompt\n\t\tconst generatedMessages: AppMessage[] = [];\n\n\t\ttry {\n\t\t\tlet partial: Message | null = null;\n\n\t\t\t// Transform app messages to LLM-compatible messages (initial set)\n\t\t\tconst llmMessages = await this.messageTransformer(this._state.messages);\n\n\t\t\tfor await (const ev of this.transport.run(\n\t\t\t\tllmMessages,\n\t\t\t\tuserMessage as Message,\n\t\t\t\tcfg,\n\t\t\t\tthis.abortController.signal,\n\t\t\t)) {\n\t\t\t\t// Pass through all events directly\n\t\t\t\tthis.emit(ev as AgentEvent);\n\n\t\t\t\t// Update internal state as needed\n\t\t\t\tswitch (ev.type) {\n\t\t\t\t\tcase \"message_start\": {\n\t\t\t\t\t\t// Track streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_update\": {\n\t\t\t\t\t\t// Update streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_end\": {\n\t\t\t\t\t\t// Add completed message to state\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(ev.message as AppMessage);\n\t\t\t\t\t\tgeneratedMessages.push(ev.message as AppMessage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_start\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.add(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_end\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.delete(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"turn_end\": {\n\t\t\t\t\t\t// Capture error from turn_end event\n\t\t\t\t\t\tif (ev.message.role === \"assistant\" && ev.message.errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = ev.message.errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"agent_end\": {\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial as AppMessage);\n\t\t\t\t\tgeneratedMessages.push(partial as AppMessage);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst msg: Message = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: {\n\t\t\t\t\tinput: 0,\n\t\t\t\t\toutput: 0,\n\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t},\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis.appendMessage(msg as AppMessage);\n\t\t\tgeneratedMessages.push(msg as AppMessage);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, Message, QueuedMessage, ReasoningEffort, TextContent } from \"@mariozechner/pi-ai\";\nimport { getModel } from \"@mariozechner/pi-ai\";\nimport type { AgentTransport } from \"./transports/types.js\";\nimport type { AgentEvent, AgentState, AppMessage, Attachment, ThinkingLevel } from \"./types.js\";\n\n/**\n * Default message transformer: Keep only LLM-compatible messages, strip app-specific fields.\n * Converts attachments to proper content blocks (images → ImageContent, documents → TextContent).\n */\nfunction defaultMessageTransformer(messages: AppMessage[]): Message[] {\n\treturn messages\n\t\t.filter((m) => {\n\t\t\t// Only keep standard LLM message roles\n\t\t\treturn m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\";\n\t\t})\n\t\t.map((m) => {\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst { attachments, ...rest } = m as any;\n\n\t\t\t\t// If no attachments, return as-is\n\t\t\t\tif (!attachments || attachments.length === 0) {\n\t\t\t\t\treturn rest as Message;\n\t\t\t\t}\n\n\t\t\t\t// Convert attachments to content blocks\n\t\t\t\tconst content = Array.isArray(rest.content) ? [...rest.content] : [{ type: \"text\", text: rest.content }];\n\n\t\t\t\tfor (const attachment of attachments as Attachment[]) {\n\t\t\t\t\t// Add image blocks for image attachments\n\t\t\t\t\tif (attachment.type === \"image\") {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tdata: attachment.content,\n\t\t\t\t\t\t\tmimeType: attachment.mimeType,\n\t\t\t\t\t\t} as ImageContent);\n\t\t\t\t\t}\n\t\t\t\t\t// Add text blocks for documents with extracted text\n\t\t\t\t\telse if (attachment.type === \"document\" && attachment.extractedText) {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `\\n\\n[Document: ${attachment.fileName}]\\n${attachment.extractedText}`,\n\t\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t\t} as TextContent);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { ...rest, content } as Message;\n\t\t\t}\n\t\t\treturn m as Message;\n\t\t});\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\ttransport: AgentTransport;\n\t// Transform app messages to LLM-compatible messages before sending to transport\n\tmessageTransformer?: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\t// Queue mode: \"all\" = send all queued messages at once, \"one-at-a-time\" = send one queued message per turn\n\tqueueMode?: \"all\" | \"one-at-a-time\";\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate transport: AgentTransport;\n\tprivate messageTransformer: (messages: AppMessage[]) => Message[] | Promise<Message[]>;\n\tprivate messageQueue: Array<QueuedMessage<AppMessage>> = [];\n\tprivate queueMode: \"all\" | \"one-at-a-time\";\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\n\tconstructor(opts: AgentOptions) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.transport = opts.transport;\n\t\tthis.messageTransformer = opts.messageTransformer || defaultMessageTransformer;\n\t\tthis.queueMode = opts.queueMode || \"one-at-a-time\";\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators - update internal state without emitting events\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: typeof this._state.model) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetQueueMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.queueMode = mode;\n\t}\n\n\tgetQueueMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.queueMode;\n\t}\n\n\tsetTools(t: typeof this._state.tools) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AppMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AppMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\tasync queueMessage(m: AppMessage) {\n\t\t// Transform message and queue it for injection at next turn\n\t\tconst transformed = await this.messageTransformer([m]);\n\t\tthis.messageQueue.push({\n\t\t\toriginal: m,\n\t\t\tllm: transformed[0], // undefined if filtered out\n\t\t});\n\t}\n\n\tclearMessageQueue() {\n\t\tthis.messageQueue = [];\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\t/**\n\t * Returns a promise that resolves when the current prompt completes.\n\t * Returns immediately resolved promise if no prompt is running.\n\t */\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\t/**\n\t * Clear all messages and state. Call abort() first if a prompt is in flight.\n\t */\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.messageQueue = [];\n\t}\n\n\tasync prompt(input: string, attachments?: Attachment[]) {\n\t\tconst model = this._state.model;\n\t\tif (!model) {\n\t\t\tthrow new Error(\"No model configured\");\n\t\t}\n\n\t\t// Set up running prompt tracking\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\t// Build user message with attachments\n\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\tif (attachments?.length) {\n\t\t\tfor (const a of attachments) {\n\t\t\t\tif (a.type === \"image\") {\n\t\t\t\t\tcontent.push({ type: \"image\", data: a.content, mimeType: a.mimeType });\n\t\t\t\t} else if (a.type === \"document\" && a.extractedText) {\n\t\t\t\t\tcontent.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `\\n\\n[Document: ${a.fileName}]\\n${a.extractedText}`,\n\t\t\t\t\t\tisDocument: true,\n\t\t\t\t\t} as TextContent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst userMessage: AppMessage = {\n\t\t\trole: \"user\",\n\t\t\tcontent,\n\t\t\tattachments: attachments?.length ? attachments : undefined,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning: ReasoningEffort | undefined =\n\t\t\tthis._state.thinkingLevel === \"off\"\n\t\t\t\t? undefined\n\t\t\t\t: this._state.thinkingLevel === \"minimal\"\n\t\t\t\t\t? \"low\"\n\t\t\t\t\t: this._state.thinkingLevel;\n\n\t\tconst cfg = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\ttools: this._state.tools,\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tgetQueuedMessages: async <T>() => {\n\t\t\t\t// Return queued messages based on queue mode\n\t\t\t\tif (this.queueMode === \"one-at-a-time\") {\n\t\t\t\t\t// Return only first message\n\t\t\t\t\tif (this.messageQueue.length > 0) {\n\t\t\t\t\t\tconst first = this.messageQueue[0];\n\t\t\t\t\t\tthis.messageQueue = this.messageQueue.slice(1);\n\t\t\t\t\t\treturn [first] as QueuedMessage<T>[];\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t} else {\n\t\t\t\t\t// Return all queued messages at once\n\t\t\t\t\tconst queued = this.messageQueue.slice();\n\t\t\t\t\tthis.messageQueue = [];\n\t\t\t\t\treturn queued as QueuedMessage<T>[];\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\n\t\t// Track all messages generated in this prompt\n\t\tconst generatedMessages: AppMessage[] = [];\n\n\t\ttry {\n\t\t\tlet partial: Message | null = null;\n\n\t\t\t// Transform app messages to LLM-compatible messages (initial set)\n\t\t\tconst llmMessages = await this.messageTransformer(this._state.messages);\n\n\t\t\tfor await (const ev of this.transport.run(\n\t\t\t\tllmMessages,\n\t\t\t\tuserMessage as Message,\n\t\t\t\tcfg,\n\t\t\t\tthis.abortController.signal,\n\t\t\t)) {\n\t\t\t\t// Pass through all events directly\n\t\t\t\tthis.emit(ev as AgentEvent);\n\n\t\t\t\t// Update internal state as needed\n\t\t\t\tswitch (ev.type) {\n\t\t\t\t\tcase \"message_start\": {\n\t\t\t\t\t\t// Track streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_update\": {\n\t\t\t\t\t\t// Update streaming message\n\t\t\t\t\t\tpartial = ev.message;\n\t\t\t\t\t\tthis._state.streamMessage = ev.message;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_end\": {\n\t\t\t\t\t\t// Add completed message to state\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(ev.message as AppMessage);\n\t\t\t\t\t\tgeneratedMessages.push(ev.message as AppMessage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_start\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.add(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"tool_execution_end\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.delete(ev.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"turn_end\": {\n\t\t\t\t\t\t// Capture error from turn_end event\n\t\t\t\t\t\tif (ev.message.role === \"assistant\" && ev.message.errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = ev.message.errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"agent_end\": {\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial as AppMessage);\n\t\t\t\t\tgeneratedMessages.push(partial as AppMessage);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst msg: Message = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: {\n\t\t\t\t\tinput: 0,\n\t\t\t\t\toutput: 0,\n\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t},\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis.appendMessage(msg as AppMessage);\n\t\t\tgeneratedMessages.push(msg as AppMessage);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentEvent, AgentTool, Message, Model, QueuedMessage } from "@mariozechner/pi-ai";
|
|
1
|
+
import type { AgentEvent, AgentTool, Message, Model, QueuedMessage, ReasoningEffort } from "@mariozechner/pi-ai";
|
|
2
2
|
/**
|
|
3
3
|
* The minimal configuration needed to run an agent turn.
|
|
4
4
|
*/
|
|
@@ -6,7 +6,7 @@ export interface AgentRunConfig {
|
|
|
6
6
|
systemPrompt: string;
|
|
7
7
|
tools: AgentTool<any>[];
|
|
8
8
|
model: Model<any>;
|
|
9
|
-
reasoning?:
|
|
9
|
+
reasoning?: ReasoningEffort;
|
|
10
10
|
getQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEjH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,iBAAiB,CAAC,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CACzD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B,GAAG,CACF,QAAQ,EAAE,OAAO,EAAE,EACnB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,aAAa,CAAC,UAAU,CAAC,CAAC;CAC7B","sourcesContent":["import type { AgentEvent, AgentTool, Message, Model, QueuedMessage, ReasoningEffort } from \"@mariozechner/pi-ai\";\n\n/**\n * The minimal configuration needed to run an agent turn.\n */\nexport interface AgentRunConfig {\n\tsystemPrompt: string;\n\ttools: AgentTool<any>[];\n\tmodel: Model<any>;\n\treasoning?: ReasoningEffort;\n\tgetQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;\n}\n\n/**\n * Transport interface for executing agent turns.\n * Transports handle the communication with LLM providers,\n * abstracting away the details of API calls, proxies, etc.\n *\n * Events yielded must match the @mariozechner/pi-ai AgentEvent types.\n */\nexport interface AgentTransport {\n\trun(\n\t\tmessages: Message[],\n\t\tuserMessage: Message,\n\t\tconfig: AgentRunConfig,\n\t\tsignal?: AbortSignal,\n\t): AsyncIterable<AgentEvent>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentEvent, AgentTool, Message, Model, QueuedMessage } from \"@mariozechner/pi-ai\";\n\n/**\n * The minimal configuration needed to run an agent turn.\n */\nexport interface AgentRunConfig {\n\tsystemPrompt: string;\n\ttools: AgentTool<any>[];\n\tmodel: Model<any>;\n\treasoning?:
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentEvent, AgentTool, Message, Model, QueuedMessage, ReasoningEffort } from \"@mariozechner/pi-ai\";\n\n/**\n * The minimal configuration needed to run an agent turn.\n */\nexport interface AgentRunConfig {\n\tsystemPrompt: string;\n\ttools: AgentTool<any>[];\n\tmodel: Model<any>;\n\treasoning?: ReasoningEffort;\n\tgetQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;\n}\n\n/**\n * Transport interface for executing agent turns.\n * Transports handle the communication with LLM providers,\n * abstracting away the details of API calls, proxies, etc.\n *\n * Events yielded must match the @mariozechner/pi-ai AgentEvent types.\n */\nexport interface AgentTransport {\n\trun(\n\t\tmessages: Message[],\n\t\tuserMessage: Message,\n\t\tconfig: AgentRunConfig,\n\t\tsignal?: AbortSignal,\n\t): AsyncIterable<AgentEvent>;\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -15,8 +15,9 @@ export interface Attachment {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Thinking/reasoning level for models that support it.
|
|
18
|
+
* Note: "xhigh" is only supported by OpenAI codex-max models.
|
|
18
19
|
*/
|
|
19
|
-
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high";
|
|
20
|
+
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
20
21
|
/**
|
|
21
22
|
* User message with optional attachments.
|
|
22
23
|
*/
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,OAAO,EACP,KAAK,EACL,WAAW,EACX,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,OAAO,EACP,KAAK,EACL,WAAW,EACX,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,WAAW,GAAG;IAAE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC;AAEtF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;CAE9B;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GACnB,gBAAgB,GAChB,0BAA0B,GAC1B,OAAO,GACP,cAAc,CAAC,MAAM,cAAc,CAAC,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAEnB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,UAAU,EAAE,CAAA;CAAE,GAE7C;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,GAEpE;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GAE9C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC;IAAC,qBAAqB,EAAE,qBAAqB,CAAA;CAAE,GAC7F;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GAE5C;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,GACjF;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC","sourcesContent":["import type {\n\tAgentTool,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tMessage,\n\tModel,\n\tUserMessage,\n} from \"@mariozechner/pi-ai\";\n\n/**\n * Attachment type definition.\n * Processing is done by consumers (e.g., document extraction in web-ui).\n */\nexport interface Attachment {\n\tid: string;\n\ttype: \"image\" | \"document\";\n\tfileName: string;\n\tmimeType: string;\n\tsize: number;\n\tcontent: string; // base64 encoded (without data URL prefix)\n\textractedText?: string; // For documents\n\tpreview?: string; // base64 image preview\n}\n\n/**\n * Thinking/reasoning level for models that support it.\n * Note: \"xhigh\" is only supported by OpenAI codex-max models.\n */\nexport type ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\n/**\n * User message with optional attachments.\n */\nexport type UserMessageWithAttachments = UserMessage & { attachments?: Attachment[] };\n\n/**\n * Extensible interface for custom app messages.\n * Apps can extend via declaration merging:\n *\n * @example\n * ```typescript\n * declare module \"@mariozechner/agent\" {\n * interface CustomMessages {\n * artifact: ArtifactMessage;\n * notification: NotificationMessage;\n * }\n * }\n * ```\n */\nexport interface CustomMessages {\n\t// Empty by default - apps extend via declaration merging\n}\n\n/**\n * AppMessage: Union of LLM messages + attachments + custom messages.\n * This abstraction allows apps to add custom message types while maintaining\n * type safety and compatibility with the base LLM messages.\n */\nexport type AppMessage =\n\t| AssistantMessage\n\t| UserMessageWithAttachments\n\t| Message // Includes ToolResultMessage\n\t| CustomMessages[keyof CustomMessages];\n\n/**\n * Agent state containing all configuration and conversation data.\n */\nexport interface AgentState {\n\tsystemPrompt: string;\n\tmodel: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\ttools: AgentTool<any>[];\n\tmessages: AppMessage[]; // Can include attachments + custom message types\n\tisStreaming: boolean;\n\tstreamMessage: Message | null;\n\tpendingToolCalls: Set<string>;\n\terror?: string;\n}\n\n/**\n * Events emitted by the Agent for UI updates.\n * These events provide fine-grained lifecycle information for messages, turns, and tool executions.\n */\nexport type AgentEvent =\n\t// Agent lifecycle\n\t| { type: \"agent_start\" }\n\t| { type: \"agent_end\"; messages: AppMessage[] }\n\t// Turn lifecycle - a turn is one assistant response + any tool calls/results\n\t| { type: \"turn_start\" }\n\t| { type: \"turn_end\"; message: AppMessage; toolResults: AppMessage[] }\n\t// Message lifecycle - emitted for user, assistant, and toolResult messages\n\t| { type: \"message_start\"; message: AppMessage }\n\t// Only emitted for assistant messages during streaming\n\t| { type: \"message_update\"; message: AppMessage; assistantMessageEvent: AssistantMessageEvent }\n\t| { type: \"message_end\"; message: AppMessage }\n\t// Tool execution lifecycle\n\t| { type: \"tool_execution_start\"; toolCallId: string; toolName: string; args: any }\n\t| { type: \"tool_execution_end\"; toolCallId: string; toolName: string; result: any; isError: boolean };\n"]}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n\tAgentTool,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tMessage,\n\tModel,\n\tUserMessage,\n} from \"@mariozechner/pi-ai\";\n\n/**\n * Attachment type definition.\n * Processing is done by consumers (e.g., document extraction in web-ui).\n */\nexport interface Attachment {\n\tid: string;\n\ttype: \"image\" | \"document\";\n\tfileName: string;\n\tmimeType: string;\n\tsize: number;\n\tcontent: string; // base64 encoded (without data URL prefix)\n\textractedText?: string; // For documents\n\tpreview?: string; // base64 image preview\n}\n\n/**\n * Thinking/reasoning level for models that support it.\n */\nexport type ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\";\n\n/**\n * User message with optional attachments.\n */\nexport type UserMessageWithAttachments = UserMessage & { attachments?: Attachment[] };\n\n/**\n * Extensible interface for custom app messages.\n * Apps can extend via declaration merging:\n *\n * @example\n * ```typescript\n * declare module \"@mariozechner/agent\" {\n * interface CustomMessages {\n * artifact: ArtifactMessage;\n * notification: NotificationMessage;\n * }\n * }\n * ```\n */\nexport interface CustomMessages {\n\t// Empty by default - apps extend via declaration merging\n}\n\n/**\n * AppMessage: Union of LLM messages + attachments + custom messages.\n * This abstraction allows apps to add custom message types while maintaining\n * type safety and compatibility with the base LLM messages.\n */\nexport type AppMessage =\n\t| AssistantMessage\n\t| UserMessageWithAttachments\n\t| Message // Includes ToolResultMessage\n\t| CustomMessages[keyof CustomMessages];\n\n/**\n * Agent state containing all configuration and conversation data.\n */\nexport interface AgentState {\n\tsystemPrompt: string;\n\tmodel: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\ttools: AgentTool<any>[];\n\tmessages: AppMessage[]; // Can include attachments + custom message types\n\tisStreaming: boolean;\n\tstreamMessage: Message | null;\n\tpendingToolCalls: Set<string>;\n\terror?: string;\n}\n\n/**\n * Events emitted by the Agent for UI updates.\n * These events provide fine-grained lifecycle information for messages, turns, and tool executions.\n */\nexport type AgentEvent =\n\t// Agent lifecycle\n\t| { type: \"agent_start\" }\n\t| { type: \"agent_end\"; messages: AppMessage[] }\n\t// Turn lifecycle - a turn is one assistant response + any tool calls/results\n\t| { type: \"turn_start\" }\n\t| { type: \"turn_end\"; message: AppMessage; toolResults: AppMessage[] }\n\t// Message lifecycle - emitted for user, assistant, and toolResult messages\n\t| { type: \"message_start\"; message: AppMessage }\n\t// Only emitted for assistant messages during streaming\n\t| { type: \"message_update\"; message: AppMessage; assistantMessageEvent: AssistantMessageEvent }\n\t| { type: \"message_end\"; message: AppMessage }\n\t// Tool execution lifecycle\n\t| { type: \"tool_execution_start\"; toolCallId: string; toolName: string; args: any }\n\t| { type: \"tool_execution_end\"; toolCallId: string; toolName: string; result: any; isError: boolean };\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n\tAgentTool,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tMessage,\n\tModel,\n\tUserMessage,\n} from \"@mariozechner/pi-ai\";\n\n/**\n * Attachment type definition.\n * Processing is done by consumers (e.g., document extraction in web-ui).\n */\nexport interface Attachment {\n\tid: string;\n\ttype: \"image\" | \"document\";\n\tfileName: string;\n\tmimeType: string;\n\tsize: number;\n\tcontent: string; // base64 encoded (without data URL prefix)\n\textractedText?: string; // For documents\n\tpreview?: string; // base64 image preview\n}\n\n/**\n * Thinking/reasoning level for models that support it.\n * Note: \"xhigh\" is only supported by OpenAI codex-max models.\n */\nexport type ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\n/**\n * User message with optional attachments.\n */\nexport type UserMessageWithAttachments = UserMessage & { attachments?: Attachment[] };\n\n/**\n * Extensible interface for custom app messages.\n * Apps can extend via declaration merging:\n *\n * @example\n * ```typescript\n * declare module \"@mariozechner/agent\" {\n * interface CustomMessages {\n * artifact: ArtifactMessage;\n * notification: NotificationMessage;\n * }\n * }\n * ```\n */\nexport interface CustomMessages {\n\t// Empty by default - apps extend via declaration merging\n}\n\n/**\n * AppMessage: Union of LLM messages + attachments + custom messages.\n * This abstraction allows apps to add custom message types while maintaining\n * type safety and compatibility with the base LLM messages.\n */\nexport type AppMessage =\n\t| AssistantMessage\n\t| UserMessageWithAttachments\n\t| Message // Includes ToolResultMessage\n\t| CustomMessages[keyof CustomMessages];\n\n/**\n * Agent state containing all configuration and conversation data.\n */\nexport interface AgentState {\n\tsystemPrompt: string;\n\tmodel: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\ttools: AgentTool<any>[];\n\tmessages: AppMessage[]; // Can include attachments + custom message types\n\tisStreaming: boolean;\n\tstreamMessage: Message | null;\n\tpendingToolCalls: Set<string>;\n\terror?: string;\n}\n\n/**\n * Events emitted by the Agent for UI updates.\n * These events provide fine-grained lifecycle information for messages, turns, and tool executions.\n */\nexport type AgentEvent =\n\t// Agent lifecycle\n\t| { type: \"agent_start\" }\n\t| { type: \"agent_end\"; messages: AppMessage[] }\n\t// Turn lifecycle - a turn is one assistant response + any tool calls/results\n\t| { type: \"turn_start\" }\n\t| { type: \"turn_end\"; message: AppMessage; toolResults: AppMessage[] }\n\t// Message lifecycle - emitted for user, assistant, and toolResult messages\n\t| { type: \"message_start\"; message: AppMessage }\n\t// Only emitted for assistant messages during streaming\n\t| { type: \"message_update\"; message: AppMessage; assistantMessageEvent: AssistantMessageEvent }\n\t| { type: \"message_end\"; message: AppMessage }\n\t// Tool execution lifecycle\n\t| { type: \"tool_execution_start\"; toolCallId: string; toolName: string; args: any }\n\t| { type: \"tool_execution_end\"; toolCallId: string; toolName: string; result: any; isError: boolean };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mariozechner/pi-agent-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"prepublishOnly": "npm run clean && npm run build"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@mariozechner/pi-ai": "^0.
|
|
22
|
-
"@mariozechner/pi-tui": "^0.
|
|
21
|
+
"@mariozechner/pi-ai": "^0.14.1",
|
|
22
|
+
"@mariozechner/pi-tui": "^0.14.1"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
25
25
|
"ai",
|