orchajs 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { OrchaError } from "../errors.js";
1
+ import { describeProviderError, isRetryableProviderConnectionError, OrchaError, } from "../errors.js";
2
2
  import { normalizeLocalFile, normalizeUrlContent, } from "../file-content.js";
3
3
  import { messagesFromEvents, normalizePersistedToolResults, SessionEventWriter, } from "./session-events.js";
4
4
  import { validateStructuredValue } from "./structured-output.js";
@@ -620,7 +620,8 @@ export class RuntimeAgent {
620
620
  }
621
621
  providerTools.push(...this.#subagentToolDefinitions());
622
622
  try {
623
- response = await this.#generateProviderResponse(this.#manifest.provider, provider, {
623
+ const signal = this.#sessionControls.get(sessionId)?.controller.signal;
624
+ response = await withProviderConnectionRetry(() => this.#generateProviderResponse(this.#manifest.provider, provider, {
624
625
  model: this.#manifest.model,
625
626
  region: this.#manifest.region,
626
627
  maxTokens: this.#manifest.maxTokens,
@@ -634,8 +635,8 @@ export class RuntimeAgent {
634
635
  streamedOutput = output;
635
636
  publishOutput?.(output);
636
637
  },
637
- signal: this.#sessionControls.get(sessionId)?.controller.signal,
638
- });
638
+ signal,
639
+ }), signal);
639
640
  }
