@polka-codes/core 0.9.51 → 0.9.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Core AI services and agent implementations for Polka Codes framework.
8
8
 
9
9
  ## Features
10
10
 
11
- - Multiple AI provider support (Ollama, Anthropic, DeepSeek)
11
+ - Multiple AI provider support (Anthropic, DeepSeek, GoogleVertex, Ollama, OpenAI, and OpenRouter)
12
12
  - Extensible agent architecture
13
13
  - Tool integration system
14
14
  - Type-safe API
@@ -22,82 +22,80 @@ bun add @polka-codes/core
22
22
 
23
23
  ## Usage
24
24
 
25
- ### Basic Setup
25
+ The core of `@polka-codes/core` is the `agentWorkflow`. You can use it to create a workflow that interacts with an AI model.
26
26
 
27
27
  ```typescript
28
- import { AgentBase } from '@polka-codes/core';
29
-
30
- class MyAgent extends AgentBase {
31
- // Implement your agent logic
32
- }
33
-
34
- const agent = new MyAgent();
35
- await agent.runTask('your-task');
36
- ```
37
-
38
- ### Available Services
39
-
40
- - `AnthropicService`: Integration with Anthropic API
41
- - `DeepSeekService`: Integration with DeepSeek API
42
- - `OllamaService`: Integration with Ollama API
43
-
44
- ### Tools
45
-
46
- The core package provides a tool system for extending functionality:
47
-
48
- ```typescript
49
- import { ToolBase } from '@polka-codes/core';
50
-
51
- class MyTool extends ToolBase {
52
- // Implement your tool logic
28
+ import {
29
+ agentWorkflow,
30
+ createContext,
31
+ makeStepFn,
32
+ type ToolResponse,
33
+ ToolResponseType,
34
+ } from '@polka-codes/core';
35
+ import { z } from 'zod';
36
+
37
+ // Define a tool
38
+ const getCurrentWeather = {
39
+ name: 'getCurrentWeather',
40
+ description: 'Get the current weather in a given location',
41
+ parameters: z.object({
42
+ location: z.string().describe("The city and state, e.g. San Francisco, CA"),
43
+ }),
44
+ };
45
+
46
+ async function main() {
47
+ // Create a context for the workflow
48
+ const context = createContext({
49
+ // Implement the tool
50
+ invokeTool: async ({ toolName, input }) => {
51
+ if (toolName === 'getCurrentWeather') {
52
+ const { location } = input as z.infer<typeof getCurrentWeather.parameters>;
53
+ // In a real app, you would call a weather API here
54
+ const weather = `The weather in ${location} is 70°F and sunny.`;
55
+ const response: ToolResponse = { type: ToolResponseType.Reply, message: weather };
56
+ return response;
57
+ }
58
+ const response: ToolResponse = { type: ToolResponseType.Error, message: 'Tool not found' };
59
+ return response;
60
+ },
61
+ // A simple text generation function
62
+ generateText: async ({ messages }) => {
63
+ // In a real app, you would call an AI provider here (e.g. Anthropic, OpenAI)
64
+ console.log('--- Assistant Turn ---');
65
+ console.log(messages);
66
+ // This is a mock response for demonstration purposes
67
+ return [{
68
+ role: 'assistant',
69
+ content: [{
70
+ type: 'tool-call',
71
+ toolName: 'getCurrentWeather',
72
+ toolCallId: '123',
73
+ input: { location: 'San Francisco, CA' }
74
+ }]
75
+ }];
76
+ },
77
+ taskEvent: async (event) => {
78
+ console.log('Task Event:', event.kind);
79
+ }
80
+ }, makeStepFn());
81
+
82
+ // Run the agent workflow
83
+ const result = await agentWorkflow(
84
+ {
85
+ tools: [getCurrentWeather],
86
+ systemPrompt: "You are a helpful assistant.",
87
+ userMessage: [{ role: 'user', content: "What's the weather in San Francisco, CA?" }],
88
+ },
89
+ context
90
+ );
91
+
92
+ console.log('--- Workflow Result ---');
93
+ console.log(result);
53
94
  }
54
- ```
55
-
56
- ### Nested workflows
57
95
 
58
- You can reuse existing workflows inside other workflows with the `workflow` step. This is helpful when you want to repeat a
59
- common CLI pattern such as `custom → agent → custom`.
60
-
61
- ```typescript
62
- import {
63
- builder,
64
- combineHandlers,
65
- customStepSpecHandler,
66
- makeAgentStepSpecHandler,
67
- sequentialStepSpecHandler,
68
- workflowStepSpecHandler,
69
- } from '@polka-codes/core/workflow';
70
-
71
- const reviewWorkflow = builder<{ code: string }>()
72
- .custom('prepare', async ({ code }) => ({ prompt: `Review this snippet:\n${code}` }))
73
- .agent('agent', {
74
- messages: [{ type: 'function', fn: (input) => input.prompt }],
75
- systemPrompt: 'You are a careful reviewer.',
76
- parseOutput: (raw) => ({ success: true, data: { review: raw } }),
77
- })
78
- .custom('summarize', async (input) => ({ summary: input.review }))
79
- .build();
80
-
81
- const mainWorkflow = builder<{ code: string; notify: boolean }>()
82
- .workflow('review', {
83
- workflow: reviewWorkflow,
84
- mapInput: (input) => ({ code: input.code }),
85
- mapOutput: ({ workflowOutput, input }) => ({ summary: workflowOutput.summary, notify: input.notify }),
86
- })
87
- .custom('finalize', async ({ summary, notify }) => ({ summary, notified: notify }))
88
- .build();
89
-
90
- const handlers = combineHandlers(
91
- sequentialStepSpecHandler,
92
- customStepSpecHandler,
93
- workflowStepSpecHandler,
94
- makeAgentStepSpecHandler(async () => /* return a LanguageModelV2 */ throw new Error('model not configured')),
95
- );
96
+ main();
96
97
  ```
