smithers-orchestrator 0.21.0 → 0.22.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smithers-orchestrator",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Public Smithers facade for durable coding-agent workflows and Gateway operation",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -61,27 +61,27 @@
61
61
  "incur": "^0.4.1",
62
62
  "react": "^19.2.5",
63
63
  "zod": "^4.3.6",
64
- "@smithers-orchestrator/components": "0.21.0",
65
- "@smithers-orchestrator/agents": "0.21.0",
66
- "@smithers-orchestrator/cli": "0.21.0",
67
- "@smithers-orchestrator/db": "0.21.0",
68
- "@smithers-orchestrator/control-plane": "0.21.0",
69
- "@smithers-orchestrator/driver": "0.21.0",
70
- "@smithers-orchestrator/engine": "0.21.0",
71
- "@smithers-orchestrator/errors": "0.21.0",
72
- "@smithers-orchestrator/gateway-client": "0.21.0",
73
- "@smithers-orchestrator/gateway-react": "0.21.0",
74
- "@smithers-orchestrator/graph": "0.21.0",
75
- "@smithers-orchestrator/memory": "0.21.0",
76
- "@smithers-orchestrator/openapi": "0.21.0",
77
- "@smithers-orchestrator/observability": "0.21.0",
78
- "@smithers-orchestrator/sandbox": "0.21.0",
79
- "@smithers-orchestrator/react-reconciler": "0.21.0",
80
- "@smithers-orchestrator/scheduler": "0.21.0",
81
- "@smithers-orchestrator/scorers": "0.21.0",
82
- "@smithers-orchestrator/server": "0.21.0",
83
- "@smithers-orchestrator/time-travel": "0.21.0",
84
- "@smithers-orchestrator/vcs": "0.21.0"
64
+ "@smithers-orchestrator/agents": "0.22.0",
65
+ "@smithers-orchestrator/cli": "0.22.0",
66
+ "@smithers-orchestrator/components": "0.22.0",
67
+ "@smithers-orchestrator/control-plane": "0.22.0",
68
+ "@smithers-orchestrator/driver": "0.22.0",
69
+ "@smithers-orchestrator/engine": "0.22.0",
70
+ "@smithers-orchestrator/gateway-client": "0.22.0",
71
+ "@smithers-orchestrator/errors": "0.22.0",
72
+ "@smithers-orchestrator/gateway-react": "0.22.0",
73
+ "@smithers-orchestrator/graph": "0.22.0",
74
+ "@smithers-orchestrator/db": "0.22.0",
75
+ "@smithers-orchestrator/memory": "0.22.0",
76
+ "@smithers-orchestrator/observability": "0.22.0",
77
+ "@smithers-orchestrator/openapi": "0.22.0",
78
+ "@smithers-orchestrator/react-reconciler": "0.22.0",
79
+ "@smithers-orchestrator/sandbox": "0.22.0",
80
+ "@smithers-orchestrator/scorers": "0.22.0",
81
+ "@smithers-orchestrator/scheduler": "0.22.0",
82
+ "@smithers-orchestrator/server": "0.22.0",
83
+ "@smithers-orchestrator/time-travel": "0.22.0",
84
+ "@smithers-orchestrator/vcs": "0.22.0"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@types/bun": "latest",
package/src/create.js CHANGED
@@ -249,8 +249,9 @@ export function createSmithers(schemas, opts) {
249
249
  sqlite.close();
250
250
  }
251
251
  catch { }
252
+ process.removeListener("exit", closeDb);
252
253
  };
253
- process.on("exit", closeDb);
254
+ process.once("exit", closeDb);
254
255
  // 3. Auto-create tables, and ALTER any existing tables to add columns the
255
256
  // current schema introduced (CREATE TABLE IF NOT EXISTS would silently
256
257
  // skip the columns and a later upsert would fail with "no column named X").
@@ -127,8 +127,9 @@ export function createExternalSmithers(config) {
127
127
  sqlite.close();
128
128
  }
129
129
  catch { }
130
+ process.removeListener("exit", closeDb);
130
131
  };