640
641
  catch (error) {
641
642
  if (this.#sessionControls.get(sessionId)?.pauseRequested) {
@@ -665,7 +666,16 @@ export class RuntimeAgent {
665
666
  if (error instanceof OrchaError) {
666
667
  throw error;
667
668
  }
668
- throw new OrchaError("provider_error", error instanceof Error ? error.message : String(error), { retryable: true, cause: error });
669
+ const providerError = describeProviderError(error);
670
+ throw new OrchaError("provider_error", providerError.message, {
671
+ retryable: true,
672
+ cause: error,
673
+ details: {
674
+ provider: this.#manifest.provider,
675
+ model: this.#manifest.model,
676
+ ...providerError.details,
677
+ },
678
+ });
669
679
  }
670
680
  const modelDurationMs = Math.round(performance.now() - modelStartedAt);
671
681
  const usage = aggregateUsage(previousEvents, writer.run, response.usage);
@@ -2609,6 +2619,21 @@ function findLast(events, predicate) {
2609
2619
  }
2610
2620
  return undefined;
2611
2621
  }
2622
+ async function withProviderConnectionRetry(operation, signal) {
2623
+ try {
2624
+ return await operation();
2625
+ }
2626
+ catch (error) {
2627
+ if (signal?.aborted ||
2628
+ !isRetryableProviderConnectionError(error)) {
2629
+ throw error;
2630
+ }
2631
+ await new Promise((resolve) => setTimeout(resolve, 250));
2632
+ if (signal?.aborted)
2633
+ throw error;
2634
+ return operation();
2635
+ }
2636
+ }
2612
2637
  function failure(sessionId, code, message, options = {}) {
2613
2638
  const retryable = options.retryable ??
2614
2639
  (code === "session_busy" ||
@@ -4,6 +4,10 @@ import type { AgentRuntime, CompiledBundle, OrchaInitConfiguration } from "../ty
4
4
  export interface Orcha {
5
5
  init(configuration: OrchaInitConfiguration): OrchaClient;
6
6
  isInitialized(): boolean;
7
+ /** Flushes queued Amarsia telemetry without blocking normal agent runs. */
8
+ flushTelemetry(options?: {
9
+ timeoutMs?: number;
10
+ }): Promise<void>;
7
11
  /** @internal Used by the development compiler. */
8
12
  getCompiledBundle(): CompiledBundle;
9
13
  }
@@ -1,9 +1,11 @@
1
1
  import { RuntimeAgent } from "./agent.js";
2
+ import { AmarsiaTelemetryClient, withAmarsiaTelemetry, } from "../amarsia/analytics.js";
2
3
  import { setOrchaRuntimeContext } from "./context.js";
3
4
  class OrchaRuntimeCore {
4
5
  #agents = new Map();
5
6
  #bundle;
6
7
  #client;
8
+ #telemetry;
7
9
  #activeSessions = new Set();
8
10
  #sessionControls = new Map();
9
11
  #resolveBundle;
@@ -18,6 +20,9 @@ class OrchaRuntimeCore {
18
20
  this.#client = client;
19
21
  }
20
22
  init(configuration) {
23
+ if (this.#telemetry) {
24
+ void this.#telemetry.close();
25
+ }
21
26
  const projectRoot = this.#platform.projectRoot(configuration);
22
27
  const bundle = configuration.bundle ?? this.#resolveBundle(configuration);
23
28
  if (configuration.amarsia?.key && this.#platform.syncProject) {
@@ -47,6 +52,16 @@ class OrchaRuntimeCore {
47
52
  projectRoot,
48
53
  manifest,
49
54
  });
55
+ const telemetry = configuration.amarsia?.key
56
+ ? new AmarsiaTelemetryClient(configuration.amarsia)
57
+ : undefined;
58
+ this.#telemetry = telemetry;
59
+ const createRuntimeStore = (manifest) => {
60
+ const store = createStore(manifest);
61
+ return telemetry
62
+ ? withAmarsiaTelemetry({ store, manifest, client: telemetry })
63
+ : store;
64
+ };
50
65
  const agents = new Map();
51
66
  for (const [name, manifest] of Object.entries(bundle.agents)) {
52
67
  const subagents = Object.fromEntries(Object.entries(manifest.subagents ?? {}).map(([subagentName, subagentManifest]) => [
@@ -54,7 +69,7 @@ class OrchaRuntimeCore {
54
69
  new RuntimeAgent({
55
70
  manifest: subagentManifest,
56
71
  configuration: runtimeConfiguration,
57
- store: createStore(subagentManifest),
72
+ store: createRuntimeStore(subagentManifest),
58
73
  activeSessions: this.#activeSessions,
59
74
  sessionControls: this.#sessionControls,
60
75
  generateProviderResponse: this.#generateProviderResponse,
@@ -66,7 +81,7 @@ class OrchaRuntimeCore {
66
81
  agents.set(name, new RuntimeAgent({
67
82
  manifest,
68
83
  configuration: runtimeConfiguration,
69
- store: createStore(manifest),
84
+ store: createRuntimeStore(manifest),
70
85
  activeSessions: this.#activeSessions,
71
86
  sessionControls: this.#sessionControls,
72
87
  generateProviderResponse: this.#generateProviderResponse,
@@ -89,6 +104,9 @@ class OrchaRuntimeCore {
89
104
  isInitialized() {
90
105
  return this.#bundle !== undefined;
91
106
  }
107
+ async flushTelemetry(options) {
108
+ await this.#telemetry?.drain(options);
109
+ }
92
110
  getCompiledBundle() {
93
111
  if (!this.#bundle) {
94
112
  throw new Error("Orcha has not been initialized.");
package/dist/types.d.ts CHANGED
@@ -64,6 +64,84 @@ export interface OrchaInitConfiguration {
64
64
  storage?: ProjectConfiguration["storage"];
65
65
  root?: string;
66
66
  }
67
+ /** Privacy-safe, versioned run fact sent to Amarsia when `amarsia.key` is set. */
68
+ export interface AmarsiaTelemetryRunV1 {
69
+ event_id: string;
70
+ agent_external_id: string;
71
+ session_id: string;
72
+ run_number: number;
73
+ parent_agent_external_id?: string;
74
+ parent_session_id?: string;
75
+ status: string;
76
+ provider: string;
77
+ model: string;
78
+ region?: string;
79
+ output_type?: string;
80
+ stop_reason?: string;
81
+ started_at: string;
82
+ ended_at?: string;
83
+ duration_ms?: number;
84
+ model_duration_ms: number;
85
+ action_duration_ms: number;
86
+ input_tokens: number;
87
+ output_tokens: number;
88
+ reasoning_tokens?: number;
89
+ cache_read_tokens: number;
90
+ cache_write_tokens: number;
91
+ user_message_count: number;
92
+ assistant_message_count: number;
93
+ action_count: number;
94
+ action_success_count: number;
95
+ action_failure_count: number;
96
+ subagent_count: number;
97
+ actions: AmarsiaTelemetryActionV1[];
98
+ evaluation_count: number;
99
+ evaluation_pass_count: number;
100
+ evaluation_failure_count: number;
101
+ evaluation_error_count: number;
102
+ evaluation_metric_count: number;
103
+ evaluation_metric_pass_count: number;
104
+ evaluations: AmarsiaTelemetryEvaluationV1[];
105
+ error_code?: string;
106
+ error_message?: string;
107
+ error_retryable?: boolean;
108
+ }
109
+ export interface AmarsiaTelemetryActionV1 {
110
+ call_id: string;
111
+ name: string;
112
+ status: "completed" | "failed";
113
+ started_at: string;
114
+ ended_at: string;
115
+ duration_ms: number;
116
+ error_code?: string;
117
+ error_message?: string;
118
+ }
119
+ export interface AmarsiaTelemetryEvaluationMetricV1 {
120
+ name: string;
121
+ score: number;
122
+ threshold: number;
123
+ passed: boolean;
124
+ reasoning: string;
125
+ evidence: string[];
126
+ }
127
+ export interface AmarsiaTelemetryEvaluationV1 {
128
+ name: string;
129
+ status: "passed" | "failed" | "error";
130
+ provider?: string;
131
+ model?: string;
132
+ duration_ms: number;
133
+ input_tokens: number;
134
+ output_tokens: number;
135
+ reasoning_tokens: number;
136
+ cache_read_tokens: number;
137
+ cache_write_tokens: number;
138
+ metrics: AmarsiaTelemetryEvaluationMetricV1[];
139
+ error_message?: string;
140
+ }
141
+ export interface AmarsiaTelemetryBatchV1 {
142
+ schema_version: 1;
143
+ runs: AmarsiaTelemetryRunV1[];
144
+ }
67
145
  export interface SubagentConfiguration {
68
146
  maxPerRun?: number;
69
147
  }