@theway-ai/sdk 1.1.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.
Files changed (59) hide show
  1. package/README.md +102 -0
  2. package/dist/client.d.ts +138 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +390 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/generated/commands.d.ts +160 -0
  7. package/dist/generated/commands.d.ts.map +1 -0
  8. package/dist/generated/commands.js +449 -0
  9. package/dist/generated/commands.js.map +1 -0
  10. package/dist/generated/events.d.ts +144 -0
  11. package/dist/generated/events.d.ts.map +1 -0
  12. package/dist/generated/events.js +1044 -0
  13. package/dist/generated/events.js.map +1 -0
  14. package/dist/generated/extensions.d.ts +184 -0
  15. package/dist/generated/extensions.d.ts.map +1 -0
  16. package/dist/generated/extensions.js +1309 -0
  17. package/dist/generated/extensions.js.map +1 -0
  18. package/dist/generated/graph_engine.d.ts +373 -0
  19. package/dist/generated/graph_engine.d.ts.map +1 -0
  20. package/dist/generated/graph_engine.js +2422 -0
  21. package/dist/generated/graph_engine.js.map +1 -0
  22. package/dist/generated/health.d.ts +83 -0
  23. package/dist/generated/health.d.ts.map +1 -0
  24. package/dist/generated/health.js +179 -0
  25. package/dist/generated/health.js.map +1 -0
  26. package/dist/generated/session.d.ts +490 -0
  27. package/dist/generated/session.d.ts.map +1 -0
  28. package/dist/generated/session.js +3809 -0
  29. package/dist/generated/session.js.map +1 -0
  30. package/dist/generated/settings.d.ts +175 -0
  31. package/dist/generated/settings.d.ts.map +1 -0
  32. package/dist/generated/settings.js +304 -0
  33. package/dist/generated/settings.js.map +1 -0
  34. package/dist/generated/state.d.ts +291 -0
  35. package/dist/generated/state.d.ts.map +1 -0
  36. package/dist/generated/state.js +1382 -0
  37. package/dist/generated/state.js.map +1 -0
  38. package/dist/generated/tools.d.ts +413 -0
  39. package/dist/generated/tools.d.ts.map +1 -0
  40. package/dist/generated/tools.js +2487 -0
  41. package/dist/generated/tools.js.map +1 -0
  42. package/dist/health.d.ts +20 -0
  43. package/dist/health.d.ts.map +1 -0
  44. package/dist/health.js +62 -0
  45. package/dist/health.js.map +1 -0
  46. package/dist/index.d.ts +15 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +21 -0
  49. package/dist/index.js.map +1 -0
  50. package/package.json +46 -0
  51. package/proto/commands.proto +57 -0
  52. package/proto/events.proto +80 -0
  53. package/proto/extensions.proto +99 -0
  54. package/proto/graph_engine.proto +193 -0
  55. package/proto/health.proto +26 -0
  56. package/proto/session.proto +299 -0
  57. package/proto/settings.proto +73 -0
  58. package/proto/state.proto +129 -0
  59. package/proto/tools.proto +238 -0
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @theway-ai/sdk
2
+
3
+ Typed TypeScript SDK for the **theway** gRPC daemon (`theway --grpc` loopback server).
4
+ Generated from the five domain protos
5
+ ([`proto/commands.proto`](proto/commands.proto),
6
+ [`proto/session.proto`](proto/session.proto),
7
+ [`proto/graph_engine.proto`](proto/graph_engine.proto),
8
+ [`proto/events.proto`](proto/events.proto),
9
+ [`proto/settings.proto`](proto/settings.proto)) + [`proto/health.proto`](proto/health.proto)
10
+ via ts-proto + `@grpc/grpc-js` — **no runtime proto loading**, no path magic.
11
+
12
+ `ThewayGrpcClient` routes each RPC to its domain service — `CommandService`,
13
+ `SessionService`, `SettingsService`, `GraphEngineService`, and `EventService` — while
14
+ `HealthClient` covers the standard `grpc.health.v1.Health` service.
15
+
16
+ Published as a public package on the official npm registry (`https://registry.npmjs.org/`).
17
+
18
+ ## Install
19
+
20
+ ```sh
21
+ npm install @theway-ai/sdk
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```ts
27
+ import { ThewayGrpcClient, HealthClient } from '@theway-ai/sdk';
28
+
29
+ const client = new ThewayGrpcClient('http://127.0.0.1:34567');
30
+
31
+ // Full session state (typed SessionState)
32
+ const state = await client.getState();
33
+
34
+ // Commands — throw when the server replies accepted: false
35
+ await client.prompt('hello');
36
+ await client.setModelSpec('anthropic:claude-sonnet-4-5');
37
+ await client.abort();
38
+ await client.resolveControlPlane(true);
39
+
40
+ // Graph / session control
41
+ const { resetNodeIds } = await client.graphRetry('dag-1');
42
+ const sessions = await client.listSessions();
43
+
44
+ // Daemon settings (issue #72) — partial update: only set fields are applied
45
+ const config = await client.getConfig();
46
+ await client.setConfig({ triggerPollSecs: 30, skillsDirs: ['/extra/skills'] });
47
+
48
+ // Snapshot + event stream (StreamFrame oneof: payload.$case === 'snapshot' | 'event')
49
+ await client.streamEvents((frame) => {
50
+ if (frame.payload?.$case === 'snapshot') {
51
+ console.log(frame.payload.snapshot.feedLines?.length);
52
+ }
53
+ }, abortSignal);
54
+
55
+ // Standard gRPC health probe (grpc.health.v1)
56
+ const health = new HealthClient('127.0.0.1:34567');
57
+ const serving = await health.check('');
58
+
59
+ client.close();
60
+ ```
61
+
62
+ ## Regenerating
63
+
64
+ `crates/theway-transport/proto/` at the repo root is the single source of truth; `proto/*.proto` in this package is a mirror and
65
+ `src/generated/` is regenerated from it. Sync and regenerate with:
66
+
67
+ ```sh
68
+ cd ../.. # repo root
69
+ make hooks # once per clone: enable the pre-commit hook
70
+ make sdk-sync # or: bash scripts/sdk-sync.sh
71
+ ```
72
+
73
+ The enabled pre-commit hook ([`.githooks/pre-commit`](../../.githooks/pre-commit)) runs the sync automatically
74
+ whenever `crates/theway-transport/proto/` changes and stages the regenerated files into the same commit, so the checked-in proto and
75
+ generated client never drift.
76
+
77
+ Manual generation without the Makefile:
78
+
79
+ ```sh
80
+ npm install
81
+ npm run gen # protoc (grpc-tools) + ts-proto → src/generated/
82
+ ```
83
+
84
+ ## Publishing
85
+
86
+ Publishing to the official npm registry is manual ([`scripts/sdk-publish.sh`](../../scripts/sdk-publish.sh)):
87
+
88
+ ```sh
89
+ cd ../..
90
+ make sdk-publish BUMP=minor ISSUE="#62"
91
+ # 或: bash scripts/sdk-publish.sh minor "#62"
92
+ ```
93
+
94
+ The script verifies the tree is clean and in sync, checks the active npm identity against the official
95
+ registry, bumps the version, publishes with public access, and commits the version bump. Run
96
+ `npm login --registry=https://registry.npmjs.org/` before invoking it; the account must satisfy npm's
97
+ two-factor authentication requirements for publishing.
98
+
99
+ ## Versioning
100
+
101
+ The SDK version tracks the theway release that the proto contract was cut from
102
+ (theway v1.0.0 → SDK 1.0.0). Bump together with contract changes.
@@ -0,0 +1,138 @@
1
+ import * as grpc from '@grpc/grpc-js';
2
+ import { type CommandResult, type Empty, type SendMessageRequest } from './generated/commands.js';
3
+ import { type StreamFrame } from './generated/events.js';
4
+ import { type DecideExtensionTrustRequest, type DecideExtensionTrustResponse, type ExtensionCommandOutcome, type ExtensionSnapshot, type InvokeExtensionCommandRequest, type ReloadExtensionsRequest, type ReloadExtensionsResponse } from './generated/extensions.js';
5
+ import { type GetNodeOutputRequest, type GetNodeOutputResponse, type GraphCheckpointRequest, type GraphCheckpointResponse, type GraphListResponse, type GraphRestoreResponse, type GraphRetryResponse, type GraphSkipResponse } from './generated/graph_engine.js';
6
+ import { type CreateSessionRequest, type CreateSessionResponse, type DeleteSessionRequest, type DeleteSessionResponse, type ListSessionsResponse, type RenameSessionRequest, type SessionState } from './generated/session.js';
7
+ import { type DaemonConfig } from './generated/settings.js';
8
+ import { type EditFileRequest, type EditFileResponse, type ExecCommandRequest, type FindRequest, type FindResponse, type GrepRequest, type GrepResponse, type ListDirRequest, type ListDirResponse, type MemoryForgetRequest, type MemoryForgetResponse, type MemoryListRequest, type MemoryListResponse, type MemoryReadRequest, type MemoryReadResponse, type MemorySaveRequest, type MemorySaveResponse, type ReadFileRequest, type ReadFileResponse, type SkillInstallRequest, type SkillInstallResponse, type WriteFileRequest, type WriteFileResponse } from './generated/tools.js';
9
+ import { type LoadCronJobsRequest, type LoadCronJobsResponse, type LoadDagRunsRequest, type LoadDagRunsResponse, type LoadTriggerRulesRequest, type LoadTriggerRulesResponse, type SaveCronJobsRequest, type SaveCronJobsResponse, type SaveDagRunRequest, type SaveDagRunResponse, type SaveTriggerRulesRequest, type SaveTriggerRulesResponse } from './generated/state.js';
10
+ /**
11
+ * Typed gRPC client for the `theway --grpc` loopback server
12
+ * (theway.grpc.v1.CommandService / SessionService / SettingsService /
13
+ * ExtensionService / ToolService / StorageService / GraphEngineService /
14
+ * EventService).
15
+ * Generated from the domain proto files
16
+ * and health.proto (ts-proto + @grpc/grpc-js) — no runtime proto loading.
17
+ *
18
+ * Command RPCs (SendMessage / SetModel / …) resolve the raw CommandResult;
19
+ * the convenience wrappers (`prompt`, `setModelSpec`, `abort`, …) throw when
20
+ * the server replies `accepted: false`, mirroring the caller-side contract of
21
+ * the JSON channels.
22
+ */
23
+ export declare class ThewayGrpcClient {
24
+ #private;
25
+ constructor(baseUrl: string, credentials?: grpc.ChannelCredentials);
26
+ /** `GetState` — the latest full session state. */
27
+ getState(): Promise<SessionState>;
28
+ /** `GetNodeOutput` — a DAG node's output fragment from an offset. */
29
+ getNodeOutput(request: GetNodeOutputRequest): Promise<GetNodeOutputResponse>;
30
+ /** `SendMessage` — submit a user prompt (mode=QUEUE). */
31
+ prompt(text: string, images?: SendMessageRequest['images']): Promise<void>;
32
+ /** `SendMessage` — raw request (mode=INTERRUPT supported). */
33
+ sendMessage(request: SendMessageRequest): Promise<CommandResult>;
34
+ /** `SetModel` — switch model with a composed `provider:model` spec. */
35
+ setModelSpec(spec: string): Promise<void>;
36
+ /** `SetModel` with `provider` + `model` (composed into `provider:model`). */
37
+ setModel(provider: string, model: string): Promise<void>;
38
+ /** `Cancel` — stop the in-flight turn (same as local Ctrl-C). */
39
+ abort(): Promise<void>;
40
+ /** `Approve` — resolve the pending control-plane approval (approve / reject). */
41
+ resolveControlPlane(approve: boolean): Promise<void>;
42
+ /** Structured extension catalog, redacted diagnostics and contributions. */
43
+ getExtensions(): Promise<ExtensionSnapshot>;
44
+ /** Invoke a registered extension command in either interactive or headless mode. */
45
+ invokeExtensionCommand(request: InvokeExtensionCommandRequest): Promise<ExtensionCommandOutcome>;
46
+ /** Re-discover extensions; active work may return `status=pending`. */
47
+ reloadExtensions(request?: ReloadExtensionsRequest): Promise<ReloadExtensionsResponse>;
48
+ /** Persist a project or exact-package trust decision and request reload. */
49
+ decideExtensionTrust(request: DecideExtensionTrustRequest): Promise<DecideExtensionTrustResponse>;
50
+ /** `GraphCancel` — cancel a run. */
51
+ graphCancel(runId: string): Promise<void>;
52
+ /** `GraphRetry` — re-run failed/cancelled nodes (omitted nodeId = all). */
53
+ graphRetry(runId: string, nodeId?: string): Promise<GraphRetryResponse>;
54
+ /** `GraphSkip` — skip a node (counts as success for downstream). */
55
+ graphSkip(runId: string, nodeId: string): Promise<GraphSkipResponse>;
56
+ /** `GraphNodeInterrupt` — stop the node's in-flight turn. */
57
+ graphNodeInterrupt(runId: string, nodeId: string): Promise<void>;
58
+ /** `GraphNodeSteer` — queue a steering message at the node's next turn boundary. */
59
+ graphNodeSteer(runId: string, nodeId: string, text: string): Promise<void>;
60
+ /** `GraphCheckpoint` — export run snapshots as portable JSON. */
61
+ graphCheckpoint(request?: GraphCheckpointRequest): Promise<GraphCheckpointResponse>;
62
+ /** `GraphRestore` — revive a run from a GraphCheckpoint snapshot. */
63
+ graphRestore(sessionId: string, snapshot: string): Promise<GraphRestoreResponse>;
64
+ /** `GraphList` — enumerate one session's graph runs. */
65
+ graphList(sessionId: string): Promise<GraphListResponse>;
66
+ /** `ListSessions` — all sessions (live + archived) with the current one marked. */
67
+ listSessions(): Promise<ListSessionsResponse>;
68
+ /** `CreateSession` — create a session. */
69
+ createSession(name?: string): Promise<CreateSessionResponse>;
70
+ /** `SwitchSession` — switch the live session. */
71
+ switchSession(sessionId: string): Promise<void>;
72
+ /** `RenameSession` — rename a session. */
73
+ renameSession(sessionId: string, name: string): Promise<void>;
74
+ /** `DeleteSession` — delete a session (refused while graphs are running). */
75
+ deleteSession(sessionId: string): Promise<DeleteSessionResponse>;
76
+ /** `GetConfig` — the daemon's current configuration view. */
77
+ getConfig(): Promise<DaemonConfig>;
78
+ /**
79
+ * `SetConfig` — push a partial configuration update. Absent fields keep
80
+ * the daemon's current value (repeated fields default to empty = no-op).
81
+ */
82
+ setConfig(config: Partial<DaemonConfig>): Promise<void>;
83
+ /** `Configure` — alias of `setConfig` (JSON-RPC / WS / MCP verb alignment). */
84
+ configure(config: Partial<DaemonConfig>): Promise<void>;
85
+ /** `ReadFile` — read a file with line pagination. */
86
+ toolRead(request: ReadFileRequest): Promise<ReadFileResponse>;
87
+ /** `WriteFile` — write a file. */
88
+ toolWrite(request: WriteFileRequest): Promise<WriteFileResponse>;
89
+ /** `EditFile` — search-and-replace edit. */
90
+ toolEdit(request: EditFileRequest): Promise<EditFileResponse>;
91
+ /** `ExecCommand` — streaming shell execution. */
92
+ toolExec(request: ExecCommandRequest): grpc.ClientReadableStream<import("./generated/tools.js").ExecOutputFrame>;
93
+ /** `ListDir` — list one directory level. */
94
+ toolListDir(request: ListDirRequest): Promise<ListDirResponse>;
95
+ /** `Grep` — regex content search. */
96
+ toolGrep(request: GrepRequest): Promise<GrepResponse>;
97
+ /** `Find` — filename-glob search. */
98
+ toolFind(request: FindRequest): Promise<FindResponse>;
99
+ /** `MemorySave` — save a memory entry. */
100
+ toolMemorySave(request: MemorySaveRequest): Promise<MemorySaveResponse>;
101
+ /** `MemoryList` — list memory entries. */
102
+ toolMemoryList(request: MemoryListRequest): Promise<MemoryListResponse>;
103
+ /** `MemoryRead` — read one memory entry. */
104
+ toolMemoryRead(request: MemoryReadRequest): Promise<MemoryReadResponse>;
105
+ /** `MemoryForget` — forget a memory entry. */
106
+ toolMemoryForget(request: MemoryForgetRequest): Promise<MemoryForgetResponse>;
107
+ /** `SkillInstall` — two-phase skill install. */
108
+ toolSkillInstall(request: SkillInstallRequest): Promise<SkillInstallResponse>;
109
+ /** `StorageService.ListSessions` — session list from external storage. */
110
+ stateListSessions(request: Empty): Promise<import('./generated/session.js').ListSessionsResponse>;
111
+ /** `StorageService.CreateSession` — create a session in external storage. */
112
+ stateCreateSession(request: CreateSessionRequest): Promise<CreateSessionResponse>;
113
+ /** `StorageService.RenameSession` — rename a session in external storage. */
114
+ stateRenameSession(request: RenameSessionRequest): Promise<CommandResult>;
115
+ /** `StorageService.DeleteSession` — delete a session in external storage. */
116
+ stateDeleteSession(request: DeleteSessionRequest): Promise<DeleteSessionResponse>;
117
+ /** `StorageService.SaveDagRun` — persist a DAG run. */
118
+ stateSaveDagRun(request: SaveDagRunRequest): Promise<SaveDagRunResponse>;
119
+ /** `StorageService.LoadDagRuns` — load persisted DAG runs. */
120
+ stateLoadDagRuns(request: LoadDagRunsRequest): Promise<LoadDagRunsResponse>;
121
+ /** `StorageService.SaveTriggerRules` — persist trigger rules. */
122
+ stateSaveTriggerRules(request: SaveTriggerRulesRequest): Promise<SaveTriggerRulesResponse>;
123
+ /** `StorageService.LoadTriggerRules` — load persisted trigger rules. */
124
+ stateLoadTriggerRules(request: LoadTriggerRulesRequest): Promise<LoadTriggerRulesResponse>;
125
+ /** `StorageService.SaveCronJobs` — persist cron jobs. */
126
+ stateSaveCronJobs(request: SaveCronJobsRequest): Promise<SaveCronJobsResponse>;
127
+ /** `StorageService.LoadCronJobs` — load persisted cron jobs. */
128
+ stateLoadCronJobs(request: LoadCronJobsRequest): Promise<LoadCronJobsResponse>;
129
+ /**
130
+ * `StreamEvents` — server-streaming snapshot/event frames. Every frame
131
+ * (snapshot and event) is delivered to `onFrame`. Resolves when the stream
132
+ * ends normally; rejects on transport errors or when the client is closed.
133
+ */
134
+ streamEvents(onFrame: (frame: StreamFrame) => void, signal?: AbortSignal): Promise<void>;
135
+ /** Close the underlying channel; in-flight streams fail fast. */
136
+ close(): void;
137
+ }
138
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,390 @@
1
+ import * as grpc from '@grpc/grpc-js';
2
+ import { CommandServiceClient as CommandServiceClientCtor, MessageMode, } from './generated/commands.js';
3
+ import { EventServiceClient as EventServiceClientCtor, } from './generated/events.js';
4
+ import { ExtensionServiceClient as ExtensionServiceClientCtor, } from './generated/extensions.js';
5
+ import { GraphEngineServiceClient as GraphEngineServiceClientCtor, } from './generated/graph_engine.js';
6
+ import { SessionServiceClient as SessionServiceClientCtor, } from './generated/session.js';
7
+ import { SettingsServiceClient as SettingsServiceClientCtor, } from './generated/settings.js';
8
+ import { ToolServiceClient as ToolServiceClientCtor, } from './generated/tools.js';
9
+ import { StorageServiceClient as StorageServiceClientCtor, } from './generated/state.js';
10
+ // ── authority cleaning ──
11
+ const SCHEME_PREFIX = /^https?:\/\//;
12
+ const TRAILING_SLASHES = /\/+$/;
13
+ /**
14
+ * Typed gRPC client for the `theway --grpc` loopback server
15
+ * (theway.grpc.v1.CommandService / SessionService / SettingsService /
16
+ * ExtensionService / ToolService / StorageService / GraphEngineService /
17
+ * EventService).
18
+ * Generated from the domain proto files
19
+ * and health.proto (ts-proto + @grpc/grpc-js) — no runtime proto loading.
20
+ *
21
+ * Command RPCs (SendMessage / SetModel / …) resolve the raw CommandResult;
22
+ * the convenience wrappers (`prompt`, `setModelSpec`, `abort`, …) throw when
23
+ * the server replies `accepted: false`, mirroring the caller-side contract of
24
+ * the JSON channels.
25
+ */
26
+ export class ThewayGrpcClient {
27
+ #session;
28
+ #command;
29
+ #extensions;
30
+ #graph;
31
+ #events;
32
+ #settings;
33
+ #tools;
34
+ #storage;
35
+ constructor(baseUrl, credentials = grpc.credentials.createInsecure()) {
36
+ const authority = baseUrl.replace(SCHEME_PREFIX, '').replace(TRAILING_SLASHES, '');
37
+ this.#session = new SessionServiceClientCtor(authority, credentials);
38
+ this.#command = new CommandServiceClientCtor(authority, credentials);
39
+ this.#extensions = new ExtensionServiceClientCtor(authority, credentials);
40
+ this.#graph = new GraphEngineServiceClientCtor(authority, credentials);
41
+ this.#events = new EventServiceClientCtor(authority, credentials);
42
+ this.#settings = new SettingsServiceClientCtor(authority, credentials);
43
+ this.#tools = new ToolServiceClientCtor(authority, credentials);
44
+ this.#storage = new StorageServiceClientCtor(authority, credentials);
45
+ }
46
+ // ── session state ──
47
+ /** `GetState` — the latest full session state. */
48
+ getState() {
49
+ return this.#call(this.#session.getState.bind(this.#session), 'GetState', {});
50
+ }
51
+ /** `GetNodeOutput` — a DAG node's output fragment from an offset. */
52
+ getNodeOutput(request) {
53
+ return this.#call(this.#graph.getNodeOutput.bind(this.#graph), 'GetNodeOutput', request);
54
+ }
55
+ // ── commands ──
56
+ /** `SendMessage` — submit a user prompt (mode=QUEUE). */
57
+ async prompt(text, images = []) {
58
+ const request = { text, images, mode: MessageMode.QUEUE };
59
+ const result = await this.sendMessage(request);
60
+ if (!result.accepted) {
61
+ throw new Error('theway grpc: SendMessage was not accepted by the server');
62
+ }
63
+ }
64
+ /** `SendMessage` — raw request (mode=INTERRUPT supported). */
65
+ sendMessage(request) {
66
+ return this.#call(this.#command.sendMessage.bind(this.#command), 'SendMessage', request);
67
+ }
68
+ /** `SetModel` — switch model with a composed `provider:model` spec. */
69
+ async setModelSpec(spec) {
70
+ const request = { spec };
71
+ const result = await this.#call(this.#command.setModel.bind(this.#command), 'SetModel', request);
72
+ if (!result.accepted) {
73
+ throw new Error('theway grpc: SetModel was not accepted by the server');
74
+ }
75
+ }
76
+ /** `SetModel` with `provider` + `model` (composed into `provider:model`). */
77
+ setModel(provider, model) {
78
+ return this.setModelSpec(`${provider}:${model}`);
79
+ }
80
+ /** `Cancel` — stop the in-flight turn (same as local Ctrl-C). */
81
+ async abort() {
82
+ const result = await this.#call(this.#command.cancel.bind(this.#command), 'Cancel', {});
83
+ if (!result.accepted) {
84
+ throw new Error('theway grpc: Cancel was not accepted by the server');
85
+ }
86
+ }
87
+ /** `Approve` — resolve the pending control-plane approval (approve / reject). */
88
+ async resolveControlPlane(approve) {
89
+ const request = { approve };
90
+ const result = await this.#call(this.#command.approve.bind(this.#command), 'Approve', request);
91
+ if (!result.accepted) {
92
+ throw new Error('theway grpc: Approve was not accepted by the server');
93
+ }
94
+ }
95
+ // ── runtime extensions ──
96
+ /** Structured extension catalog, redacted diagnostics and contributions. */
97
+ getExtensions() {
98
+ return this.#call(this.#extensions.getExtensions.bind(this.#extensions), 'GetExtensions', {});
99
+ }
100
+ /** Invoke a registered extension command in either interactive or headless mode. */
101
+ invokeExtensionCommand(request) {
102
+ return this.#call(this.#extensions.invokeCommand.bind(this.#extensions), 'InvokeExtensionCommand', request);
103
+ }
104
+ /** Re-discover extensions; active work may return `status=pending`. */
105
+ reloadExtensions(request = { cancelActive: false }) {
106
+ return this.#call(this.#extensions.reload.bind(this.#extensions), 'ReloadExtensions', request);
107
+ }
108
+ /** Persist a project or exact-package trust decision and request reload. */
109
+ decideExtensionTrust(request) {
110
+ return this.#call(this.#extensions.decideTrust.bind(this.#extensions), 'DecideExtensionTrust', request);
111
+ }
112
+ // ── graph control (DAG + goal runs) ──
113
+ /** `GraphCancel` — cancel a run. */
114
+ async graphCancel(runId) {
115
+ const request = { runId };
116
+ const result = await this.#call(this.#graph.graphCancel.bind(this.#graph), 'GraphCancel', request);
117
+ if (!result.accepted) {
118
+ throw new Error('theway grpc: GraphCancel was not accepted by the server');
119
+ }
120
+ }
121
+ /** `GraphRetry` — re-run failed/cancelled nodes (omitted nodeId = all). */
122
+ graphRetry(runId, nodeId) {
123
+ const request = { runId, nodeId };
124
+ return this.#call(this.#graph.graphRetry.bind(this.#graph), 'GraphRetry', request);
125
+ }
126
+ /** `GraphSkip` — skip a node (counts as success for downstream). */
127
+ graphSkip(runId, nodeId) {
128
+ const request = { runId, nodeId };
129
+ return this.#call(this.#graph.graphSkip.bind(this.#graph), 'GraphSkip', request);
130
+ }
131
+ /** `GraphNodeInterrupt` — stop the node's in-flight turn. */
132
+ async graphNodeInterrupt(runId, nodeId) {
133
+ const request = { runId, nodeId };
134
+ const result = await this.#call(this.#graph.graphNodeInterrupt.bind(this.#graph), 'GraphNodeInterrupt', request);
135
+ if (!result.accepted) {
136
+ throw new Error('theway grpc: GraphNodeInterrupt was not accepted by the server');
137
+ }
138
+ }
139
+ /** `GraphNodeSteer` — queue a steering message at the node's next turn boundary. */
140
+ async graphNodeSteer(runId, nodeId, text) {
141
+ const request = { runId, nodeId, text };
142
+ const result = await this.#call(this.#graph.graphNodeSteer.bind(this.#graph), 'GraphNodeSteer', request);
143
+ if (!result.accepted) {
144
+ throw new Error('theway grpc: GraphNodeSteer was not accepted by the server');
145
+ }
146
+ }
147
+ /** `GraphCheckpoint` — export run snapshots as portable JSON. */
148
+ graphCheckpoint(request = {}) {
149
+ return this.#call(this.#graph.graphCheckpoint.bind(this.#graph), 'GraphCheckpoint', request);
150
+ }
151
+ /** `GraphRestore` — revive a run from a GraphCheckpoint snapshot. */
152
+ graphRestore(sessionId, snapshot) {
153
+ const request = { sessionId, snapshot };
154
+ return this.#call(this.#graph.graphRestore.bind(this.#graph), 'GraphRestore', request);
155
+ }
156
+ /** `GraphList` — enumerate one session's graph runs. */
157
+ graphList(sessionId) {
158
+ const request = { sessionId };
159
+ return this.#call(this.#graph.graphList.bind(this.#graph), 'GraphList', request);
160
+ }
161
+ // ── session resources ──
162
+ /** `ListSessions` — all sessions (live + archived) with the current one marked. */
163
+ listSessions() {
164
+ return this.#call(this.#session.listSessions.bind(this.#session), 'ListSessions', {});
165
+ }
166
+ /** `CreateSession` — create a session. */
167
+ createSession(name) {
168
+ const request = { name };
169
+ return this.#call(this.#session.createSession.bind(this.#session), 'CreateSession', request);
170
+ }
171
+ /** `SwitchSession` — switch the live session. */
172
+ async switchSession(sessionId) {
173
+ const request = { sessionId };
174
+ const result = await this.#call(this.#session.switchSession.bind(this.#session), 'SwitchSession', request);
175
+ if (!result.accepted) {
176
+ throw new Error('theway grpc: SwitchSession was not accepted by the server');
177
+ }
178
+ }
179
+ /** `RenameSession` — rename a session. */
180
+ async renameSession(sessionId, name) {
181
+ const request = { sessionId, name };
182
+ const result = await this.#call(this.#session.renameSession.bind(this.#session), 'RenameSession', request);
183
+ if (!result.accepted) {
184
+ throw new Error('theway grpc: RenameSession was not accepted by the server');
185
+ }
186
+ }
187
+ /** `DeleteSession` — delete a session (refused while graphs are running). */
188
+ deleteSession(sessionId) {
189
+ const request = { sessionId };
190
+ return this.#call(this.#session.deleteSession.bind(this.#session), 'DeleteSession', request);
191
+ }
192
+ // ── settings / config ──
193
+ /** `GetConfig` — the daemon's current configuration view. */
194
+ getConfig() {
195
+ return this.#call(this.#settings.getConfig.bind(this.#settings), 'GetConfig', {});
196
+ }
197
+ /**
198
+ * `SetConfig` — push a partial configuration update. Absent fields keep
199
+ * the daemon's current value (repeated fields default to empty = no-op).
200
+ */
201
+ async setConfig(config) {
202
+ const result = await this.#call(this.#settings.setConfig.bind(this.#settings), 'SetConfig', fillDaemonConfig(config));
203
+ if (!result.accepted) {
204
+ throw new Error('theway grpc: SetConfig was not accepted by the server');
205
+ }
206
+ }
207
+ /** `Configure` — alias of `setConfig` (JSON-RPC / WS / MCP verb alignment). */
208
+ async configure(config) {
209
+ const result = await this.#call(this.#settings.configure.bind(this.#settings), 'Configure', fillDaemonConfig(config));
210
+ if (!result.accepted) {
211
+ throw new Error('theway grpc: Configure was not accepted by the server');
212
+ }
213
+ }
214
+ // ── tool operations ──
215
+ /** `ReadFile` — read a file with line pagination. */
216
+ toolRead(request) {
217
+ return this.#call(this.#tools.readFile.bind(this.#tools), 'ReadFile', request);
218
+ }
219
+ /** `WriteFile` — write a file. */
220
+ toolWrite(request) {
221
+ return this.#call(this.#tools.writeFile.bind(this.#tools), 'WriteFile', request);
222
+ }
223
+ /** `EditFile` — search-and-replace edit. */
224
+ toolEdit(request) {
225
+ return this.#call(this.#tools.editFile.bind(this.#tools), 'EditFile', request);
226
+ }
227
+ /** `ExecCommand` — streaming shell execution. */
228
+ toolExec(request) {
229
+ return this.#tools.execCommand(request);
230
+ }
231
+ /** `ListDir` — list one directory level. */
232
+ toolListDir(request) {
233
+ return this.#call(this.#tools.listDir.bind(this.#tools), 'ListDir', request);
234
+ }
235
+ /** `Grep` — regex content search. */
236
+ toolGrep(request) {
237
+ return this.#call(this.#tools.grep.bind(this.#tools), 'Grep', request);
238
+ }
239
+ /** `Find` — filename-glob search. */
240
+ toolFind(request) {
241
+ return this.#call(this.#tools.find.bind(this.#tools), 'Find', request);
242
+ }
243
+ /** `MemorySave` — save a memory entry. */
244
+ toolMemorySave(request) {
245
+ return this.#call(this.#tools.memorySave.bind(this.#tools), 'MemorySave', request);
246
+ }
247
+ /** `MemoryList` — list memory entries. */
248
+ toolMemoryList(request) {
249
+ return this.#call(this.#tools.memoryList.bind(this.#tools), 'MemoryList', request);
250
+ }
251
+ /** `MemoryRead` — read one memory entry. */
252
+ toolMemoryRead(request) {
253
+ return this.#call(this.#tools.memoryRead.bind(this.#tools), 'MemoryRead', request);
254
+ }
255
+ /** `MemoryForget` — forget a memory entry. */
256
+ toolMemoryForget(request) {
257
+ return this.#call(this.#tools.memoryForget.bind(this.#tools), 'MemoryForget', request);
258
+ }
259
+ /** `SkillInstall` — two-phase skill install. */
260
+ toolSkillInstall(request) {
261
+ return this.#call(this.#tools.skillInstall.bind(this.#tools), 'SkillInstall', request);
262
+ }
263
+ // ── runtime state storage ──
264
+ /** `StorageService.ListSessions` — session list from external storage. */
265
+ stateListSessions(request) {
266
+ return this.#call(this.#storage.listSessions.bind(this.#storage), 'ListSessions', request);
267
+ }
268
+ /** `StorageService.CreateSession` — create a session in external storage. */
269
+ stateCreateSession(request) {
270
+ return this.#call(this.#storage.createSession.bind(this.#storage), 'CreateSession', request);
271
+ }
272
+ /** `StorageService.RenameSession` — rename a session in external storage. */
273
+ stateRenameSession(request) {
274
+ return this.#call(this.#storage.renameSession.bind(this.#storage), 'RenameSession', request);
275
+ }
276
+ /** `StorageService.DeleteSession` — delete a session in external storage. */
277
+ stateDeleteSession(request) {
278
+ return this.#call(this.#storage.deleteSession.bind(this.#storage), 'DeleteSession', request);
279
+ }
280
+ /** `StorageService.SaveDagRun` — persist a DAG run. */
281
+ stateSaveDagRun(request) {
282
+ return this.#call(this.#storage.saveDagRun.bind(this.#storage), 'SaveDagRun', request);
283
+ }
284
+ /** `StorageService.LoadDagRuns` — load persisted DAG runs. */
285
+ stateLoadDagRuns(request) {
286
+ return this.#call(this.#storage.loadDagRuns.bind(this.#storage), 'LoadDagRuns', request);
287
+ }
288
+ /** `StorageService.SaveTriggerRules` — persist trigger rules. */
289
+ stateSaveTriggerRules(request) {
290
+ return this.#call(this.#storage.saveTriggerRules.bind(this.#storage), 'SaveTriggerRules', request);
291
+ }
292
+ /** `StorageService.LoadTriggerRules` — load persisted trigger rules. */
293
+ stateLoadTriggerRules(request) {
294
+ return this.#call(this.#storage.loadTriggerRules.bind(this.#storage), 'LoadTriggerRules', request);
295
+ }
296
+ /** `StorageService.SaveCronJobs` — persist cron jobs. */
297
+ stateSaveCronJobs(request) {
298
+ return this.#call(this.#storage.saveCronJobs.bind(this.#storage), 'SaveCronJobs', request);
299
+ }
300
+ /** `StorageService.LoadCronJobs` — load persisted cron jobs. */
301
+ stateLoadCronJobs(request) {
302
+ return this.#call(this.#storage.loadCronJobs.bind(this.#storage), 'LoadCronJobs', request);
303
+ }
304
+ // ── event stream ──
305
+ /**
306
+ * `StreamEvents` — server-streaming snapshot/event frames. Every frame
307
+ * (snapshot and event) is delivered to `onFrame`. Resolves when the stream
308
+ * ends normally; rejects on transport errors or when the client is closed.
309
+ */
310
+ streamEvents(onFrame, signal) {
311
+ return new Promise((resolve, reject) => {
312
+ const forwardAbort = () => {
313
+ this.#closed = true;
314
+ // Cancel the stream by ending the call
315
+ };
316
+ signal?.addEventListener('abort', forwardAbort, { once: true });
317
+ const stream = this.#events.streamEvents.bind(this.#events)({});
318
+ stream.on('data', (frame) => {
319
+ try {
320
+ onFrame(frame);
321
+ }
322
+ catch (err) {
323
+ signal?.removeEventListener('abort', forwardAbort);
324
+ stream.destroy();
325
+ reject(new Error(`theway grpc: StreamEvents handler threw: ${extractErrorMessage(err)}`, { cause: err }));
326
+ }
327
+ });
328
+ stream.on('end', () => {
329
+ signal?.removeEventListener('abort', forwardAbort);
330
+ resolve();
331
+ });
332
+ stream.on('error', (err) => {
333
+ signal?.removeEventListener('abort', forwardAbort);
334
+ if (this.#closed || signal?.aborted) {
335
+ reject(new Error('theway grpc: StreamEvents aborted by close()'));
336
+ }
337
+ else {
338
+ reject(this.#mapError('StreamEvents', err));
339
+ }
340
+ });
341
+ });
342
+ }
343
+ /** Close the underlying channel; in-flight streams fail fast. */
344
+ close() {
345
+ this.#closed = true;
346
+ this.#session.close();
347
+ this.#command.close();
348
+ this.#extensions.close();
349
+ this.#graph.close();
350
+ this.#events.close();
351
+ this.#settings.close();
352
+ this.#tools.close();
353
+ this.#storage.close();
354
+ }
355
+ // ── private helpers ──
356
+ #closed = false;
357
+ #call(invoke, method, request) {
358
+ return new Promise((resolve, reject) => {
359
+ invoke(request, (err, response) => {
360
+ if (err) {
361
+ reject(this.#mapError(method, err));
362
+ return;
363
+ }
364
+ resolve(response);
365
+ });
366
+ });
367
+ }
368
+ #mapError(method, err) {
369
+ return new Error(`theway grpc: ${method} failed: ${err.message}`, { cause: err });
370
+ }
371
+ }
372
+ function extractErrorMessage(err) {
373
+ if (err instanceof Error)
374
+ return err.message;
375
+ return String(err);
376
+ }
377
+ /**
378
+ * Complete a partial `DaemonConfig` for the wire: ts-proto models proto3
379
+ * repeated fields as required arrays. Empty value arrays mean "keep" while
380
+ * `clearFields` carries explicit clear intent.
381
+ */
382
+ function fillDaemonConfig(config) {
383
+ return {
384
+ ...config,
385
+ builtinSkills: config.builtinSkills ?? [],
386
+ skillsDirs: config.skillsDirs ?? [],
387
+ clearFields: config.clearFields ?? [],
388
+ };
389
+ }
390
+ //# sourceMappingURL=client.js.map