131
- process.on("exit", closeDb);
132
+ process.once("exit", closeDb);
132
133
  const inputTable = sqliteTable("input", {
133
134
  runId: text("run_id").primaryKey(),
134
135
  payload: text("payload", { mode: "json" }).$type(),
package/src/index.d.ts CHANGED
@@ -56,7 +56,7 @@ import { WorkflowProps } from '@smithers-orchestrator/components/components/Work
56
56
  import * as _smithers_server_gateway from '@smithers-orchestrator/server/gateway';
57
57
  export { Gateway } from '@smithers-orchestrator/server/gateway';
58
58
  import * as _smithers_agents from '@smithers-orchestrator/agents';
59
- export { AmpAgent, AnthropicAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, ForgeAgent, GeminiAgent, KimiAgent, OpenAIAgent, OpenCodeAgent, PiAgent } from '@smithers-orchestrator/agents';
59
+ export { AmpAgent, AnthropicAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, ForgeAgent, GeminiAgent, HermesAgent, KimiAgent, OpenAIAgent, OpenCodeAgent, PiAgent } from '@smithers-orchestrator/agents';
60
60
  import * as _smithers_scorers from '@smithers-orchestrator/scorers';
61
61
  export { aggregateScores, createScorer, faithfulnessScorer, latencyScorer, llmJudge, relevancyScorer, runScorersAsync, runScorersBatch, schemaAdherenceScorer, smithersScorers, toxicityScorer } from '@smithers-orchestrator/scorers';
62
62
  import * as _smithers_agents_capability_registry from '@smithers-orchestrator/agents/capability-registry';
@@ -331,6 +331,7 @@ type MemoryStore = _smithers_memory.MemoryStore;
331
331
  type MemoryThread = _smithers_memory.MemoryThread;
332
332
  type MessageHistoryConfig = _smithers_memory.MessageHistoryConfig;
333
333
  type OpenAIAgentOptions<CALL_OPTIONS = never, TOOLS = ai.ToolSet> = _smithers_agents.OpenAIAgentOptions<CALL_OPTIONS, TOOLS>;
334
+ type HermesAgentOptions<CALL_OPTIONS = never, TOOLS = ai.ToolSet> = _smithers_agents.HermesAgentOptions<CALL_OPTIONS, TOOLS>;
334
335
  type OpenCodeAgentOptions = _smithers_agents.OpenCodeAgentOptions;
335
336
  type OpenApiAuth = _smithers_openapi.OpenApiAuth;
336
337
  type OpenApiSpec = _smithers_openapi.OpenApiSpec;
@@ -407,4 +408,4 @@ type XmlElement = _smithers_graph_XmlNode.XmlElement;
407
408
  type XmlNode = _smithers_graph_XmlNode.XmlNode;
408
409
  type XmlText = _smithers_graph_XmlNode.XmlText;
409
410
 
410
- export { type AgentCapabilityRegistry, type AgentLike, type AgentToolDescriptor, type AggregateOptions, type AggregateScore, type AnthropicAgentOptions, type ApprovalAutoApprove, type ApprovalDecision, type ApprovalMode, type ApprovalOption, type ApprovalProps, type ApprovalRanking, type ApprovalRequest, type ApprovalSelection, type ColumnDef, type ConnectRequest, type ContinueAsNewProps, type CreateScorerConfig, type CreateSmithersApi, type DepsSpec, type EventFrame, type ExternalSmithersConfig, type GatewayAuthConfig, type GatewayDefaults, type GatewayOptions, type GatewayTokenGrant, type GraphSnapshot, type HelloResponse, type HostContainer, type HostNodeJson, type InferDeps, type InferOutputEntry, type InferRow, type JjRevertResult, type KanbanProps, type KnownSmithersErrorCode, type LlmJudgeConfig, type MemoryFact, type MemoryLayerConfig, type MemoryMessage, type MemoryNamespace, type MemoryNamespaceKind, type MemoryProcessor, type MemoryProcessorConfig, type MemoryServiceApi, type MemoryStore, type MemoryThread, type MessageHistoryConfig, type OpenAIAgentOptions, type OpenApiAuth, type OpenApiSpec, type OpenApiToolsOptions, type OpenCodeAgentOptions, type OutputAccessor, type OutputKey, type OutputTarget, type PiAgentOptions, type PiExtensionUiRequest, type PiExtensionUiResponse, type PollerProps, type RequestFrame, type ResolvedSmithersObservabilityOptions, type ResponseFrame, type RevertOptions, type RevertResult, type RunJjOptions, type RunJjResult, type RunOptions, type RunResult, type RunStatus, type SagaProps, type SagaStepDef, type SagaStepProps, type SamplingConfig, type SandboxProps, type SandboxRuntime, type SandboxVolumeMount, type SandboxWorkspaceSpec, type SchemaRegistryEntry, type ScoreResult, type ScoreRow, type Scorer, type ScorerBinding, type ScorerContext, type ScorerFn, type ScorerInput, type ScorersMap, type SemanticRecallConfig, type SerializedCtx, type ServeOptions, type ServerOptions, type SignalProps, type SmithersAlertLabels, type SmithersAlertPolicy, type SmithersAlertPolicyDefaults, type SmithersAlertPolicyRule, type SmithersAlertReaction, type SmithersAlertReactionKind, type SmithersAlertReactionRef, type SmithersAlertSeverity, type SmithersCtx, type SmithersError, type SmithersErrorCode, type SmithersEvent, type SmithersLogFormat, type SmithersObservabilityOptions, type SmithersObservabilityService, type SmithersWorkflow, type SmithersWorkflowOptions, type TaskDescriptor, type TaskMemoryConfig, type TaskProps, type TimeTravelOptions, type TimeTravelResult, type TimerProps, type TryCatchFinallyProps, type WaitForEventProps, type WorkingMemoryConfig, type WorkspaceAddOptions, type WorkspaceInfo, type WorkspaceResult, type XmlElement, type XmlNode, type XmlText, bash, createExternalSmithers, createSmithers, defineTool, edit, getDefinedToolMetadata, grep, mdxPlugin, read, tools, write };
411
+ export { type AgentCapabilityRegistry, type AgentLike, type AgentToolDescriptor, type AggregateOptions, type AggregateScore, type AnthropicAgentOptions, type ApprovalAutoApprove, type ApprovalDecision, type ApprovalMode, type ApprovalOption, type ApprovalProps, type ApprovalRanking, type ApprovalRequest, type ApprovalSelection, type ColumnDef, type ConnectRequest, type ContinueAsNewProps, type CreateScorerConfig, type CreateSmithersApi, type DepsSpec, type EventFrame, type ExternalSmithersConfig, type GatewayAuthConfig, type GatewayDefaults, type GatewayOptions, type GatewayTokenGrant, type GraphSnapshot, type HelloResponse, type HermesAgentOptions, type HostContainer, type HostNodeJson, type InferDeps, type InferOutputEntry, type InferRow, type JjRevertResult, type KanbanProps, type KnownSmithersErrorCode, type LlmJudgeConfig, type MemoryFact, type MemoryLayerConfig, type MemoryMessage, type MemoryNamespace, type MemoryNamespaceKind, type MemoryProcessor, type MemoryProcessorConfig, type MemoryServiceApi, type MemoryStore, type MemoryThread, type MessageHistoryConfig, type OpenAIAgentOptions, type OpenApiAuth, type OpenApiSpec, type OpenApiToolsOptions, type OpenCodeAgentOptions, type OutputAccessor, type OutputKey, type OutputTarget, type PiAgentOptions, type PiExtensionUiRequest, type PiExtensionUiResponse, type PollerProps, type RequestFrame, type ResolvedSmithersObservabilityOptions, type ResponseFrame, type RevertOptions, type RevertResult, type RunJjOptions, type RunJjResult, type RunOptions, type RunResult, type RunStatus, type SagaProps, type SagaStepDef, type SagaStepProps, type SamplingConfig, type SandboxProps, type SandboxRuntime, type SandboxVolumeMount, type SandboxWorkspaceSpec, type SchemaRegistryEntry, type ScoreResult, type ScoreRow, type Scorer, type ScorerBinding, type ScorerContext, type ScorerFn, type ScorerInput, type ScorersMap, type SemanticRecallConfig, type SerializedCtx, type ServeOptions, type ServerOptions, type SignalProps, type SmithersAlertLabels, type SmithersAlertPolicy, type SmithersAlertPolicyDefaults, type SmithersAlertPolicyRule, type SmithersAlertReaction, type SmithersAlertReactionKind, type SmithersAlertReactionRef, type SmithersAlertSeverity, type SmithersCtx, type SmithersError, type SmithersErrorCode, type SmithersEvent, type SmithersLogFormat, type SmithersObservabilityOptions, type SmithersObservabilityService, type SmithersWorkflow, type SmithersWorkflowOptions, type TaskDescriptor, type TaskMemoryConfig, type TaskProps, type TimeTravelOptions, type TimeTravelResult, type TimerProps, type TryCatchFinallyProps, type WaitForEventProps, type WorkingMemoryConfig, type WorkspaceAddOptions, type WorkspaceInfo, type WorkspaceResult, type XmlElement, type XmlNode, type XmlText, bash, createExternalSmithers, createSmithers, defineTool, edit, getDefinedToolMetadata, grep, mdxPlugin, read, tools, write };
package/src/index.js CHANGED
@@ -68,6 +68,11 @@
68
68
  * @template [TOOLS=import("ai").ToolSet]
69
69
  * @typedef {import("@smithers-orchestrator/agents").OpenAIAgentOptions<CALL_OPTIONS, TOOLS>} OpenAIAgentOptions
70
70
  */
71
+ /**
72
+ * @template [CALL_OPTIONS=never]
73
+ * @template [TOOLS=import("ai").ToolSet]
74
+ * @typedef {import("@smithers-orchestrator/agents").HermesAgentOptions<CALL_OPTIONS, TOOLS>} HermesAgentOptions
75
+ */
71
76
  /** @typedef {import("@smithers-orchestrator/openapi").OpenApiAuth} OpenApiAuth */
72
77
  /** @typedef {import("@smithers-orchestrator/openapi").OpenApiSpec} OpenApiSpec */
73
78
  /** @typedef {import("@smithers-orchestrator/openapi").OpenApiToolsOptions} OpenApiToolsOptions */
@@ -166,7 +171,7 @@ export { knownSmithersErrorCodes } from "@smithers-orchestrator/errors/knownSmit
166
171
  // Components
167
172
  export { Approval, ApprovalGate, Aspects, Branch, CheckSuite, ClassifyAndRoute, ContentPipeline, ContinueAsNew, Debate, DecisionTable, DriftDetector, EscalationChain, GatherAndSynthesize, HumanTask, Kanban, Loop, MergeQueue, Optimizer, Panel, Parallel, Poller, Ralph, ReviewLoop, Runbook, Saga, Sandbox, ScanFixVerify, Sequence, Signal, Subflow, SuperSmithers, Supervisor, Task, Timer, TryCatchFinally, WaitForEvent, Workflow, Worktree, approvalDecisionSchema, approvalRankingSchema, approvalSelectionSchema, continueAsNew, } from "@smithers-orchestrator/components";
168
173
  // Agents
169
- export { AnthropicAgent, OpenAIAgent, AmpAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, GeminiAgent, PiAgent, KimiAgent, ForgeAgent, OpenCodeAgent, } from "@smithers-orchestrator/agents";
174
+ export { AnthropicAgent, OpenAIAgent, HermesAgent, AmpAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, GeminiAgent, PiAgent, KimiAgent, ForgeAgent, OpenCodeAgent, } from "@smithers-orchestrator/agents";
170
175
  // VCS
171
176
  export { runJj, getJjPointer, revertToJjPointer, isJjRepo, workspaceAdd, workspaceList, workspaceClose, } from "@smithers-orchestrator/vcs/jj";
172
177
  // Core API
package/src/tools/bash.js CHANGED
@@ -100,29 +100,36 @@ function validateBashInvocation(cmd, args, opts, ctx) {
100
100
  }
101
101
  }
102
102
 
103
+ function tokenExecutableName(token) {
104
+ const stripped = token.split(/[/\\]/).pop() ?? token;
105
+ return stripped;
106
+ }
107
+
103
108
  function assertNetworkAllowed(cmd, args, allowNetwork) {
104
109
  if (allowNetwork) {
105
110
  return;
106
111
  }
107
- const hay = [cmd, ...(args ?? [])].join(" ");
108
- const networkCommands = [
109
- "curl",
110
- "wget",
111
- "http://",
112
- "https://",
113
- "npm",
114
- "bun",
115
- "pip",
116
- ];
117
- if (networkCommands.some((fragment) => hay.includes(fragment))) {
112
+ const tokens = [cmd, ...(args ?? [])].flatMap((part) =>
113
+ String(part).split(/\s+/).filter(Boolean),
114
+ );
115
+ const executables = new Set(tokens.map(tokenExecutableName));
116
+ const networkExecutables = ["curl", "wget", "npm", "bun", "pip"];
117
+ const hasNetworkExecutable = networkExecutables.some((name) =>
118
+ executables.has(name),
119
+ );
120
+ const urlSchemes = ["http://", "https://"];
121
+ const hasUrlToken = tokens.some((token) =>
122
+ urlSchemes.some((scheme) => token.startsWith(scheme)),
123
+ );
124
+ if (hasNetworkExecutable || hasUrlToken) {
118
125
  throw new SmithersError(
119
126
  "TOOL_NETWORK_DISABLED",
120
127
  "Network access is disabled for bash tool",
121
128
  );
122
129
  }
123
- if (hay.includes("git")) {
124
- const gitRemoteOps = ["push", "pull", "fetch", "clone", "remote"];
125
- if (gitRemoteOps.some((op) => hay.includes(op))) {
130
+ if (executables.has("git")) {
131
+ const gitRemoteOps = new Set(["push", "pull", "fetch", "clone", "remote"]);
132
+ if (tokens.some((token) => gitRemoteOps.has(token))) {
126
133
  throw new SmithersError(
127
134
  "TOOL_GIT_REMOTE_DISABLED",
128
135
  "Git remote operations are disabled for bash tool",
@@ -27,12 +27,25 @@ export function sha256Hex(value) {
27
27
  return createHash("sha256").update(value).digest("hex");
28
28
  }
29
29
 
30
+ function utf8BoundaryLength(buf, byteLength) {
31
+ let end = Math.min(byteLength, buf.length);
32
+ if (end >= buf.length) {
33
+ return buf.length;
34
+ }
35
+ // If the cut lands on a continuation byte, back up to the lead byte of the
36
+ // partial sequence so we never decode an incomplete codepoint.
37
+ while (end > 0 && (buf[end] & 0xc0) === 0x80) {
38
+ end -= 1;
39
+ }
40
+ return end;
41
+ }
42
+
30
43
  export function truncateToBytes(text, maxBytes) {
31
44
  const buf = Buffer.from(text, "utf8");
32
45
  if (buf.length <= maxBytes) {
33
46
  return text;
34
47
  }
35
- return buf.subarray(0, maxBytes).toString("utf8");
48
+ return buf.subarray(0, utf8BoundaryLength(buf, maxBytes)).toString("utf8");
36
49
  }
37
50
 
38
51
  export async function resolveToolPath(rootDir, inputPath) {
@@ -72,8 +85,11 @@ function appendLimited(chunks, state, chunk, maxBytes) {
72
85
  state.storedBytes += buffer.length;
73
86
  return;
74
87
  }
75
- chunks.push(buffer.subarray(0, remaining));
76
- state.storedBytes += remaining;
88
+ const accepted = utf8BoundaryLength(buffer, remaining);
89
+ if (accepted > 0) {
90
+ chunks.push(buffer.subarray(0, accepted));
91
+ state.storedBytes += accepted;
92
+ }
77
93
  state.truncated = true;
78
94
  }
79
95
 
@@ -91,7 +107,12 @@ export function captureProcess(
91
107
  return new Promise((resolve, reject) => {
92
108
  const stdoutChunks = [];
93
109
  const stderrChunks = [];
94
- const state = {
110
+ const stdoutState = {
111
+ storedBytes: 0,
112
+ totalBytes: 0,
113
+ truncated: false,
114
+ };
115
+ const stderrState = {
95
116
  storedBytes: 0,
96
117
  totalBytes: 0,
97
118
  truncated: false,
@@ -149,10 +170,10 @@ export function captureProcess(
149
170
  }
150
171
 
151
172
  child.stdout.on("data", (chunk) => {
152
- appendLimited(stdoutChunks, state, chunk, maxOutputBytes);
173
+ appendLimited(stdoutChunks, stdoutState, chunk, maxOutputBytes);
153
174
  });
154
175
  child.stderr.on("data", (chunk) => {
155
- appendLimited(stderrChunks, state, chunk, maxOutputBytes);
176
+ appendLimited(stderrChunks, stderrState, chunk, maxOutputBytes);
156
177
  });
157
178
  child.on("error", (error) => {
158
179
  finish(() =>
@@ -167,7 +188,7 @@ export function captureProcess(
167
188
  });
168
189
  child.on("close", (exitCode, signal) => {
169
190
  finish(() => {
170
- resolve({ exitCode: exitCode ?? (signal ? 1 : 0), signal, stdout: Buffer.concat(stdoutChunks).toString("utf8"), stderr: Buffer.concat(stderrChunks).toString("utf8"), truncated: state.truncated, totalBytes: state.totalBytes });
191
+ resolve({ exitCode: exitCode ?? (signal ? 1 : 0), signal, stdout: Buffer.concat(stdoutChunks).toString("utf8"), stderr: Buffer.concat(stderrChunks).toString("utf8"), truncated: stdoutState.truncated || stderrState.truncated, totalBytes: stdoutState.totalBytes + stderrState.totalBytes });
171
192
  });
172
193
  });
173
194
  });