97
98
 
98
- The optional `mapInput` and `mapOutput` helpers let you shape data for the child workflow and massage the result before the
99
- next parent step runs.
100
-
101
99
  ## Development
102
100
 
103
101
  ### Building
@@ -5,7 +5,15 @@ import type { JSONValue } from '@ai-sdk/provider';
5
5
  import type { LanguageModelV2 } from '@ai-sdk/provider';
6
6
  import type { LanguageModelV2ToolResultOutput } from '@ai-sdk/provider';
7
7
  import type { LanguageModelV2Usage } from '@ai-sdk/provider';
8
+ import type { ModelMessage } from '@ai-sdk/provider-utils';
9
+ import type { ProviderOptions } from '@ai-sdk/provider-utils';
10
+ import type { ReasoningPart } from '@ai-sdk/provider-utils';
11
+ import type { SystemModelMessage } from '@ai-sdk/provider-utils';
8
12
  import type { TextPart } from 'ai';
13
+ import type { TextPart as TextPart_2 } from '@ai-sdk/provider-utils';
14
+ import type { ToolModelMessage } from '@ai-sdk/provider-utils';
15
+ import type { ToolResultPart } from '@ai-sdk/provider-utils';
16
+ import { ToolSet } from 'ai';
9
17
  import { z } from 'zod';
10
18
  import { ZodEnum } from 'zod';
11
19
  import { ZodNullable } from 'zod';
@@ -13,6 +21,51 @@ import { ZodObject } from 'zod';
13
21
  import { ZodOptional } from 'zod';
14
22
  import { ZodString } from 'zod';
15
23
 
