@polos/sdk 0.1.2 → 0.1.3

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/index.d.cts CHANGED
@@ -2155,8 +2155,8 @@ declare class DuplicateWorkflowError extends Error {
2155
2155
  */
2156
2156
  interface WorkflowRegistry {
2157
2157
  /**
2158
- * Register a workflow.
2159
- * @throws DuplicateWorkflowError if workflow ID is already registered
2158
+ * Register a workflow. If a workflow with the same ID is already
2159
+ * registered, it is silently replaced.
2160
2160
  */
2161
2161
  register(workflow: Workflow): void;
2162
2162
  /**
@@ -3006,6 +3006,8 @@ interface LLMUsage {
3006
3006
  input_tokens: number;
3007
3007
  output_tokens: number;
3008
3008
  total_tokens: number;
3009
+ cache_read_input_tokens?: number | undefined;
3010
+ cache_creation_input_tokens?: number | undefined;
3009
3011
  }
3010
3012
  /**
3011
3013
  * A tool call made by the LLM
@@ -3148,6 +3150,10 @@ declare function convertVercelUsageToPython(usage: {
3148
3150
  inputTokens: number | undefined;
3149
3151
  outputTokens: number | undefined;
3150
3152
  totalTokens?: number | undefined;
3153
+ inputTokenDetails?: {
3154
+ cacheReadTokens?: number | undefined;
3155
+ cacheWriteTokens?: number | undefined;
3156
+ };
3151
3157
  }): LLMUsage;
3152
3158
  /**
3153
3159
  * Convert Vercel finish reason (kebab-case) to Python format (snake_case).
@@ -3527,6 +3533,8 @@ interface DefineAgentConfig {
3527
3533
  guardrailMaxRetries?: number | undefined;
3528
3534
  /** Number of conversation history messages to retain (default: 10) */
3529
3535
  conversationHistory?: number | undefined;
3536
+ /** Publish text_delta and tool_call events to the workflow topic for all invocations */
3537
+ streamToWorkflow?: boolean | undefined;
3530
3538
  }
3531
3539
  /**
3532
3540
  * Payload for agent run() and stream() calls.
package/dist/index.d.ts CHANGED
@@ -2155,8 +2155,8 @@ declare class DuplicateWorkflowError extends Error {
2155
2155
  */
2156
2156
  interface WorkflowRegistry {
2157
2157
  /**
2158
- * Register a workflow.
2159
- * @throws DuplicateWorkflowError if workflow ID is already registered
2158
+ * Register a workflow. If a workflow with the same ID is already
2159
+ * registered, it is silently replaced.
2160
2160
  */
2161
2161
  register(workflow: Workflow): void;
2162
2162
  /**
@@ -3006,6 +3006,8 @@ interface LLMUsage {
3006
3006
  input_tokens: number;
3007
3007
  output_tokens: number;
3008
3008
  total_tokens: number;
3009
+ cache_read_input_tokens?: number | undefined;
3010
+ cache_creation_input_tokens?: number | undefined;
3009
3011
  }
3010
3012
  /**
3011
3013
  * A tool call made by the LLM
@@ -3148,6 +3150,10 @@ declare function convertVercelUsageToPython(usage: {
3148
3150
  inputTokens: number | undefined;
3149
3151
  outputTokens: number | undefined;
3150
3152
  totalTokens?: number | undefined;
3153
+ inputTokenDetails?: {
3154
+ cacheReadTokens?: number | undefined;
3155
+ cacheWriteTokens?: number | undefined;
3156
+ };
3151
3157
  }): LLMUsage;
3152
3158
  /**
3153
3159
  * Convert Vercel finish reason (kebab-case) to Python format (snake_case).
@@ -3527,6 +3533,8 @@ interface DefineAgentConfig {
3527
3533
  guardrailMaxRetries?: number | undefined;
3528
3534
  /** Number of conversation history messages to retain (default: 10) */
3529
3535
  conversationHistory?: number | undefined;
3536
+ /** Publish text_delta and tool_call events to the workflow topic for all invocations */
3537
+ streamToWorkflow?: boolean | undefined;
3530
3538
  }
3531
3539
  /**
3532
3540
  * Payload for agent run() and stream() calls.
package/dist/index.js CHANGED
@@ -31,9 +31,6 @@ function createWorkflowRegistry() {
31
31
  const workflows = /* @__PURE__ */ new Map();
32
32
  return {
33
33
  register(workflow) {
34
- if (workflows.has(workflow.id)) {
35
- throw new DuplicateWorkflowError(workflow.id);
36
- }
37
34
  workflows.set(workflow.id, workflow);
38
35
  },
39
36
  get(workflowId) {
@@ -1785,11 +1782,18 @@ function convertMiddlewareToolCallToPython(tc) {
1785
1782
  function convertVercelUsageToPython(usage) {
1786
1783
  const input = usage.inputTokens ?? 0;
1787
1784
  const output = usage.outputTokens ?? 0;
1788
- return {
1785
+ const result = {
1789
1786
  input_tokens: input,
1790
1787
  output_tokens: output,
1791
1788
  total_tokens: usage.totalTokens ?? input + output
1792
1789
  };
1790
+ if (usage.inputTokenDetails?.cacheReadTokens != null) {
1791
+ result.cache_read_input_tokens = usage.inputTokenDetails.cacheReadTokens;
1792
+ }
1793
+ if (usage.inputTokenDetails?.cacheWriteTokens != null) {
1794
+ result.cache_creation_input_tokens = usage.inputTokenDetails.cacheWriteTokens;
1795
+ }
1796
+ return result;
1793
1797
  }
1794
1798
  function convertFinishReason(reason) {
1795
1799
  if (!reason) return null;
@@ -1804,6 +1808,41 @@ function convertFinishReason(reason) {
1804
1808
  }
1805
1809
 
1806
1810
  // src/llm/llm.ts
1811
+ var ANTHROPIC_CACHE_BREAKPOINT = {
1812
+ anthropic: { cacheControl: { type: "ephemeral" } }
1813
+ };
1814
+ function isAnthropicModel(model) {
1815
+ return getModelProvider(model).startsWith("anthropic");
1816
+ }
1817
+ function applyAnthropicCacheControl(args, model) {
1818
+ if (!isAnthropicModel(model)) return;
1819
+ if (typeof args["system"] === "string") {
1820
+ args["system"] = {
1821
+ role: "system",
1822
+ content: args["system"],
1823
+ providerOptions: ANTHROPIC_CACHE_BREAKPOINT
1824
+ };
1825
+ }
1826
+ const tools = args["tools"];
1827
+ if (tools) {
1828
+ const toolNames = Object.keys(tools);
1829
+ if (toolNames.length > 0) {
1830
+ const lastToolName = toolNames[toolNames.length - 1];
1831
+ tools[lastToolName] = {
1832
+ ...tools[lastToolName],
1833
+ providerOptions: ANTHROPIC_CACHE_BREAKPOINT
1834
+ };
1835
+ }
1836
+ }
1837
+ const messages = args["messages"];
1838
+ if (messages && messages.length > 0) {
1839
+ const lastMsg = messages[messages.length - 1];
1840
+ messages[messages.length - 1] = {
1841
+ ...lastMsg,
1842
+ providerOptions: ANTHROPIC_CACHE_BREAKPOINT
1843
+ };
1844
+ }
1845
+ }
1807
1846
  function buildGenerateArgs(model, messages, options) {
1808
1847
  const args = { model, messages };
1809
1848
  const tools = convertToolsToVercel(options.tools);
@@ -1815,6 +1854,7 @@ function buildGenerateArgs(model, messages, options) {
1815
1854
  if (options.outputSchema) {
1816
1855
  args["experimental_output"] = Output.object({ schema: options.outputSchema });
1817
1856
  }
1857
+ applyAnthropicCacheControl(args, model);
1818
1858
  return args;
1819
1859
  }
1820
1860
  var LLM = class {
@@ -2560,6 +2600,8 @@ async function agentStreamFunction(ctx, payload, agentDef) {
2560
2600
  let finalInputTokens = 0;
2561
2601
  let finalOutputTokens = 0;
2562
2602
  let finalTotalTokens = 0;
2603
+ let finalCacheReadInputTokens = 0;
2604
+ let finalCacheCreationInputTokens = 0;
2563
2605
  let lastLlmResultContent = null;
2564
2606
  const allToolResults = [];
2565
2607
  const steps = [];
@@ -2690,6 +2732,12 @@ async function agentStreamFunction(ctx, payload, agentDef) {
2690
2732
  finalInputTokens += llmResult.usage.input_tokens;
2691
2733
  finalOutputTokens += llmResult.usage.output_tokens;
2692
2734
  finalTotalTokens += llmResult.usage.total_tokens;
2735
+ if (llmResult.usage.cache_read_input_tokens) {
2736
+ finalCacheReadInputTokens += llmResult.usage.cache_read_input_tokens;
2737
+ }
2738
+ if (llmResult.usage.cache_creation_input_tokens) {
2739
+ finalCacheCreationInputTokens += llmResult.usage.cache_creation_input_tokens;
2740
+ }
2693
2741
  }
2694
2742
  lastLlmResultContent = llmResult.content;
2695
2743
  const toolCalls = llmResult.tool_calls ?? [];
@@ -2913,7 +2961,11 @@ Please provide ONLY valid JSON that matches the schema, with no additional text
2913
2961
  usage: {
2914
2962
  input_tokens: finalInputTokens,
2915
2963
  output_tokens: finalOutputTokens,
2916
- total_tokens: finalTotalTokens
2964
+ total_tokens: finalTotalTokens,
2965
+ ...finalCacheReadInputTokens > 0 && { cache_read_input_tokens: finalCacheReadInputTokens },
2966
+ ...finalCacheCreationInputTokens > 0 && {
2967
+ cache_creation_input_tokens: finalCacheCreationInputTokens
2968
+ }
2917
2969
  }
2918
2970
  };
2919
2971
  }
@@ -3074,7 +3126,7 @@ function defineAgent(config) {
3074
3126
  maxOutputTokens: config.maxOutputTokens
3075
3127
  },
3076
3128
  input,
3077
- streaming: streamingFlag ?? false,
3129
+ streaming: streamingFlag ?? config.streamToWorkflow ?? false,
3078
3130
  conversation_id: conversationIdValue
3079
3131
  };
3080
3132
  return agentStreamFunction(ctx, streamPayload, {
@@ -5778,6 +5830,13 @@ var DEFAULT_TIMEOUT_SECONDS = 300;
5778
5830
  var DEFAULT_MAX_OUTPUT_CHARS = 1e5;
5779
5831
  function spawnCommand(command, args, options) {
5780
5832
  return new Promise((resolve8, reject) => {
5833
+ let settled = false;
5834
+ const settle = (fn) => {
5835
+ if (!settled) {
5836
+ settled = true;
5837
+ fn();
5838
+ }
5839
+ };
5781
5840
  const proc = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
5782
5841
  let stdout = "";
5783
5842
  let stderr = "";
@@ -5788,6 +5847,12 @@ function spawnCommand(command, args, options) {
5788
5847
  proc.stderr.on("data", (data) => {
5789
5848
  stderr += data.toString();
5790
5849
  });
5850
+ proc.stdin.on("error", () => {
5851
+ });
5852
+ proc.stdout.on("error", () => {
5853
+ });
5854
+ proc.stderr.on("error", () => {
5855
+ });
5791
5856
  const timeoutMs = (options?.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1e3;
5792
5857
  const timer = setTimeout(() => {
5793
5858
  killed = true;
@@ -5795,24 +5860,31 @@ function spawnCommand(command, args, options) {
5795
5860
  }, timeoutMs);
5796
5861
  proc.on("close", (code) => {
5797
5862
  clearTimeout(timer);
5798
- if (killed) {
5799
- resolve8({
5800
- exitCode: 137,
5801
- stdout,
5802
- stderr: stderr + "\n[Process killed: timeout exceeded]"
5803
- });
5804
- } else {
5805
- resolve8({ exitCode: code ?? 1, stdout, stderr });
5806
- }
5863
+ settle(() => {
5864
+ if (killed) {
5865
+ resolve8({
5866
+ exitCode: 137,
5867
+ stdout,
5868
+ stderr: stderr + "\n[Process killed: timeout exceeded]"
5869
+ });
5870
+ } else {
5871
+ resolve8({ exitCode: code ?? 1, stdout, stderr });
5872
+ }
5873
+ });
5807
5874
  });
5808
5875
  proc.on("error", (err) => {
5809
5876
  clearTimeout(timer);
5810
- reject(err);
5877
+ settle(() => {
5878
+ reject(err);
5879
+ });
5811
5880
  });
5812
5881
  if (options?.stdin) {
5813
- proc.stdin.write(options.stdin);
5882
+ proc.stdin.write(options.stdin, () => {
5883
+ proc.stdin.end();
5884
+ });
5885
+ } else {
5886
+ proc.stdin.end();
5814
5887
  }
5815
- proc.stdin.end();
5816
5888
  });
5817
5889
  }
5818
5890
  var DockerEnvironment = class {
@@ -5868,7 +5940,7 @@ var DockerEnvironment = class {
5868
5940
  }
5869
5941
  async exec(command, opts) {
5870
5942
  this.assertInitialized();
5871
- const args = ["exec", "-i"];
5943
+ const args = opts?.stdin ? ["exec", "-i"] : ["exec"];
5872
5944
  const cwd = opts?.cwd ?? this.containerWorkdir;
5873
5945
  args.push("-w", cwd);
5874
5946
  if (opts?.env) {
@@ -6003,6 +6075,13 @@ var DEFAULT_TIMEOUT_SECONDS2 = 300;
6003
6075
  var DEFAULT_MAX_OUTPUT_CHARS2 = 1e5;
6004
6076
  function spawnLocal(command, options) {
6005
6077
  return new Promise((resolve8, reject) => {
6078
+ let settled = false;
6079
+ const settle = (fn) => {
6080
+ if (!settled) {
6081
+ settled = true;
6082
+ fn();
6083
+ }
6084
+ };
6006
6085
  const proc = spawn("sh", ["-c", command], {
6007
6086
  cwd: options.cwd,
6008
6087
  env: options.env ? { ...process.env, ...options.env } : void 0,
@@ -6017,6 +6096,12 @@ function spawnLocal(command, options) {
6017
6096
  proc.stderr.on("data", (data) => {
6018
6097
  stderr += data.toString();
6019
6098
  });
6099
+ proc.stdin.on("error", () => {
6100
+ });
6101
+ proc.stdout.on("error", () => {
6102
+ });
6103
+ proc.stderr.on("error", () => {
6104
+ });
6020
6105
  const timeoutMs = (options.timeout ?? DEFAULT_TIMEOUT_SECONDS2) * 1e3;
6021
6106
  const timer = setTimeout(() => {
6022
6107
  killed = true;
@@ -6024,24 +6109,31 @@ function spawnLocal(command, options) {
6024
6109
  }, timeoutMs);
6025
6110
  proc.on("close", (code) => {
6026
6111
  clearTimeout(timer);
6027
- if (killed) {
6028
- resolve8({
6029
- exitCode: 137,
6030
- stdout,
6031
- stderr: stderr + "\n[Process killed: timeout exceeded]"
6032
- });
6033
- } else {
6034
- resolve8({ exitCode: code ?? 1, stdout, stderr });
6035
- }
6112
+ settle(() => {
6113
+ if (killed) {
6114
+ resolve8({
6115
+ exitCode: 137,
6116
+ stdout,
6117
+ stderr: stderr + "\n[Process killed: timeout exceeded]"
6118
+ });
6119
+ } else {
6120
+ resolve8({ exitCode: code ?? 1, stdout, stderr });
6121
+ }
6122
+ });
6036
6123
  });
6037
6124
  proc.on("error", (err) => {
6038
6125
  clearTimeout(timer);
6039
- reject(err);
6126
+ settle(() => {
6127
+ reject(err);
6128
+ });
6040
6129
  });
6041
6130
  if (options.stdin) {
6042
- proc.stdin.write(options.stdin);
6131
+ proc.stdin.write(options.stdin, () => {
6132
+ proc.stdin.end();
6133
+ });
6134
+ } else {
6135
+ proc.stdin.end();
6043
6136
  }
6044
- proc.stdin.end();
6045
6137
  });
6046
6138
  }
6047
6139
  var LocalEnvironment = class {