@simulacra-ai/core 0.0.6 → 0.0.9

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
@@ -90,13 +90,29 @@ class WeatherTool {
90
90
 
91
91
  The workflow engine drives the tool call loop and enables agentic behaviors. The `WorkflowManager` sits on top of the conversation object, managing workflow state and executing tools on the model's behalf, running them in parallel when possible, and feeding results back until the model produces a final response.
92
92
 
93
- The workflow manager emits events throughout its lifecycle, making it possible to observe the full agentic loop.
93
+ ### Running a Workflow
94
+
95
+ `manager.run()` sends a prompt and returns a promise that resolves when the full workflow completes, including all tool execution rounds.
96
+
97
+ ```typescript
98
+ using conversation = new Conversation(provider);
99
+ using manager = new WorkflowManager(conversation);
100
+
101
+ conversation.toolkit = [WeatherTool];
102
+
103
+ const result = await manager.run("What's the weather in Tokyo?");
104
+ // result.reason is "complete", "cancel", or "error"
105
+ ```
106
+
107
+ This is different from `conversation.prompt()`, which resolves after a single model response. If the model responds with tool calls, `prompt()` returns after that first response while the workflow continues executing tools in the background. `manager.run()` waits for the entire loop to finish.
108
+
109
+ ### Events
110
+
111
+ The workflow manager also emits events throughout its lifecycle, making it possible to observe the full agentic loop without `run()`.
94
112
 
95
113
  ```typescript
96
- // create a conversation and workflow manager
97
114
  using manager = new WorkflowManager(conversation);
98
115
 
99
- // log the final message when the workflow completes
100
116
  manager.once("workflow_begin", (workflow) =>
101
117
  workflow.once("workflow_end", () => {
102
118
  console.log(conversation.messages.at(-1));
package/dist/index.cjs CHANGED
@@ -599,6 +599,9 @@ var RETRYABLE_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
599
599
  var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504, 529]);
600
600
  function defaultRetryable(result) {
601
601
  const error = result.error;
602
+ if (error instanceof OperationCanceledError) {
603
+ return false;
604
+ }
602
605
  if (error !== null && error !== void 0 && typeof error === "object" && "status" in error) {
603
606
  const status = error.status;
604
607
  if (typeof status === "number") {
@@ -620,7 +623,7 @@ function defaultRetryable(result) {
620
623
  }
621
624
  if (error instanceof Error) {
622
625
  const msg = error.message.toLowerCase();
623
- if (msg.includes("timeout") || msg.includes("econnreset") || msg.includes("econnrefused") || msg.includes("socket hang up") || msg.includes("network error") || msg.includes("fetch failed")) {
626
+ if (msg.includes("timeout") || msg.includes("econnreset") || msg.includes("econnrefused") || msg.includes("socket hang up") || msg.includes("network error") || msg.includes("fail")) {
624
627
  return true;
625
628
  }
626
629
  }
@@ -666,6 +669,7 @@ var RetryPolicy = class _RetryPolicy extends Policy {
666
669
  metadata
667
670
  };
668
671
  } catch (error) {
672
+ cancellation_token.throw_if_cancellation_requested();
669
673
  metadata.attempts = attempt;
670
674
  const result = {
671
675
  result: false,
@@ -2160,6 +2164,26 @@ var WorkflowManager = class {
2160
2164
  throw new Error("invalid state");
2161
2165
  }
2162
2166
  }
2167
+ async run(input) {
2168
+ if (this.#state !== "idle") {
2169
+ throw new Error("invalid state");
2170
+ }
2171
+ const workflow_end = new Promise((resolve) => {
2172
+ const handler = (event) => {
2173
+ if (event.event_name === "workflow_end") {
2174
+ this.off("workflow_event", handler);
2175
+ resolve(event.event_args[0]);
2176
+ }
2177
+ };
2178
+ this.on("workflow_event", handler);
2179
+ });
2180
+ if (typeof input === "string") {
2181
+ await this.#conversation.prompt(input);
2182
+ } else {
2183
+ await this.#conversation.send_message(input);
2184
+ }
2185
+ return workflow_end;
2186
+ }
2163
2187
  #on_prompt_send = ({ message }) => {
2164
2188
  if (this.#current_workflow) {
2165
2189
  return;
@@ -2219,8 +2243,8 @@ function defined_keys(obj) {
2219
2243
  return Object.keys(obj).filter((key) => obj[key] !== void 0);
2220
2244
  }
2221
2245
  function undefined_if_empty(obj) {
2222
- if (!obj) {
2223
- return obj;
2246
+ if (obj === null || obj === void 0) {
2247
+ return void 0;
2224
2248
  }
2225
2249
  if (Array.isArray(obj)) {
2226
2250
  return obj.length === 0 ? void 0 : obj;