@khorsheed/dsh-local-agent 0.1.0-rc.6

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 (99) hide show
  1. package/README.en.md +181 -0
  2. package/README.i18n.yaml +2 -0
  3. package/README.md +181 -0
  4. package/cordis.patch.yml +21 -0
  5. package/lib/client.js +8832 -0
  6. package/lib/index.js +5281 -0
  7. package/lib/invariant.js +85 -0
  8. package/lib/member-bridge.js +298 -0
  9. package/lib/typert.host.d.ts +3 -0
  10. package/lib/typert.host.js +3137 -0
  11. package/lib/typert.remote-client.d.ts +67 -0
  12. package/lib/typert.remote-client.js +1971 -0
  13. package/lib/types/cli-version.d.ts +82 -0
  14. package/lib/types/cli-version.js +165 -0
  15. package/lib/types/client/AuthStatusDot.d.ts +17 -0
  16. package/lib/types/client/AuthStatusDot.js +9 -0
  17. package/lib/types/client/HarnessModelPicker.d.ts +17 -0
  18. package/lib/types/client/HarnessModelPicker.js +48 -0
  19. package/lib/types/client/LocalAgentRecordsAction.d.ts +41 -0
  20. package/lib/types/client/LocalAgentRecordsAction.js +74 -0
  21. package/lib/types/client/MemberComposer.d.ts +79 -0
  22. package/lib/types/client/MemberComposer.js +308 -0
  23. package/lib/types/client/MemberConfiguration.d.ts +9 -0
  24. package/lib/types/client/MemberConfiguration.js +46 -0
  25. package/lib/types/client/MemberInboxView.d.ts +12 -0
  26. package/lib/types/client/MemberInboxView.js +38 -0
  27. package/lib/types/client/MemberLiveNode.d.ts +14 -0
  28. package/lib/types/client/MemberLiveNode.js +74 -0
  29. package/lib/types/client/MemberPaintDiagnostics.d.ts +7 -0
  30. package/lib/types/client/MemberPaintDiagnostics.js +20 -0
  31. package/lib/types/client/ModelConfigurationFields.d.ts +15 -0
  32. package/lib/types/client/ModelConfigurationFields.js +23 -0
  33. package/lib/types/client/ProviderAuthBlock.d.ts +59 -0
  34. package/lib/types/client/ProviderAuthBlock.js +164 -0
  35. package/lib/types/client/auth-status.d.ts +28 -0
  36. package/lib/types/client/auth-status.js +56 -0
  37. package/lib/types/client/icons.d.ts +22 -0
  38. package/lib/types/client/icons.js +6 -0
  39. package/lib/types/client/index.d.ts +62 -0
  40. package/lib/types/client/index.js +135 -0
  41. package/lib/types/client/live-node.d.ts +14 -0
  42. package/lib/types/client/live-node.js +34 -0
  43. package/lib/types/client/live-output.d.ts +34 -0
  44. package/lib/types/client/live-output.js +94 -0
  45. package/lib/types/client/live-paint.d.ts +40 -0
  46. package/lib/types/client/live-paint.js +74 -0
  47. package/lib/types/client/locales.d.ts +120 -0
  48. package/lib/types/client/locales.js +227 -0
  49. package/lib/types/client/member-configuration.d.ts +41 -0
  50. package/lib/types/client/member-configuration.js +114 -0
  51. package/lib/types/client/member-dock.d.ts +94 -0
  52. package/lib/types/client/member-dock.js +102 -0
  53. package/lib/types/client/member-feed.d.ts +24 -0
  54. package/lib/types/client/member-feed.js +134 -0
  55. package/lib/types/client/request-id.d.ts +3 -0
  56. package/lib/types/client/request-id.js +6 -0
  57. package/lib/types/client/settings-scope.d.ts +74 -0
  58. package/lib/types/client/settings-scope.js +98 -0
  59. package/lib/types/client/use-configuration-menu.d.ts +10 -0
  60. package/lib/types/client/use-configuration-menu.js +61 -0
  61. package/lib/types/container.d.ts +69 -0
  62. package/lib/types/container.js +129 -0
  63. package/lib/types/env.d.ts +17 -0
  64. package/lib/types/env.js +89 -0
  65. package/lib/types/gateway.d.ts +162 -0
  66. package/lib/types/gateway.js +470 -0
  67. package/lib/types/index.d.ts +1463 -0
  68. package/lib/types/index.js +2704 -0
  69. package/lib/types/invariant.d.ts +16 -0
  70. package/lib/types/invariant.js +105 -0
  71. package/lib/types/live-flush.d.ts +21 -0
  72. package/lib/types/live-flush.js +59 -0
  73. package/lib/types/live-stream.d.ts +41 -0
  74. package/lib/types/live-stream.js +178 -0
  75. package/lib/types/member-bridge.d.ts +50 -0
  76. package/lib/types/member-bridge.js +216 -0
  77. package/lib/types/member-channel.d.ts +86 -0
  78. package/lib/types/member-channel.js +232 -0
  79. package/lib/types/member-control-storage.d.ts +10 -0
  80. package/lib/types/member-control-storage.js +100 -0
  81. package/lib/types/member-control.d.ts +62 -0
  82. package/lib/types/member-control.js +359 -0
  83. package/lib/types/member-controls.d.ts +23 -0
  84. package/lib/types/member-controls.js +143 -0
  85. package/lib/types/member-feed.d.ts +4 -0
  86. package/lib/types/member-feed.js +45 -0
  87. package/lib/types/member-inbox.d.ts +30 -0
  88. package/lib/types/member-inbox.js +225 -0
  89. package/lib/types/model-directory.d.ts +43 -0
  90. package/lib/types/model-directory.js +192 -0
  91. package/lib/types/prepared-members.d.ts +15 -0
  92. package/lib/types/prepared-members.js +61 -0
  93. package/lib/types/settings-face.d.ts +61 -0
  94. package/lib/types/settings-face.js +61 -0
  95. package/lib/types/types.d.ts +959 -0
  96. package/lib/types/types.js +24 -0
  97. package/locale/en.json +6 -0
  98. package/locale/zh.json +6 -0
  99. package/package.json +112 -0
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Package-owned invariant companion for `@khorsheed/dsh-local-agent`.
3
+ * @module @khorsheed/dsh-local-agent/invariant
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "local-agent-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - plugin context carrying the invariant registry.
13
+ * @returns the installed registration's disposer.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
16
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Package-owned invariant companion for `@khorsheed/dsh-local-agent`.
3
+ * @module @khorsheed/dsh-local-agent/invariant
4
+ */
5
+ const PACKAGE_NAME = '@khorsheed/dsh-local-agent';
6
+ /** Cordis companion plugin name. */
7
+ export const name = 'local-agent-invariant';
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export const inject = ['invariants'];
10
+ const NAME_PATTERN = /^[a-z][a-z0-9-]*$/u;
11
+ /**
12
+ * Audit the harness registry lifecycle: a registered harness must carry a
13
+ * valid, unique command-prefix name, a home environment variable, and a
14
+ * records adapter, and a removed name must have been registered first.
15
+ */
16
+ function auditLifecycle(ctx, fail) {
17
+ const known = new Set();
18
+ ctx.on('internal/dispatch', (_mode, eventName, args) => {
19
+ if (eventName === 'localAgent/harness-added') {
20
+ const harness = args[0];
21
+ if (!NAME_PATTERN.test(harness.name)) {
22
+ fail(`localAgent/harness-added names a harness with invalid name ${JSON.stringify(harness.name)}`);
23
+ }
24
+ if (known.has(harness.name))
25
+ fail(`localAgent/harness-added repeats name ${JSON.stringify(harness.name)}`);
26
+ if (harness.homeEnvVar.length === 0)
27
+ fail(`localAgent/harness-added for ${harness.name} has an empty homeEnvVar`);
28
+ known.add(harness.name);
29
+ return;
30
+ }
31
+ if (eventName !== 'localAgent/harness-removed')
32
+ return;
33
+ const name = args[0];
34
+ if (!known.delete(name))
35
+ fail(`localAgent/harness-removed names unknown harness ${JSON.stringify(name)}`);
36
+ }, { global: true });
37
+ }
38
+ /**
39
+ * Cross-check delegation claims against the mounted subagent providers after
40
+ * the composition settles. A harness whose {@link LocalAgentHarness.delegationProvider}
41
+ * names a provider the tree does not mount means "identity present, delegation
42
+ * 404" — a typo in either the record or the bundle patch — and fails loud.
43
+ * A composition without the subagent seam (record-and-login only) skips the
44
+ * check; so does a harness without a delegation provider.
45
+ */
46
+ async function auditDelegationClaims(ctx, fail) {
47
+ const loader = ctx.get('loader');
48
+ await loader?.await();
49
+ const subagents = ctx.get('subagents');
50
+ if (subagents === undefined)
51
+ return;
52
+ const registry = ctx.get('localAgent');
53
+ if (registry === undefined)
54
+ return;
55
+ for (const name of registry.list()) {
56
+ const providerName = registry.get(name)?.delegationProvider;
57
+ if (providerName === undefined)
58
+ continue;
59
+ if (subagents.getProvider(providerName) === undefined) {
60
+ fail(`local-agent harness ${name} declares delegation provider ${JSON.stringify(providerName)} which is not mounted`);
61
+ }
62
+ }
63
+ }
64
+ /**
65
+ * Audit the delegation registry: a recorded delegation must name a mounted
66
+ * subagent provider (the record is only useful when a resume round can route
67
+ * back through the same provider). Mirrors the harness-level delegation-claim
68
+ * check with the same "identity present, delegation 404" rationale — a record
69
+ * whose provider the tree does not mount means a provider rename left a stale
70
+ * mapping that would fail loud on the first resume attempt.
71
+ */
72
+ async function auditDelegationProviders(ctx, fail) {
73
+ const loader = ctx.get('loader');
74
+ await loader?.await();
75
+ const subagents = ctx.get('subagents');
76
+ if (subagents === undefined)
77
+ return;
78
+ const registry = ctx.get('localAgent');
79
+ if (registry === undefined)
80
+ return;
81
+ for (const record of registry.listDelegations()) {
82
+ if (subagents.getProvider(record.provider) === undefined) {
83
+ fail(`local-agent delegation for child session ${record.childSessionId} records provider ${JSON.stringify(record.provider)} which is not mounted`);
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * Install the package's checks.
89
+ * @param ctx - child context owned by this invariant registration.
90
+ * @param fail - reporter bound to the registering package name.
91
+ */
92
+ const install = Object.assign((ctx, fail) => {
93
+ auditLifecycle(ctx, fail);
94
+ return Promise.all([
95
+ auditDelegationClaims(ctx, fail),
96
+ auditDelegationProviders(ctx, fail),
97
+ ]).then(() => { });
98
+ }, {});
99
+ /**
100
+ * Register this package's invariant companion.
101
+ * @param ctx - plugin context carrying the invariant registry.
102
+ * @returns the installed registration's disposer.
103
+ */
104
+ export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
105
+ /* jscpd:ignore-end */
@@ -0,0 +1,21 @@
1
+ /** Maximum batching delay for a live mirror; independent of persistence cadence. */
2
+ export declare const LIVE_FLUSH_INTERVAL_MS = 50;
3
+ /**
4
+ * Coalesce an item's updates without postponing its first pending deadline.
5
+ * Even a single short delta flushes without another provider event. Owners
6
+ * cancel an item before its authoritative final and dispose before turn/end.
7
+ */
8
+ export declare class LiveFlush {
9
+ private readonly onError;
10
+ private readonly intervalMs;
11
+ private readonly pending;
12
+ private disposed;
13
+ constructor(onError: (error: unknown) => void, intervalMs?: number);
14
+ /** Schedule the latest content at the item's existing deadline. */
15
+ schedule(item: number, publish: () => void): void;
16
+ /** Supersede pending content with an authoritative final or immediate flush. */
17
+ cancel(item: number): void;
18
+ /** Retire every timer; a settled round must never publish a late snapshot. */
19
+ dispose(): void;
20
+ }
21
+ //# sourceMappingURL=live-flush.d.ts.map
@@ -0,0 +1,59 @@
1
+ /** Maximum batching delay for a live mirror; independent of persistence cadence. */
2
+ export const LIVE_FLUSH_INTERVAL_MS = 50;
3
+ /**
4
+ * Coalesce an item's updates without postponing its first pending deadline.
5
+ * Even a single short delta flushes without another provider event. Owners
6
+ * cancel an item before its authoritative final and dispose before turn/end.
7
+ */
8
+ export class LiveFlush {
9
+ onError;
10
+ intervalMs;
11
+ pending = new Map();
12
+ disposed = false;
13
+ constructor(onError, intervalMs = LIVE_FLUSH_INTERVAL_MS) {
14
+ this.onError = onError;
15
+ this.intervalMs = intervalMs;
16
+ }
17
+ /** Schedule the latest content at the item's existing deadline. */
18
+ schedule(item, publish) {
19
+ if (this.disposed)
20
+ return;
21
+ if (this.intervalMs <= 0) {
22
+ publish();
23
+ return;
24
+ }
25
+ const existing = this.pending.get(item);
26
+ if (existing !== undefined) {
27
+ existing.publish = publish;
28
+ return;
29
+ }
30
+ const entry = {
31
+ publish,
32
+ timer: setTimeout(() => {
33
+ this.pending.delete(item);
34
+ try {
35
+ entry.publish();
36
+ }
37
+ catch (error) {
38
+ this.onError(error);
39
+ }
40
+ }, this.intervalMs),
41
+ };
42
+ entry.timer.unref?.();
43
+ this.pending.set(item, entry);
44
+ }
45
+ /** Supersede pending content with an authoritative final or immediate flush. */
46
+ cancel(item) {
47
+ const entry = this.pending.get(item);
48
+ if (entry === undefined)
49
+ return;
50
+ clearTimeout(entry.timer);
51
+ this.pending.delete(item);
52
+ }
53
+ /** Retire every timer; a settled round must never publish a late snapshot. */
54
+ dispose() {
55
+ this.disposed = true;
56
+ for (const item of this.pending.keys())
57
+ this.cancel(item);
58
+ }
59
+ }
@@ -0,0 +1,41 @@
1
+ /** Transient member output, with bounded followers and incremental durable checkpoints. */
2
+ import type { Session } from '@deepseek-ai/dsh-session';
3
+ import type { LocalAgentStreamFrame, LocalAgentStreamItem } from './types.ts';
4
+ /** Shared process-local output registry. No Agent impersonation or durable token events. */
5
+ export declare class LocalAgentStreams {
6
+ private readonly items;
7
+ private readonly listeners;
8
+ private revision;
9
+ private disposed;
10
+ publish(sessionId: string, item: Omit<LocalAgentStreamItem, 'revision'>): void;
11
+ finish(sessionId: string, id: string): void;
12
+ private notify;
13
+ /**
14
+ * Opening baseline followed by coalesced suffix patches. Each follower keeps
15
+ * only its last delivered state; a slow browser cannot accumulate a queue.
16
+ */
17
+ follow(sessionId: string, signal: AbortSignal): AsyncIterable<LocalAgentStreamFrame>;
18
+ dispose(): void;
19
+ }
20
+ /** Durable cadence is independent of browser cadence; checkpoint bytes are suffixes. */
21
+ export declare const LIVE_CHECKPOINT_INTERVAL_MS = 1000;
22
+ /** One round's producer. Final native messages replace its presentation nodes by coordinate. */
23
+ export declare class LiveStreamPublisher {
24
+ private readonly streams;
25
+ private readonly session;
26
+ private readonly turn;
27
+ private readonly persist;
28
+ private readonly onError;
29
+ private readonly states;
30
+ constructor(streams: LocalAgentStreams, session: Session, turn: number, persist: () => void, onError: (error: unknown) => void);
31
+ update(step: number, kind: 'think' | 'text', text: string, options?: {
32
+ itemId?: string;
33
+ receivedAt?: number;
34
+ }): void;
35
+ private checkpoint;
36
+ /** Call only after the corresponding native final message has been appended. */
37
+ finish(step: number): void;
38
+ /** A producer failure keeps a durable partial, without claiming completion. */
39
+ dispose(): void;
40
+ }
41
+ //# sourceMappingURL=live-stream.d.ts.map
@@ -0,0 +1,178 @@
1
+ /** Shared process-local output registry. No Agent impersonation or durable token events. */
2
+ export class LocalAgentStreams {
3
+ items = new Map();
4
+ listeners = new Map();
5
+ revision = 0;
6
+ disposed = false;
7
+ publish(sessionId, item) {
8
+ if (this.disposed)
9
+ return;
10
+ let items = this.items.get(sessionId);
11
+ if (items === undefined)
12
+ this.items.set(sessionId, items = new Map());
13
+ items.set(item.id, { ...item, revision: ++this.revision });
14
+ this.notify(sessionId);
15
+ }
16
+ finish(sessionId, id) {
17
+ const items = this.items.get(sessionId);
18
+ if (!items?.delete(id))
19
+ return;
20
+ if (items.size === 0)
21
+ this.items.delete(sessionId);
22
+ this.notify(sessionId);
23
+ }
24
+ notify(sessionId) {
25
+ for (const listener of this.listeners.get(sessionId) ?? [])
26
+ listener();
27
+ }
28
+ /**
29
+ * Opening baseline followed by coalesced suffix patches. Each follower keeps
30
+ * only its last delivered state; a slow browser cannot accumulate a queue.
31
+ */
32
+ async *follow(sessionId, signal) {
33
+ let wake;
34
+ let dirty = true;
35
+ let baseline = true;
36
+ const previous = new Map();
37
+ const notify = () => { dirty = true; wake?.(); wake = undefined; };
38
+ let listeners = this.listeners.get(sessionId);
39
+ if (listeners === undefined)
40
+ this.listeners.set(sessionId, listeners = new Set());
41
+ listeners.add(notify);
42
+ signal.addEventListener('abort', notify, { once: true });
43
+ try {
44
+ while (!signal.aborted && !this.disposed) {
45
+ if (!dirty)
46
+ await new Promise(resolve => { wake = resolve; });
47
+ if (signal.aborted || this.disposed)
48
+ return;
49
+ dirty = false;
50
+ const items = this.items.get(sessionId) ?? new Map();
51
+ const updates = [];
52
+ const removed = [];
53
+ for (const [id, item] of items) {
54
+ const old = previous.get(id);
55
+ if (old?.revision === item.revision)
56
+ continue;
57
+ const append = old !== undefined && item.text.startsWith(old.text);
58
+ updates.push({ ...item, text: append ? item.text.slice(old.text.length) : item.text, append });
59
+ previous.set(id, item);
60
+ }
61
+ for (const id of previous.keys()) {
62
+ if (!items.has(id)) {
63
+ previous.delete(id);
64
+ removed.push(id);
65
+ }
66
+ }
67
+ if (baseline || updates.length > 0 || removed.length > 0) {
68
+ const frame = { baseline, updates, removed };
69
+ baseline = false;
70
+ yield frame;
71
+ }
72
+ }
73
+ }
74
+ finally {
75
+ signal.removeEventListener('abort', notify);
76
+ listeners.delete(notify);
77
+ if (listeners.size === 0)
78
+ this.listeners.delete(sessionId);
79
+ }
80
+ }
81
+ dispose() {
82
+ this.disposed = true;
83
+ this.items.clear();
84
+ for (const listeners of this.listeners.values())
85
+ for (const notify of listeners)
86
+ notify();
87
+ this.listeners.clear();
88
+ }
89
+ }
90
+ /** Durable cadence is independent of browser cadence; checkpoint bytes are suffixes. */
91
+ export const LIVE_CHECKPOINT_INTERVAL_MS = 1_000;
92
+ /** One round's producer. Final native messages replace its presentation nodes by coordinate. */
93
+ export class LiveStreamPublisher {
94
+ streams;
95
+ session;
96
+ turn;
97
+ persist;
98
+ onError;
99
+ states = new Map();
100
+ constructor(streams, session, turn, persist, onError) {
101
+ this.streams = streams;
102
+ this.session = session;
103
+ this.turn = turn;
104
+ this.persist = persist;
105
+ this.onError = onError;
106
+ }
107
+ update(step, kind, text, options = {}) {
108
+ const id = `${this.turn}:${step}${options.itemId === undefined ? '' : `:${options.itemId}`}`;
109
+ let state = this.states.get(id);
110
+ if (state?.item.text === text && state.item.kind === kind)
111
+ return;
112
+ const receivedAt = options.receivedAt ?? Date.now();
113
+ if (state === undefined) {
114
+ const item = { id, turn: this.turn, step, kind, text, receivedAt };
115
+ state = { item, durable: text };
116
+ this.states.set(id, state);
117
+ this.session.append('local-agent/stream', { ...item, sessionId: String(this.session.id), opening: true, append: false });
118
+ this.persist();
119
+ }
120
+ else {
121
+ state.item = { ...state.item, kind, text, receivedAt };
122
+ }
123
+ this.streams.publish(String(this.session.id), state.item);
124
+ if (state.timer === undefined) {
125
+ state.timer = setTimeout(() => {
126
+ delete state.timer;
127
+ try {
128
+ this.checkpoint(id);
129
+ }
130
+ catch (error) {
131
+ this.onError(error);
132
+ }
133
+ }, LIVE_CHECKPOINT_INTERVAL_MS);
134
+ state.timer.unref?.();
135
+ }
136
+ }
137
+ checkpoint(id) {
138
+ const state = this.states.get(id);
139
+ if (state === undefined || state.durable === state.item.text)
140
+ return;
141
+ const append = state.item.text.startsWith(state.durable);
142
+ this.session.append('local-agent/stream', {
143
+ ...state.item,
144
+ sessionId: String(this.session.id),
145
+ text: append ? state.item.text.slice(state.durable.length) : state.item.text,
146
+ append,
147
+ });
148
+ state.durable = state.item.text;
149
+ this.persist();
150
+ }
151
+ /** Call only after the corresponding native final message has been appended. */
152
+ finish(step) {
153
+ for (const [id, state] of this.states) {
154
+ if (state.item.step !== step)
155
+ continue;
156
+ if (state.timer !== undefined)
157
+ clearTimeout(state.timer);
158
+ // Native final events identify the whole step. Subitems additionally
159
+ // close their own anchors so replay cannot resurrect a duplicate block.
160
+ if (id !== `${this.turn}:${step}`) {
161
+ this.session.append('local-agent/stream', { ...state.item, sessionId: String(this.session.id), text: '', append: true, closed: true });
162
+ this.persist();
163
+ }
164
+ this.states.delete(id);
165
+ this.streams.finish(String(this.session.id), id);
166
+ }
167
+ }
168
+ /** A producer failure keeps a durable partial, without claiming completion. */
169
+ dispose() {
170
+ for (const [id, state] of this.states) {
171
+ this.checkpoint(id);
172
+ if (state.timer !== undefined)
173
+ clearTimeout(state.timer);
174
+ this.streams.finish(String(this.session.id), id);
175
+ }
176
+ this.states.clear();
177
+ }
178
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Member bridge: a minimal standalone MCP server (stdio, newline-delimited
3
+ * JSON-RPC) exposing member messaging and room coordination tools to the CLI
4
+ * member that spawned it. Each call is forwarded to the host's member-channel
5
+ * listener over the loopback socket named by `DSH_MEMBER_SOCKET`,
6
+ * authenticated by the per-run token in `DSH_MEMBER_TOKEN`; the host's
7
+ * receipt is the tool result verbatim.
8
+ *
9
+ * The process is dependency-free (node builtins only) because the CLI spawns
10
+ * it bare: `node <this file>`, with the socket path and token in its
11
+ * environment (written into the CLI's scoped MCP config by the provider).
12
+ * Covers the MCP handshake subset a client needs: `initialize`,
13
+ * `notifications/initialized`, `ping`, `tools/list`, `tools/call`.
14
+ * @module @khorsheed/dsh-local-agent/member-bridge
15
+ */
16
+ import type { Readable, Writable } from 'node:stream';
17
+ import type { MemberRoomCommandName } from './types.ts';
18
+ /** The one tool this server exposes. */
19
+ export declare const MEMBER_MESSAGE_TOOL = "member_message";
20
+ export declare function callRoomCommand(env: MemberBridgeEnv, name: MemberRoomCommandName, args: unknown): Promise<Record<string, unknown>>;
21
+ /** What the bridge needs from its environment (injectable for tests). */
22
+ export interface MemberBridgeEnv {
23
+ /** Host member-channel socket path. */
24
+ readonly socket?: string | undefined;
25
+ /** This run's member-channel token. */
26
+ readonly token?: string | undefined;
27
+ }
28
+ /**
29
+ * Handle one `member_message` tool call: forward to the host listener and map
30
+ * the outcome to a tool result. Channel failures (missing env, unreachable
31
+ * listener, rejected token) are tool errors; delivery verdicts are text.
32
+ * @param env - the bridge's environment (socket, token).
33
+ * @param args - the tool arguments (`to`, `text`).
34
+ * @returns the MCP tool result object.
35
+ */
36
+ export declare function callMemberMessage(env: MemberBridgeEnv, args: {
37
+ to?: unknown;
38
+ text?: unknown;
39
+ }): Promise<Record<string, unknown>>;
40
+ /**
41
+ * Run the stdio JSON-RPC loop over the given streams (injectable for tests).
42
+ * Unknown methods with an id get a MethodNotFound error; notifications are
43
+ * ignored. Never throws — a malformed line is answered with a parse error and
44
+ * the loop continues.
45
+ * @param env - the bridge's environment.
46
+ * @param input - the stdin side.
47
+ * @param output - the stdout side.
48
+ */
49
+ export declare function serveMemberBridge(env: MemberBridgeEnv, input: Readable, output: Writable): void;
50
+ //# sourceMappingURL=member-bridge.d.ts.map