24
+ declare type AgentToolRegistry = {
25
+ generateText: {
26
+ input: {
27
+ messages: JsonModelMessage[];
28
+ tools: ToolSet;
29
+ model?: string;
30
+ };
31
+ output: JsonResponseMessage[];
32
+ };
33
+ taskEvent: {
34
+ input: TaskEvent;
35
+ output: void;
36
+ };
37
+ invokeTool: {
38
+ input: {
39
+ toolName: string;
40
+ input: any;
41
+ };
42
+ output: ToolResponse;
43
+ };
44
+ };
45
+ export { AgentToolRegistry }
46
+ export { AgentToolRegistry as AgentToolRegistry_alias_1 }
47
+ export { AgentToolRegistry as AgentToolRegistry_alias_2 }
48
+
49
+ declare const agentWorkflow: WorkflowFn<AgentWorkflowInput, ExitReason, AgentToolRegistry>;
50
+ export { agentWorkflow }
51
+ export { agentWorkflow as agentWorkflow_alias_1 }
52
+ export { agentWorkflow as agentWorkflow_alias_2 }
53
+
54
+ declare type AgentWorkflowInput = {
55
+ tools: Readonly<FullToolInfo[]>;
56
+ maxToolRoundTrips?: number;
57
+ userMessage: JsonUserModelMessage[];
58
+ outputSchema?: z.ZodSchema;
59
+ model?: string;
60
+ } & ({
61
+ messages: JsonModelMessage[];
62
+ } | {
63
+ systemPrompt: string;
64
+ });
65
+ export { AgentWorkflowInput }
66
+ export { AgentWorkflowInput as AgentWorkflowInput_alias_1 }
67
+ export { AgentWorkflowInput as AgentWorkflowInput_alias_2 }
68
+
16
69
  declare type CommandProvider = {
17
70
  executeCommand?: (command: string, needApprove: boolean) => Promise<{
18
71
  stdout: string;
@@ -83,6 +136,11 @@ declare const configSchema: z.ZodObject<{
83
136
  export { configSchema }
84
137
  export { configSchema as configSchema_alias_1 }
85
138
 
139
+ declare function createContext<TTools extends ToolRegistry>(tools: WorkflowTools<TTools>, stepFn?: <T>(name: string, fn: () => Promise<T>) => Promise<T>, logger?: Logger): WorkflowContext<TTools>;
140
+ export { createContext }
141
+ export { createContext as createContext_alias_1 }
142
+ export { createContext as createContext_alias_2 }
143
+
86
144
  declare const _default: {
87
145
  handler: ToolHandler<{
88
146
  readonly name: "askFollowupQuestion";
@@ -463,6 +521,26 @@ export { _default_9 as readFile_alias_1 }
463
521
  */
464
522
  export declare function dirname(path: string): string;
465
523
 
524
+ declare type ExitReason = {
525
+ type: 'UsageExceeded';
526
+ messages: JsonModelMessage[];
527
+ } | {
528
+ type: 'Exit';
529
+ message: string;
530
+ object?: any;
531
+ messages: JsonModelMessage[];
532
+ } | {
533
+ type: 'Error';
534
+ error: {
535
+ message: string;
536
+ stack?: string;
537
+ };
538
+ messages: JsonModelMessage[];
539
+ };
540
+ export { ExitReason }
541
+ export { ExitReason as ExitReason_alias_1 }
542
+ export { ExitReason as ExitReason_alias_2 }
543
+
466
544
  declare type FilesystemProvider = {
467
545
  readFile?: (path: string, includeIgnored: boolean) => Promise<string | undefined>;
468
546
  writeFile?: (path: string, content: string) => Promise<void>;
@@ -479,6 +557,11 @@ export { FilesystemProvider }
479
557
  export { FilesystemProvider as FilesystemProvider_alias_1 }
480
558
  export { FilesystemProvider as FilesystemProvider_alias_2 }
481
559
 
560
+ declare const fromJsonModelMessage: (msg: JsonModelMessage) => ModelMessage;
561
+ export { fromJsonModelMessage }
562
+ export { fromJsonModelMessage as fromJsonModelMessage_alias_1 }
563
+ export { fromJsonModelMessage as fromJsonModelMessage_alias_2 }
564
+
482
565
  declare type FullToolInfo = ToolInfo & {
483
566
  handler: ToolHandler<ToolInfo, any>;
484
567
  };
@@ -541,11 +624,171 @@ export { InteractionProvider as InteractionProvider_alias_2 }
541
624
  */
542
625
  export declare function join(...parts: string[]): string;
543
626
 
627
+ /**
628
+ Content of an assistant message.
629
+ It can be a string or an array of text, image, reasoning, redacted reasoning, and tool call parts.
630
+ */
631
+ declare type JsonAssistantContent = string | Array<TextPart_2 | JsonFilePart | ReasoningPart | JsonToolCallPart | ToolResultPart>;
632
+
633
+ /**
634
+ An assistant message. It can contain text, tool calls, or a combination of text and tool calls.
635
+ */
636
+ declare type JsonAssistantModelMessage = {
637
+ role: 'assistant';
638
+ content: JsonAssistantContent;
639
+ /**
640
+ Additional provider-specific metadata. They are passed through
641
+ to the provider from the AI SDK and enable provider-specific
642
+ functionality that can be fully encapsulated in the provider.
643
+ */
644
+ providerOptions?: ProviderOptions;
645
+ };
646
+
647
+ declare type JsonDataContent = {
648
+ type: 'base64' | 'url';
649
+ value: string;
650
+ };
651
+
652
+ /**
653
+ File content part of a prompt. It contains a file.
654
+ */
655
+ declare interface JsonFilePart {
656
+ type: 'file';
657
+ /**
658
+ File data. Can either be:
659
+
660
+ - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer
661
+ - URL: a URL that points to the image
662
+ */
663
+ data: JsonDataContent;
664
+ /**
665
+ Optional filename of the file.
666
+ */
667
+ filename?: string;
668
+ /**
669
+ IANA media type of the file.
670
+
671
+ @see https://www.iana.org/assignments/media-types/media-types.xhtml
672
+ */
673
+ mediaType: string;
674
+ /**
675
+ Additional provider-specific metadata. They are passed through
676
+ to the provider from the AI SDK and enable provider-specific
677
+ functionality that can be fully encapsulated in the provider.
678
+ */
679
+ providerOptions?: ProviderOptions;
680
+ }
681
+ export { JsonFilePart }
682
+ export { JsonFilePart as JsonFilePart_alias_1 }
683
+ export { JsonFilePart as JsonFilePart_alias_2 }
684
+
685
+ declare interface JsonImagePart {
686
+ type: 'image';
687
+ /**
688
+ Image data. Can either be:
689
+
690
+ - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer
691
+ - URL: a URL that points to the image
692
+ */
693
+ image: JsonDataContent;
694
+ /**
695
+ Optional IANA media type of the image.
696
+
697
+ @see https://www.iana.org/assignments/media-types/media-types.xhtml
698
+ */
699
+ mediaType?: string;
700
+ /**
701
+ Additional provider-specific metadata. They are passed through
702
+ to the provider from the AI SDK and enable provider-specific
703
+ functionality that can be fully encapsulated in the provider.
704
+ */
705
+ providerOptions?: ProviderOptions;
706
+ }
707
+ export { JsonImagePart }
708
+ export { JsonImagePart as JsonImagePart_alias_1 }
709
+ export { JsonImagePart as JsonImagePart_alias_2 }
710
+
711
+ declare type JsonModelMessage = SystemModelMessage | JsonUserModelMessage | JsonAssistantModelMessage | ToolModelMessage;
712
+ export { JsonModelMessage }
713
+ export { JsonModelMessage as JsonModelMessage_alias_1 }
714
+ export { JsonModelMessage as JsonModelMessage_alias_2 }
715
+
716
+ declare type JsonResponseMessage = JsonAssistantModelMessage | ToolModelMessage;
717
+ export { JsonResponseMessage }
718
+ export { JsonResponseMessage as JsonResponseMessage_alias_1 }
719
+ export { JsonResponseMessage as JsonResponseMessage_alias_2 }
720
+
721
+ declare interface JsonToolCallPart {
722
+ type: 'tool-call';
723
+ /**
724
+ ID of the tool call. This ID is used to match the tool call with the tool result.
725
+ */
726
+ toolCallId: string;
727
+ /**
728
+ Name of the tool that is being called.
729
+ */
730
+ toolName: string;
731
+ /**
732
+ Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema.
733
+ */
734
+ input: JSONValue;
735
+ /**
736
+ Additional provider-specific metadata. They are passed through
737
+ to the provider from the AI SDK and enable provider-specific
738
+ functionality that can be fully encapsulated in the provider.
739
+ */
740
+ providerOptions?: ProviderOptions;
741
+ /**
742
+ Whether the tool call was executed by the provider.
743
+ */
744
+ providerExecuted?: boolean;
745
+ }
746
+
747
+ /**
748
+ Content of a user message. It can be a string or an array of text and image parts.
749
+ */
750
+ declare type JsonUserContent = string | Array<TextPart_2 | JsonImagePart | JsonFilePart>;
751
+ export { JsonUserContent }
752
+ export { JsonUserContent as JsonUserContent_alias_1 }
753
+ export { JsonUserContent as JsonUserContent_alias_2 }
754
+
755
+ /**
756
+ A user message. It can contain text or a combination of text and images.
757
+ */
758
+ declare type JsonUserModelMessage = {
759
+ role: 'user';
760
+ content: JsonUserContent;
761
+ /**
762
+ Additional provider-specific metadata. They are passed through
763
+ to the provider from the AI SDK and enable provider-specific
764
+ functionality that can be fully encapsulated in the provider.
765
+ */
766
+ providerOptions?: ProviderOptions;
767
+ };
768
+ export { JsonUserModelMessage }
769
+ export { JsonUserModelMessage as JsonUserModelMessage_alias_1 }
770
+ export { JsonUserModelMessage as JsonUserModelMessage_alias_2 }
771
+
544
772
  declare type ListTodoItemsOutput = TodoItem[];
545
773
  export { ListTodoItemsOutput }
546
774
  export { ListTodoItemsOutput as ListTodoItemsOutput_alias_1 }
547
775
  export { ListTodoItemsOutput as ListTodoItemsOutput_alias_2 }
548
776
 
777
+ declare interface Logger {
778
+ debug: (...args: any[]) => void;
779
+ info: (...args: any[]) => void;
780
+ warn: (...args: any[]) => void;
781
+ error: (...args: any[]) => void;
782
+ }
783
+ export { Logger }
784
+ export { Logger as Logger_alias_1 }
785
+ export { Logger as Logger_alias_2 }
786
+
787
+ declare const makeStepFn: () => (<T>(name: string, fn: () => Promise<T>) => Promise<T>);
788
+ export { makeStepFn }
789
+ export { makeStepFn as makeStepFn_alias_1 }
790
+ export { makeStepFn as makeStepFn_alias_2 }
791
+
549
792
  declare interface MemoryProvider {
550
793
  listMemoryTopics: () => Promise<string[]>;
551
794
  readMemory: (topic?: string) => Promise<string | undefined>;
@@ -637,6 +880,143 @@ export { responsePrompts }
637
880
  export { responsePrompts as responsePrompts_alias_1 }
638
881
  export { responsePrompts as responsePrompts_alias_2 }
639
882
 
883
+ /**
884
+ * Union type of all possible task events
885
+ */
886
+ declare type TaskEvent = TaskEventStartTask | TaskEventStartRequest | TaskEventEndRequest | TaskEventText | TaskEventToolUse | TaskEventToolResult | TaskEventToolError | TaskEventUsageExceeded | TaskEventEndTask;
887
+ export { TaskEvent }
888
+ export { TaskEvent as TaskEvent_alias_1 }
889
+ export { TaskEvent as TaskEvent_alias_2 }
890
+
891
+ /**
892
+ * Base interface for all task events
893
+ */
894
+ declare interface TaskEventBase {
895
+ kind: TaskEventKind;
896
+ }
897
+ export { TaskEventBase }
898
+ export { TaskEventBase as TaskEventBase_alias_1 }
899
+ export { TaskEventBase as TaskEventBase_alias_2 }
900
+
901
+ declare type TaskEventCallback = (event: TaskEvent) => void | Promise<void>;
902
+ export { TaskEventCallback }
903
+ export { TaskEventCallback as TaskEventCallback_alias_1 }
904
+ export { TaskEventCallback as TaskEventCallback_alias_2 }
905
+
906
+ /**
907
+ * Event for request end
908
+ */
909
+ declare interface TaskEventEndRequest extends TaskEventBase {
910
+ kind: TaskEventKind.EndRequest;
911
+ message: string;
912
+ }
913
+ export { TaskEventEndRequest }
914
+ export { TaskEventEndRequest as TaskEventEndRequest_alias_1 }
915
+ export { TaskEventEndRequest as TaskEventEndRequest_alias_2 }
916
+
917
+ /**
918
+ * Event for task end
919
+ */
920
+ declare interface TaskEventEndTask extends TaskEventBase {
921
+ kind: TaskEventKind.EndTask;
922
+ exitReason: ExitReason;
923
+ }
924
+ export { TaskEventEndTask }
925
+ export { TaskEventEndTask as TaskEventEndTask_alias_1 }
926
+ export { TaskEventEndTask as TaskEventEndTask_alias_2 }
927
+
928
+ /**
929
+ * Enum representing different kinds of task events
930
+ */
931
+ declare enum TaskEventKind {
932
+ StartTask = "StartTask",
933
+ StartRequest = "StartRequest",
934
+ EndRequest = "EndRequest",
935
+ Text = "Text",
936
+ Reasoning = "Reasoning",
937
+ ToolUse = "ToolUse",
938
+ ToolReply = "ToolReply",
939
+ ToolError = "ToolError",
940
+ UsageExceeded = "UsageExceeded",
941
+ EndTask = "EndTask"
942
+ }
943
+ export { TaskEventKind }
944
+ export { TaskEventKind as TaskEventKind_alias_1 }
945
+ export { TaskEventKind as TaskEventKind_alias_2 }
946
+
947
+ /**
948
+ * Event for request start
949
+ */
950
+ declare interface TaskEventStartRequest extends TaskEventBase {
951
+ kind: TaskEventKind.StartRequest;
952
+ userMessage: JsonModelMessage[];
953
+ }
954
+ export { TaskEventStartRequest }
955
+ export { TaskEventStartRequest as TaskEventStartRequest_alias_1 }
956
+ export { TaskEventStartRequest as TaskEventStartRequest_alias_2 }
957
+
958
+ /**
959
+ * Event for task start
960
+ */
961
+ declare interface TaskEventStartTask extends TaskEventBase {
962
+ kind: TaskEventKind.StartTask;
963
+ systemPrompt: string;
964
+ }
965
+ export { TaskEventStartTask }
966
+ export { TaskEventStartTask as TaskEventStartTask_alias_1 }
967
+ export { TaskEventStartTask as TaskEventStartTask_alias_2 }
968
+
969
+ /**
970
+ * Event for text/reasoning updates
971
+ */
972
+ declare interface TaskEventText extends TaskEventBase {
973
+ kind: TaskEventKind.Text | TaskEventKind.Reasoning;
974
+ newText: string;
975
+ }
976
+ export { TaskEventText }
977
+ export { TaskEventText as TaskEventText_alias_1 }
978
+ export { TaskEventText as TaskEventText_alias_2 }
979
+
980
+ declare interface TaskEventToolError extends TaskEventBase {
981
+ kind: TaskEventKind.ToolError;
982
+ tool: string;
983
+ error: ToolResponseError | ToolResponseResult;
984
+ }
985
+ export { TaskEventToolError }
986
+ export { TaskEventToolError as TaskEventToolError_alias_1 }
987
+ export { TaskEventToolError as TaskEventToolError_alias_2 }
988
+
989
+ declare interface TaskEventToolResult extends TaskEventBase {
990
+ kind: TaskEventKind.ToolReply;
991
+ tool: string;
992
+ content: ToolResponseResult;
993
+ }
994
+ export { TaskEventToolResult }
995
+ export { TaskEventToolResult as TaskEventToolResult_alias_1 }
996
+ export { TaskEventToolResult as TaskEventToolResult_alias_2 }
997
+
998
+ /**
999
+ * Event for tool-related updates
1000
+ */
1001
+ declare interface TaskEventToolUse extends TaskEventBase {
1002
+ kind: TaskEventKind.ToolUse;
1003
+ tool: string;
1004
+ params: Record<string, any>;
1005
+ }
1006
+ export { TaskEventToolUse }
1007
+ export { TaskEventToolUse as TaskEventToolUse_alias_1 }
1008
+ export { TaskEventToolUse as TaskEventToolUse_alias_2 }
1009
+
1010
+ /**
1011
+ * Event for task usage exceeded
1012
+ */
1013
+ declare interface TaskEventUsageExceeded extends TaskEventBase {
1014
+ kind: TaskEventKind.UsageExceeded;
1015
+ }
1016
+ export { TaskEventUsageExceeded }
1017
+ export { TaskEventUsageExceeded as TaskEventUsageExceeded_alias_1 }
1018
+ export { TaskEventUsageExceeded as TaskEventUsageExceeded_alias_2 }
1019
+
640
1020
  declare type TodoItem = z.infer<typeof TodoItemSchema>;
641
1021
  export { TodoItem }
642
1022
  export { TodoItem as TodoItem_alias_1 }
@@ -674,6 +1054,11 @@ export { TodoStatus }
674
1054
  export { TodoStatus as TodoStatus_alias_1 }
675
1055
  export { TodoStatus as TodoStatus_alias_2 }
676
1056
 
1057
+ declare const toJsonModelMessage: (msg: ModelMessage) => JsonModelMessage;
1058
+ export { toJsonModelMessage }
1059
+ export { toJsonModelMessage as toJsonModelMessage_alias_1 }
1060
+ export { toJsonModelMessage as toJsonModelMessage_alias_2 }
1061
+
677
1062
  declare type ToolHandler<_T, P> = (provider: P, args: Partial<Record<string, ToolParameterValue>>) => Promise<ToolResponse>;
678
1063
  export { ToolHandler }
679
1064
  export { ToolHandler as ToolHandler_alias_1 }
@@ -878,6 +1263,11 @@ export { ToolProvider }
878
1263
  export { ToolProvider as ToolProvider_alias_1 }
879
1264
  export { ToolProvider as ToolProvider_alias_2 }
880
1265
 
1266
+ declare type ToolRegistry = Record<string, ToolSignature<any, any>>;
1267
+ export { ToolRegistry }
1268
+ export { ToolRegistry as ToolRegistry_alias_1 }
1269
+ export { ToolRegistry as ToolRegistry_alias_2 }
1270
+
881
1271
  declare type ToolResponse = ToolResponseReply | ToolResponseExit | ToolResponseError;
882
1272
  export { ToolResponse }
883
1273
  export { ToolResponse as ToolResponse_alias_1 }
@@ -943,6 +1333,14 @@ declare enum ToolResponseType {
943
1333
  export { ToolResponseType }
944
1334
  export { ToolResponseType as ToolResponseType_alias_1 }
945
1335
 
1336
+ declare type ToolSignature<I, O> = {
1337
+ input: I;
1338
+ output: O;
1339
+ };
1340
+ export { ToolSignature }
1341
+ export { ToolSignature as ToolSignature_alias_1 }
1342
+ export { ToolSignature as ToolSignature_alias_2 }
1343
+
946
1344
  declare type Totals = {
947
1345
  input: number;
948
1346
  output: number;
@@ -1048,4 +1446,25 @@ export { WebProvider }
1048
1446
  export { WebProvider as WebProvider_alias_1 }
1049
1447
  export { WebProvider as WebProvider_alias_2 }
1050
1448
 
1449
+ declare type WorkflowContext<TTools extends ToolRegistry> = {
1450
+ step: <T>(name: string, fn: () => Promise<T>) => Promise<T>;
1451
+ logger: Logger;
1452
+ tools: WorkflowTools<TTools>;
1453
+ };
1454
+ export { WorkflowContext }
1455
+ export { WorkflowContext as WorkflowContext_alias_1 }
1456
+ export { WorkflowContext as WorkflowContext_alias_2 }
1457
+
1458
+ declare type WorkflowFn<TInput, TOutput, TTools extends ToolRegistry> = (input: TInput, context: WorkflowContext<TTools>) => Promise<TOutput>;
1459
+ export { WorkflowFn }
1460
+ export { WorkflowFn as WorkflowFn_alias_1 }
1461
+ export { WorkflowFn as WorkflowFn_alias_2 }
1462
+
1463
+ declare type WorkflowTools<TTools extends ToolRegistry> = {
1464
+ [K in keyof TTools]: (input: TTools[K]['input']) => Promise<TTools[K]['output']>;
1465
+ };
1466
+ export { WorkflowTools }
1467
+ export { WorkflowTools as WorkflowTools_alias_1 }
1468
+ export { WorkflowTools as WorkflowTools_alias_2 }
1469
+
1051
1470
  export { }
package/dist/index.d.ts CHANGED
@@ -53,3 +53,36 @@ export { UpdateTodoItemOutputSchema } from './_tsup-dts-rollup.js';
53
53
  export { UpdateTodoItemOutput } from './_tsup-dts-rollup.js';
54
54
  export { ModelInfo_alias_1 as ModelInfo } from './_tsup-dts-rollup.js';
55
55
  export { UsageMeter_alias_1 as UsageMeter } from './_tsup-dts-rollup.js';
56
+ export { AgentWorkflowInput } from './_tsup-dts-rollup.js';
57
+ export { AgentToolRegistry } from './_tsup-dts-rollup.js';
58
+ export { agentWorkflow } from './_tsup-dts-rollup.js';
59
+ export { JsonImagePart } from './_tsup-dts-rollup.js';
60
+ export { JsonFilePart } from './_tsup-dts-rollup.js';
61
+ export { JsonUserModelMessage } from './_tsup-dts-rollup.js';
62
+ export { JsonUserContent } from './_tsup-dts-rollup.js';
63
+ export { JsonModelMessage } from './_tsup-dts-rollup.js';
64
+ export { JsonResponseMessage } from './_tsup-dts-rollup.js';
65
+ export { toJsonModelMessage } from './_tsup-dts-rollup.js';
66
+ export { fromJsonModelMessage } from './_tsup-dts-rollup.js';
67
+ export { TaskEventKind } from './_tsup-dts-rollup.js';
68
+ export { TaskEventBase } from './_tsup-dts-rollup.js';
69
+ export { TaskEventStartTask } from './_tsup-dts-rollup.js';
70
+ export { TaskEventStartRequest } from './_tsup-dts-rollup.js';
71
+ export { TaskEventEndRequest } from './_tsup-dts-rollup.js';
72
+ export { TaskEventText } from './_tsup-dts-rollup.js';
73
+ export { TaskEventToolUse } from './_tsup-dts-rollup.js';
74
+ export { TaskEventToolResult } from './_tsup-dts-rollup.js';
75
+ export { TaskEventToolError } from './_tsup-dts-rollup.js';
76
+ export { TaskEventUsageExceeded } from './_tsup-dts-rollup.js';
77
+ export { TaskEventEndTask } from './_tsup-dts-rollup.js';
78
+ export { TaskEvent } from './_tsup-dts-rollup.js';
79
+ export { TaskEventCallback } from './_tsup-dts-rollup.js';
80
+ export { ExitReason } from './_tsup-dts-rollup.js';
81
+ export { createContext } from './_tsup-dts-rollup.js';
82
+ export { Logger } from './_tsup-dts-rollup.js';
83
+ export { ToolSignature } from './_tsup-dts-rollup.js';
84
+ export { ToolRegistry } from './_tsup-dts-rollup.js';
85
+ export { WorkflowTools } from './_tsup-dts-rollup.js';
86
+ export { WorkflowContext } from './_tsup-dts-rollup.js';
87
+ export { WorkflowFn } from './_tsup-dts-rollup.js';
88
+ export { makeStepFn } from './_tsup-dts-rollup.js';
package/dist/index.js CHANGED
@@ -1644,23 +1644,372 @@ var UsageMeter = class {
1644
1644
  };
1645
1645
  }
1646
1646
  };
1647
+
1648
+ // src/workflow/agent.workflow.ts
1649
+ import { jsonSchema } from "ai";
1650
+ import { toJSONSchema, z as z19 } from "zod";
1651
+
1652
+ // src/workflow/types.ts
1653
+ var TaskEventKind = /* @__PURE__ */ ((TaskEventKind2) => {
1654
+ TaskEventKind2["StartTask"] = "StartTask";
1655
+ TaskEventKind2["StartRequest"] = "StartRequest";
1656
+ TaskEventKind2["EndRequest"] = "EndRequest";
1657
+ TaskEventKind2["Text"] = "Text";
1658
+ TaskEventKind2["Reasoning"] = "Reasoning";
1659
+ TaskEventKind2["ToolUse"] = "ToolUse";
1660
+ TaskEventKind2["ToolReply"] = "ToolReply";
1661
+ TaskEventKind2["ToolError"] = "ToolError";
1662
+ TaskEventKind2["UsageExceeded"] = "UsageExceeded";
1663
+ TaskEventKind2["EndTask"] = "EndTask";
1664
+ return TaskEventKind2;
1665
+ })(TaskEventKind || {});
1666
+
1667
+ // src/workflow/agent.workflow.ts
1668
+ var agentWorkflow = async (input, { step, tools }) => {
1669
+ const event = (name, event2) => step(name, () => tools.taskEvent(event2));
1670
+ const { tools: toolInfo18, maxToolRoundTrips = 200 } = input;
1671
+ const messages = "systemPrompt" in input ? [{ role: "system", content: input.systemPrompt }] : input.messages;
1672
+ await event("start-task", { kind: "StartTask" /* StartTask */, systemPrompt: "systemPrompt" in input ? input.systemPrompt : "" });
1673
+ const toolSet = {};
1674
+ for (const tool of toolInfo18) {
1675
+ toolSet[tool.name] = {
1676
+ description: tool.description,
1677
+ inputSchema: jsonSchema(toJSONSchema(tool.parameters))
1678
+ };
1679
+ }
1680
+ let nextMessage = input.userMessage;
1681
+ for (let i = 0; i < maxToolRoundTrips; i++) {
1682
+ messages.push(...nextMessage);
1683
+ await event(`start-round-${i}`, { kind: "StartRequest" /* StartRequest */, userMessage: nextMessage });
1684
+ const assistantMessage = await step(`agent-round-${i}`, async () => {
1685
+ return await tools.generateText({
1686
+ messages,
1687
+ tools: toolSet,
1688
+ model: input.model
1689
+ });
1690
+ });
1691
+ messages.push(...assistantMessage);
1692
+ const toolCalls = [];
1693
+ for (const msg of assistantMessage) {
1694
+ if (typeof msg.content === "string") {
1695
+ continue;
1696
+ }
1697
+ if (msg.content) {
1698
+ for (const part of msg.content) {
1699
+ if (part.type === "tool-call") {
1700
+ toolCalls.push(part);
1701
+ }
1702
+ }
1703
+ }
1704
+ }
1705
+ const textContent = assistantMessage.flatMap((m) => {
1706
+ if (typeof m.content === "string") {
1707
+ return [m.content];
1708
+ }
1709
+ if (m.role === "assistant" && Array.isArray(m.content)) {
1710
+ return m.content.map((part) => {
1711
+ if (part.type === "text") {
1712
+ return part.text;
1713
+ }
1714
+ return "";
1715
+ });
1716
+ }
1717
+ return [];
1718
+ }).join("\n");
1719
+ await event(`end-round-${i}`, { kind: "EndRequest" /* EndRequest */, message: textContent });
1720
+ if (toolCalls.length === 0) {
1721
+ if (!input.outputSchema) {
1722
+ const exitReason2 = { type: "Exit", message: textContent, messages };
1723
+ await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: exitReason2 });
1724
+ return exitReason2;
1725
+ }
1726
+ const parsed = parseJsonFromMarkdown(textContent);
1727
+ if (!parsed.success) {
1728
+ const errorMessage = `Failed to parse JSON from markdown. Error: ${parsed.error}. Please correct the output. It MUST be in valid JSON format.`;
1729
+ nextMessage = [{ role: "user", content: errorMessage }];
1730
+ continue;
1731
+ }
1732
+ const validated = input.outputSchema.safeParse(parsed.data);
1733
+ if (!validated.success) {
1734
+ const errorMessage = `Output validation failed. Error: ${z19.prettifyError(validated.error)}. Please correct the output.`;
1735
+ nextMessage = [{ role: "user", content: errorMessage }];
1736
+ continue;
1737
+ }
1738
+ const exitReason = { type: "Exit", message: textContent, object: validated.data, messages };
1739
+ await event("end-task", { kind: "EndTask" /* EndTask */, exitReason });
1740
+ return exitReason;
1741
+ }
1742
+ const toolResults = [];
1743
+ for (const toolCall of toolCalls) {
1744
+ await event(`event-tool-use-${toolCall.toolName}-${toolCall.toolCallId}`, {
1745
+ kind: "ToolUse" /* ToolUse */,
1746
+ tool: toolCall.toolName,
1747
+ params: toolCall.input
1748
+ });
1749
+ const toolResponse = await step(`invoke-tool-${toolCall.toolName}-${toolCall.toolCallId}`, async () => {
1750
+ return await tools.invokeTool({
1751
+ toolName: toolCall.toolName,
1752
+ input: toolCall.input
1753
+ });
1754
+ });
1755
+ switch (toolResponse.type) {
1756
+ case "Reply" /* Reply */:
1757
+ await event(`event-tool-reply-${toolCall.toolName}-${toolCall.toolCallId}`, {
1758
+ kind: "ToolReply" /* ToolReply */,
1759
+ tool: toolCall.toolName,
1760
+ content: toolResponse.message
1761
+ });
1762
+ toolResults.push({
1763
+ toolCallId: toolCall.toolCallId,
1764
+ toolName: toolCall.toolName,
1765
+ output: toolResponse.message
1766
+ });
1767
+ break;
1768
+ case "Error" /* Error */:
1769
+ await event(`event-tool-error-${toolCall.toolName}-${toolCall.toolCallId}`, {
1770
+ kind: "ToolError" /* ToolError */,
1771
+ tool: toolCall.toolName,
1772
+ error: toolResponse.message ?? "Unknown error"
1773
+ });
1774
+ toolResults.push({
1775
+ toolCallId: toolCall.toolCallId,
1776
+ toolName: toolCall.toolName,
1777
+ output: toolResponse.message
1778
+ });
1779
+ break;
1780
+ case "Exit": {
1781
+ if (toolCalls.length > 1) {
1782
+ toolResults.push({
1783
+ toolCallId: toolCall.toolCallId,
1784
+ toolName: toolCall.toolName,
1785
+ output: {
1786
+ type: "error-text",
1787
+ value: `Error: The tool '${toolCall.toolName}' must be called alone, but it was called with other tools.`
1788
+ }
1789
+ });
1790
+ break;
1791
+ }
1792
+ if (toolResults.length > 0) {
1793
+ break;
1794
+ }
1795
+ const exitReason = { ...toolResponse, messages };
1796
+ await event("end-task", { kind: "EndTask" /* EndTask */, exitReason });
1797
+ return exitReason;
1798
+ }
1799
+ }
1800
+ }
1801
+ nextMessage = [
1802
+ {
1803
+ role: "tool",
1804
+ content: toolResults.map((r) => ({
1805
+ type: "tool-result",
1806
+ ...r
1807
+ }))
1808
+ }
1809
+ ];
1810
+ }
1811
+ await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: { type: "UsageExceeded", messages } });
1812
+ throw new Error("Maximum number of tool round trips reached.");
1813
+ };
1814
+
1815
+ // src/workflow/json-ai-types.ts
1816
+ var toJsonDataContent = (data) => {
1817
+ if (data instanceof URL) {
1818
+ return {
1819
+ type: "url",
1820
+ value: data.toString()
1821
+ };
1822
+ }
1823
+ if (typeof data === "string") {
1824
+ return {
1825
+ type: "base64",
1826
+ value: data
1827
+ };
1828
+ }
1829
+ let buffer;
1830
+ if (data instanceof Uint8Array) {
1831
+ buffer = Buffer.from(data);
1832
+ } else if (data instanceof Buffer) {
1833
+ buffer = data;
1834
+ } else {
1835
+ buffer = Buffer.from(data);
1836
+ }
1837
+ return {
1838
+ type: "base64",
1839
+ value: buffer.toString("base64")
1840
+ };
1841
+ };
1842
+ var toJsonUserContent = (content) => {
1843
+ if (typeof content === "string") {
1844
+ return content;
1845
+ }
1846
+ return content.map((part) => {
1847
+ switch (part.type) {
1848
+ case "image":
1849
+ return {
1850
+ ...part,
1851
+ image: toJsonDataContent(part.image)
1852
+ };
1853
+ case "file":
1854
+ return {
1855
+ ...part,
1856
+ data: toJsonDataContent(part.data)
1857
+ };
1858
+ }
1859
+ return part;
1860
+ });
1861
+ };
1862
+ var toJsonAssistantContent = (content) => {
1863
+ if (typeof content === "string") {
1864
+ return content;
1865
+ }
1866
+ return content.map((part) => {
1867
+ switch (part.type) {
1868
+ case "file":
1869
+ return {
1870
+ ...part,
1871
+ data: toJsonDataContent(part.data)
1872
+ };
1873
+ case "tool-call":
1874
+ return {
1875
+ ...part,
1876
+ input: part.input
1877
+ };
1878
+ }
1879
+ return part;
1880
+ });
1881
+ };
1882
+ var toJsonModelMessage = (msg) => {
1883
+ switch (msg.role) {
1884
+ case "user":
1885
+ return {
1886
+ ...msg,
1887
+ content: toJsonUserContent(msg.content)
1888
+ };
1889
+ case "assistant":
1890
+ return {
1891
+ ...msg,
1892
+ content: toJsonAssistantContent(msg.content)
1893
+ };
1894
+ }
1895
+ return msg;
1896
+ };
1897
+ var fromJsonDataContent = (data) => {
1898
+ if (data.type === "url") {
1899
+ return new URL(data.value);
1900
+ }
1901
+ return Buffer.from(data.value, "base64");
1902
+ };
1903
+ var fromJsonUserContent = (content) => {
1904
+ if (typeof content === "string") {
1905
+ return content;
1906
+ }
1907
+ return content.map((part) => {
1908
+ switch (part.type) {
1909
+ case "image":
1910
+ return {
1911
+ ...part,
1912
+ image: fromJsonDataContent(part.image)
1913
+ };
1914
+ case "file":
1915
+ return {
1916
+ ...part,
1917
+ data: fromJsonDataContent(part.data)
1918
+ };
1919
+ }
1920
+ return part;
1921
+ });
1922
+ };
1923
+ var fromJsonAssistantContent = (content) => {
1924
+ if (typeof content === "string") {
1925
+ return content;
1926
+ }
1927
+ return content.map((part) => {
1928
+ switch (part.type) {
1929
+ case "file":
1930
+ return {
1931
+ ...part,
1932
+ data: fromJsonDataContent(part.data)
1933
+ };
1934
+ }
1935
+ return part;
1936
+ });
1937
+ };
1938
+ var fromJsonModelMessage = (msg) => {
1939
+ switch (msg.role) {
1940
+ case "system":
1941
+ return msg;
1942
+ case "user":
1943
+ return {
1944
+ ...msg,
1945
+ content: fromJsonUserContent(msg.content)
1946
+ };
1947
+ case "assistant":
1948
+ return {
1949
+ ...msg,
1950
+ content: fromJsonAssistantContent(msg.content)
1951
+ };
1952
+ }
1953
+ return msg;
1954
+ };
1955
+
1956
+ // src/workflow/workflow.ts
1957
+ var silentLogger = {
1958
+ debug: () => {
1959
+ },
1960
+ info: () => {
1961
+ },
1962
+ warn: () => {
1963
+ },
1964
+ error: () => {
1965
+ }
1966
+ };
1967
+ function createContext(tools, stepFn, logger = silentLogger) {
1968
+ if (!stepFn) {
1969
+ stepFn = async (_name, fn) => fn();
1970
+ }
1971
+ return { step: stepFn, logger, tools };
1972
+ }
1973
+ var makeStepFn = () => {
1974
+ const results = /* @__PURE__ */ new Map();
1975
+ const callStack = [];
1976
+ return async (name, fn) => {
1977
+ callStack.push(name);
1978
+ const key = callStack.join(">");
1979
+ try {
1980
+ if (results.has(key)) {
1981
+ return results.get(key);
1982
+ }
1983
+ const result = await fn();
1984
+ results.set(key, result);
1985
+ return result;
1986
+ } finally {
1987
+ callStack.pop();
1988
+ }
1989
+ };
1990
+ };
1647
1991
  export {
1648
1992
  MockProvider,
1993
+ TaskEventKind,
1649
1994
  TodoItemSchema,
1650
1995
  TodoStatus,
1651
1996
  ToolResponseType,
1652
1997
  UpdateTodoItemInputSchema,
1653
1998
  UpdateTodoItemOutputSchema,
1654
1999
  UsageMeter,
2000
+ agentWorkflow,
1655
2001
  askFollowupQuestion_default as askFollowupQuestion,
1656
2002
  computeRateLimitBackoffSeconds,
1657
2003
  configSchema,
2004
+ createContext,
1658
2005
  executeCommand_default as executeCommand,
1659
2006
  fetchUrl_default as fetchUrl,
2007
+ fromJsonModelMessage,
1660
2008
  getTodoItem_default as getTodoItem,
1661
2009
  listFiles_default as listFiles,
1662
2010
  listMemoryTopics_default as listMemoryTopics,
1663
2011
  listTodoItems_default as listTodoItems,
2012
+ makeStepFn,
1664
2013
  parseJsonFromMarkdown,
1665
2014
  readBinaryFile_default as readBinaryFile,
1666
2015
  readFile_default as readFile,
@@ -1671,6 +2020,7 @@ export {
1671
2020
  replaceInFile as replaceInFileHelper,
1672
2021
  responsePrompts,
1673
2022
  searchFiles_default as searchFiles,
2023
+ toJsonModelMessage,
1674
2024
  updateMemory_default as updateMemory,
1675
2025
  updateTodoItem_default as updateTodoItem,
1676
2026
  writeToFile_default as writeToFile
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/core",
3
- "version": "0.9.51",
3
+ "version": "0.9.53",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",