@stigmer/sdk 2.0.1 → 3.0.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/README.md CHANGED
@@ -182,11 +182,66 @@ interface StigmerConfig {
182
182
  getAccessToken?: () => string | null | Promise<string | null>; // Dynamic token provider
183
183
  onUnauthenticated?: () => void; // Called once on UNAUTHENTICATED (code 16)
184
184
  transport?: "grpc-web" | "connect"; // Default: "grpc-web"
185
+ executionTarget?: "local" | "cloud"; // Default execution target — see "Local Execution"
185
186
  }
186
187
  ```
187
188
 
188
189
  Exactly one of `apiKey` or `getAccessToken` must be provided.
189
190
 
191
+ ## Local Execution
192
+
193
+ Agent and workflow execution runs in the cloud by default — the Stigmer server provisions a sandbox with a runner. To run execution on the client (a desktop app, CLI, or self-hosted deployment), set the execution target.
194
+
195
+ ### Selecting the target
196
+
197
+ ```typescript
198
+ // App-level default for every session and workflow execution
199
+ const stigmer = new Stigmer({
200
+ baseUrl: "https://api.stigmer.ai",
201
+ getAccessToken: () => authStore.getToken(),
202
+ executionTarget: "local", // "local" | "cloud"; omit to let the server decide
203
+ });
204
+
205
+ // A per-call executionTarget takes precedence over the app-level default
206
+ const session = await stigmer.session.create({
207
+ name: "review",
208
+ org: "my-org",
209
+ agentInstanceId: "inst-abc",
210
+ executionTarget: "cloud",
211
+ });
212
+ ```
213
+
214
+ `workflowExecution.create()` accepts the same per-call `executionTarget`.
215
+
216
+ ### `RunnerAdapter`
217
+
218
+ For local execution, the client owns the runner lifecycle. `@stigmer/sdk` exports the `RunnerAdapter` type so non-React hosts (Node scripts, custom frameworks) can implement it:
219
+
220
+ ```typescript
221
+ import type { RunnerAdapter } from "@stigmer/sdk";
222
+
223
+ const adapter: RunnerAdapter = {
224
+ onSessionOpened: async (sessionId) => { /* start a worker for this session */ },
225
+ onSessionClosed: async (sessionId) => { /* stop it */ },
226
+ onWorkflowExecutionCreated: async (executionId) => { /* start a worker */ },
227
+ onWorkflowExecutionTerminated: async (executionId) => { /* stop it */ },
228
+ };
229
+ ```
230
+
231
+ If your runner backend already exposes `addSession` / `removeSession` / `addWorkflowExecution` / `removeWorkflowExecution` (a `RunnerWorkerHost`) — the in-process `createStigmerRunnerManager`, the desktop's embedded-runner context, or your own API — skip the hand-wiring and let `createRunnerAdapter` build the adapter:
232
+
233
+ ```typescript
234
+ import { createRunnerAdapter } from "@stigmer/sdk";
235
+
236
+ const adapter = createRunnerAdapter(myRunnerHost);
237
+ ```
238
+
239
+ A Session has no terminal phase, so its worker is tied to whether the session is **open**: attach on `onSessionOpened`, detach on `onSessionClosed` (and keep both idempotent — `onSessionOpened` may fire again on re-open). A Workflow Execution runs to a terminal phase, so its worker is tied to create/terminate.
240
+
241
+ The SDK does not invoke these methods on its own in a non-React host — you wire the adapter to your own open/close and create/terminate code paths. In React apps, `@stigmer/react` does this wiring automatically: pass `executionTarget` and `runnerAdapter` to `StigmerProvider` and the SDK hooks invoke the adapter at the right lifecycle points.
242
+
243
+ See the [`@stigmer/react` local execution docs](../react/README.md#local-execution) and the [runner embedding guide](https://stigmer.ai/docs/guides/runners/embedding) for the full desktop (local) and web (cloud) walkthrough.
244
+
190
245
  ## Code Generation
191
246
 
192
247
  The resource clients in `src/gen/` are generated from protobuf service schemas. To regenerate after proto changes:
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runner-adapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-adapter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/runner-adapter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,88 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { createRunnerAdapter, } from "../runner-adapter";
3
+ function createMockHost() {
4
+ return {
5
+ addSession: vi.fn().mockResolvedValue(undefined),
6
+ removeSession: vi.fn().mockResolvedValue(undefined),
7
+ addWorkflowExecution: vi.fn().mockResolvedValue(undefined),
8
+ removeWorkflowExecution: vi.fn().mockResolvedValue(undefined),
9
+ };
10
+ }
11
+ describe("createRunnerAdapter", () => {
12
+ it("returns an adapter with all four lifecycle methods", () => {
13
+ const adapter = createRunnerAdapter(createMockHost());
14
+ expect(adapter.onSessionOpened).toBeInstanceOf(Function);
15
+ expect(adapter.onSessionClosed).toBeInstanceOf(Function);
16
+ expect(adapter.onWorkflowExecutionCreated).toBeInstanceOf(Function);
17
+ expect(adapter.onWorkflowExecutionTerminated).toBeInstanceOf(Function);
18
+ });
19
+ it("maps onSessionOpened to host.addSession with the session id", async () => {
20
+ const host = createMockHost();
21
+ const adapter = createRunnerAdapter(host);
22
+ await adapter.onSessionOpened("ses-123");
23
+ expect(host.addSession).toHaveBeenCalledTimes(1);
24
+ expect(host.addSession).toHaveBeenCalledWith("ses-123");
25
+ // The asymmetric mapping is the footgun this factory exists to prevent:
26
+ // closing/removing must not fire on open.
27
+ expect(host.removeSession).not.toHaveBeenCalled();
28
+ });
29
+ it("maps onSessionClosed to host.removeSession with the session id", async () => {
30
+ const host = createMockHost();
31
+ const adapter = createRunnerAdapter(host);
32
+ await adapter.onSessionClosed("ses-123");
33
+ expect(host.removeSession).toHaveBeenCalledTimes(1);
34
+ expect(host.removeSession).toHaveBeenCalledWith("ses-123");
35
+ expect(host.addSession).not.toHaveBeenCalled();
36
+ });
37
+ it("maps onWorkflowExecutionCreated to host.addWorkflowExecution with the execution id", async () => {
38
+ const host = createMockHost();
39
+ const adapter = createRunnerAdapter(host);
40
+ await adapter.onWorkflowExecutionCreated("wfexec-456");
41
+ expect(host.addWorkflowExecution).toHaveBeenCalledTimes(1);
42
+ expect(host.addWorkflowExecution).toHaveBeenCalledWith("wfexec-456");
43
+ expect(host.removeWorkflowExecution).not.toHaveBeenCalled();
44
+ });
45
+ it("maps onWorkflowExecutionTerminated to host.removeWorkflowExecution with the execution id", async () => {
46
+ const host = createMockHost();
47
+ const adapter = createRunnerAdapter(host);
48
+ await adapter.onWorkflowExecutionTerminated("wfexec-456");
49
+ expect(host.removeWorkflowExecution).toHaveBeenCalledTimes(1);
50
+ expect(host.removeWorkflowExecution).toHaveBeenCalledWith("wfexec-456");
51
+ expect(host.addWorkflowExecution).not.toHaveBeenCalled();
52
+ });
53
+ it("resolves to undefined regardless of the host's return value", async () => {
54
+ // The host's add methods return a task queue string; the adapter contract
55
+ // is Promise<void>, so the value must be swallowed.
56
+ const host = createMockHost();
57
+ host.addSession.mockResolvedValue("session:ses-123");
58
+ host.addWorkflowExecution.mockResolvedValue("wfexec:wfexec-456");
59
+ const adapter = createRunnerAdapter(host);
60
+ await expect(adapter.onSessionOpened("ses-123")).resolves.toBeUndefined();
61
+ await expect(adapter.onWorkflowExecutionCreated("wfexec-456")).resolves.toBeUndefined();
62
+ });
63
+ it("awaits the host: it does not resolve before the host settles", async () => {
64
+ let release;
65
+ const gate = new Promise((resolve) => {
66
+ release = resolve;
67
+ });
68
+ const host = createMockHost();
69
+ host.addSession.mockReturnValue(gate);
70
+ const adapter = createRunnerAdapter(host);
71
+ let settled = false;
72
+ const pending = adapter.onSessionOpened("ses-123").then(() => {
73
+ settled = true;
74
+ });
75
+ await Promise.resolve();
76
+ expect(settled).toBe(false);
77
+ release();
78
+ await pending;
79
+ expect(settled).toBe(true);
80
+ });
81
+ it("propagates a host rejection", async () => {
82
+ const host = createMockHost();
83
+ host.removeSession.mockRejectedValue(new Error("worker teardown failed"));
84
+ const adapter = createRunnerAdapter(host);
85
+ await expect(adapter.onSessionClosed("ses-123")).rejects.toThrow("worker teardown failed");
86
+ });
87
+ });
88
+ //# sourceMappingURL=runner-adapter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-adapter.test.js","sourceRoot":"","sources":["../../src/__tests__/runner-adapter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-view.fixtures.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.fixtures.test.d.ts","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.fixtures.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ // Validates the tool-view layer against the shared cross-language contract in
2
+ // test/fixtures/tool-view/. The Go CLI runs the same fixtures, so the two
3
+ // surfaces cannot drift in classification or result interpretation.
4
+ import { readFileSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import { dirname, resolve } from "node:path";
7
+ import { describe, it, expect } from "vitest";
8
+ import { create } from "@bufbuild/protobuf";
9
+ import { ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
10
+ import { ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
11
+ import { ToolKind, resolveToolKindByName, normalizeToolResult } from "../tool-view";
12
+ const here = dirname(fileURLToPath(import.meta.url));
13
+ // sdk/typescript/src/execution/__tests__ -> repo root is five levels up.
14
+ const fixtureDir = resolve(here, "../../../../../test/fixtures/tool-view");
15
+ function loadFixture(name) {
16
+ return JSON.parse(readFileSync(resolve(fixtureDir, name), "utf8"));
17
+ }
18
+ describe("classification fixtures", () => {
19
+ const { cases } = loadFixture("classification.json");
20
+ it("loads the fixture", () => {
21
+ expect(cases.length).toBeGreaterThan(0);
22
+ });
23
+ for (const c of cases) {
24
+ const expected = ToolKind[c.toolKind.replace(/^TOOL_KIND_/, "")];
25
+ it(`classifies ${c.name || "(empty)"}${c.mcpServerSlug ? ` @${c.mcpServerSlug}` : ""}`, () => {
26
+ expect(resolveToolKindByName(c.name, c.mcpServerSlug)).toBe(expected);
27
+ });
28
+ }
29
+ });
30
+ describe("result-view fixtures", () => {
31
+ const { cases } = loadFixture("result-views.json");
32
+ it("loads the fixture", () => {
33
+ expect(cases.length).toBeGreaterThan(0);
34
+ });
35
+ for (const c of cases) {
36
+ it(`normalizes ${c.name} -> ${c.expected.type}`, () => {
37
+ const status = c.status === "TOOL_CALL_FAILED"
38
+ ? ToolCallStatus.TOOL_CALL_FAILED
39
+ : ToolCallStatus.TOOL_CALL_COMPLETED;
40
+ const toolCall = create(ToolCallSchema, {
41
+ id: c.name,
42
+ name: c.toolName,
43
+ mcpServerSlug: c.mcpServerSlug,
44
+ result: c.result,
45
+ error: c.error ?? "",
46
+ status,
47
+ args: c.args,
48
+ });
49
+ const view = normalizeToolResult(toolCall);
50
+ expect(view.type).toBe(c.expected.type);
51
+ // Only deterministic facts are part of the shared contract.
52
+ if (c.expected.path !== undefined && view.type === "diff") {
53
+ expect(view.path).toBe(c.expected.path);
54
+ }
55
+ if (c.expected.path !== undefined && view.type === "file") {
56
+ expect(view.path).toBe(c.expected.path);
57
+ }
58
+ if (c.expected.exitCode !== undefined && view.type === "terminal") {
59
+ expect(view.exitCode).toBe(c.expected.exitCode);
60
+ }
61
+ if (c.expected.count !== undefined && view.type === "search") {
62
+ expect(view.count).toBe(c.expected.count);
63
+ }
64
+ if (c.expected.count !== undefined && view.type === "list") {
65
+ expect(view.count).toBe(c.expected.count);
66
+ }
67
+ if (c.expected.mcpServerSlug !== undefined && view.type === "contentBlocks") {
68
+ expect(view.mcpServerSlug).toBe(c.expected.mcpServerSlug);
69
+ }
70
+ if (c.expected.linesAdded !== undefined && view.type === "diff") {
71
+ expect(view.linesAdded).toBe(c.expected.linesAdded);
72
+ }
73
+ if (c.expected.linesRemoved !== undefined && view.type === "diff") {
74
+ expect(view.linesRemoved).toBe(c.expected.linesRemoved);
75
+ }
76
+ });
77
+ }
78
+ });
79
+ describe("resolveToolKind wire field precedence", () => {
80
+ it("prefers the wire tool_kind over the name fallback", () => {
81
+ const toolCall = create(ToolCallSchema, {
82
+ name: "some_unknown_name",
83
+ toolKind: ToolKind.SHELL,
84
+ });
85
+ // resolveToolKind is exercised indirectly via normalizeToolResult routing.
86
+ const view = normalizeToolResult(create(ToolCallSchema, {
87
+ name: "some_unknown_name",
88
+ toolKind: ToolKind.SHELL,
89
+ result: "done\n[Command succeeded]",
90
+ status: ToolCallStatus.TOOL_CALL_COMPLETED,
91
+ }));
92
+ expect(view.type).toBe("terminal");
93
+ expect(toolCall.toolKind).toBe(ToolKind.SHELL);
94
+ });
95
+ it("degrades unknown results to json or text", () => {
96
+ const jsonView = normalizeToolResult(create(ToolCallSchema, { name: "mystery", result: '{"a":1}', status: ToolCallStatus.TOOL_CALL_COMPLETED }));
97
+ expect(jsonView.type).toBe("json");
98
+ const textView = normalizeToolResult(create(ToolCallSchema, { name: "mystery", result: "plain", status: ToolCallStatus.TOOL_CALL_COMPLETED }));
99
+ expect(textView.type).toBe("text");
100
+ });
101
+ });
102
+ //# sourceMappingURL=tool-view.fixtures.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.fixtures.test.js","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.fixtures.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { ToolKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
2
+ import type { ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
3
+ export { ToolKind };
4
+ /** A single match in a search/grep result. */
5
+ export interface ToolSearchMatch {
6
+ /** File path the match was found in, when the result format provides it. */
7
+ readonly file?: string;
8
+ /** 1-based line number, when available. */
9
+ readonly line?: number;
10
+ /** The matched text. */
11
+ readonly text: string;
12
+ }
13
+ /** An MCP content block (the `content: [...]` array MCP servers return). */
14
+ export interface ToolContentBlock {
15
+ /** Block type, e.g. "text". */
16
+ readonly type: string;
17
+ /** Text payload, when the block is textual. */
18
+ readonly text?: string;
19
+ }
20
+ /**
21
+ * A typed projection of a tool call's result, discriminated by `type`.
22
+ *
23
+ * Presentation layers switch on `type` and never re-parse the raw string. The
24
+ * `json` and `text` variants are the guaranteed graceful-degradation fallbacks:
25
+ * any unrecognized or truncated payload lands there, so this is never worse than
26
+ * showing the raw result.
27
+ */
28
+ export type ToolResultView = {
29
+ readonly type: "diff";
30
+ readonly path: string;
31
+ readonly oldText?: string;
32
+ readonly newText?: string;
33
+ readonly linesAdded?: number;
34
+ readonly linesRemoved?: number;
35
+ readonly unifiedDiff?: string;
36
+ } | {
37
+ readonly type: "file";
38
+ readonly path: string;
39
+ readonly content: string;
40
+ readonly language?: string;
41
+ readonly truncated: boolean;
42
+ } | {
43
+ readonly type: "terminal";
44
+ readonly stdout: string;
45
+ readonly stderr: string;
46
+ readonly exitCode?: number;
47
+ } | {
48
+ readonly type: "search";
49
+ readonly matches: readonly ToolSearchMatch[];
50
+ readonly count: number;
51
+ } | {
52
+ readonly type: "list";
53
+ readonly entries: readonly string[];
54
+ readonly count: number;
55
+ } | {
56
+ readonly type: "contentBlocks";
57
+ readonly blocks: readonly ToolContentBlock[];
58
+ readonly mcpServerSlug: string;
59
+ } | {
60
+ readonly type: "text";
61
+ readonly text: string;
62
+ } | {
63
+ readonly type: "json";
64
+ readonly value: unknown;
65
+ } | {
66
+ readonly type: "error";
67
+ readonly message: string;
68
+ } | {
69
+ readonly type: "empty";
70
+ };
71
+ /**
72
+ * Resolves the harness-agnostic kind of a tool call.
73
+ *
74
+ * Prefers the wire `tool_kind` set by the runner; falls back to a name lookup
75
+ * for legacy executions where it is UNSPECIFIED. An unknown name with a
76
+ * non-empty mcpServerSlug is an MCP tool.
77
+ */
78
+ export declare function resolveToolKind(toolCall: Pick<ToolCall, "name" | "mcpServerSlug" | "toolKind">): ToolKind;
79
+ /** Name-based classification used as the legacy fallback for resolveToolKind. */
80
+ export declare function resolveToolKindByName(name: string, mcpServerSlug?: string): ToolKind;
81
+ /**
82
+ * Normalizes a tool call into a typed ToolResultView for rendering.
83
+ *
84
+ * A FAILED tool with an error always yields an `error` view. Otherwise the kind
85
+ * drives interpretation, and anything unrecognized degrades to `json`/`text`.
86
+ */
87
+ export declare function normalizeToolResult(toolCall: ToolCall): ToolResultView;
88
+ //# sourceMappingURL=tool-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.d.ts","sourceRoot":"","sources":["../../src/execution/tool-view.ts"],"names":[],"mappings":"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"}