@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,470 @@
1
+ /**
2
+ * Read-only Remote channel for the local-agent family: roster, per-harness
3
+ * auth status, and scoped session records. The web client polls these through
4
+ * Typert Gateway instead of the slash-command channel, so UI refreshes never
5
+ * leave `command/run`/`command/done` lifecycle nodes in the session log.
6
+ * Sign-out and login stay on the command channel: they are user-initiated
7
+ * actions whose visible command node is the expected feedback.
8
+ * @module @khorsheed/dsh-local-agent/gateway
9
+ */
10
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
11
+ var useValue = arguments.length > 2;
12
+ for (var i = 0; i < initializers.length; i++) {
13
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
14
+ }
15
+ return useValue ? value : void 0;
16
+ };
17
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
18
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
19
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
20
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
21
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
22
+ var _, done = false;
23
+ for (var i = decorators.length - 1; i >= 0; i--) {
24
+ var context = {};
25
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
26
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
27
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
28
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
29
+ if (kind === "accessor") {
30
+ if (result === void 0) continue;
31
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
32
+ if (_ = accept(result.get)) descriptor.get = _;
33
+ if (_ = accept(result.set)) descriptor.set = _;
34
+ if (_ = accept(result.init)) initializers.unshift(_);
35
+ }
36
+ else if (_ = accept(result)) {
37
+ if (kind === "field") initializers.unshift(_);
38
+ else descriptor[key] = _;
39
+ }
40
+ }
41
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
42
+ done = true;
43
+ };
44
+ import { randomUUID } from 'node:crypto';
45
+ import { SessionId } from '@deepseek-ai/dsh-session';
46
+ import { TypertRemoteService, Remote } from '@deepseek-ai/dsh-typert-protocol';
47
+ import { extendModelDirectory } from './model-directory.js';
48
+ import { mergeMemberFeeds } from './member-feed.js';
49
+ /**
50
+ * Remote-only projection of the local-agent registry, exposed to the browser
51
+ * through Typert Gateway under the `localAgentGateway` service key.
52
+ */
53
+ /**
54
+ * Fold a model surface's `lastObserved` into its pick list: a member (or
55
+ * harness) whose only named model is what it was observed running still gets
56
+ * a one-item menu instead of an empty one. The observation appends LAST —
57
+ * the broker's own choices keep their ranking — and an already-listed value
58
+ * leaves the list untouched (choices arrive deduped from the broker).
59
+ */
60
+ function withObservedChoice(info) {
61
+ const observed = info.lastObserved;
62
+ if (observed === undefined)
63
+ return info;
64
+ return {
65
+ ...info,
66
+ choices: info.choices.includes(observed) ? info.choices : [...info.choices, observed],
67
+ ...info.directory === undefined ? {} : { directory: extendModelDirectory(info.directory, [], [observed]) },
68
+ };
69
+ }
70
+ let LocalAgentGateway = (() => {
71
+ let _classSuper = TypertRemoteService;
72
+ let _instanceExtraInitializers = [];
73
+ let _followMemberOutput_decorators;
74
+ let _followMembers_decorators;
75
+ let _modelDirectory_decorators;
76
+ let _followModelDirectory_decorators;
77
+ let _memberDirectory_decorators;
78
+ let _followMemberDirectory_decorators;
79
+ let _roster_decorators;
80
+ let _activeDelegations_decorators;
81
+ let _status_decorators;
82
+ let _sessions_decorators;
83
+ let _memberOf_decorators;
84
+ let _harnessModel_decorators;
85
+ let _memberModel_decorators;
86
+ let _setMemberModel_decorators;
87
+ let _memberConfiguration_decorators;
88
+ let _selectMemberConfiguration_decorators;
89
+ let _cancelMemberConfiguration_decorators;
90
+ let _retryMemberConfiguration_decorators;
91
+ let _followMemberConfiguration_decorators;
92
+ let _promptMember_decorators;
93
+ let _memberInbox_decorators;
94
+ let _controlMemberInbox_decorators;
95
+ let _stopMember_decorators;
96
+ return class LocalAgentGateway extends _classSuper {
97
+ static {
98
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
99
+ _followMemberOutput_decorators = [Remote({ mode: 'stream' })];
100
+ _followMembers_decorators = [Remote({ mode: 'stream' })];
101
+ _modelDirectory_decorators = [Remote('modelDirectory')];
102
+ _followModelDirectory_decorators = [Remote({ mode: 'stream' })];
103
+ _memberDirectory_decorators = [Remote('memberDirectory')];
104
+ _followMemberDirectory_decorators = [Remote({ mode: 'stream' })];
105
+ _roster_decorators = [Remote('roster')];
106
+ _activeDelegations_decorators = [Remote('activeDelegations')];
107
+ _status_decorators = [Remote('status')];
108
+ _sessions_decorators = [Remote('sessions')];
109
+ _memberOf_decorators = [Remote('memberOf')];
110
+ _harnessModel_decorators = [Remote('harnessModel')];
111
+ _memberModel_decorators = [Remote('memberModel')];
112
+ _setMemberModel_decorators = [Remote('setMemberModel')];
113
+ _memberConfiguration_decorators = [Remote('memberConfiguration')];
114
+ _selectMemberConfiguration_decorators = [Remote('selectMemberConfiguration')];
115
+ _cancelMemberConfiguration_decorators = [Remote('cancelMemberConfiguration')];
116
+ _retryMemberConfiguration_decorators = [Remote('retryMemberConfiguration')];
117
+ _followMemberConfiguration_decorators = [Remote({ mode: 'stream' })];
118
+ _promptMember_decorators = [Remote('promptMember')];
119
+ _memberInbox_decorators = [Remote('memberInbox')];
120
+ _controlMemberInbox_decorators = [Remote('controlMemberInbox')];
121
+ _stopMember_decorators = [Remote('stopMember')];
122
+ __esDecorate(this, null, _followMemberOutput_decorators, { kind: "method", name: "followMemberOutput", static: false, private: false, access: { has: obj => "followMemberOutput" in obj, get: obj => obj.followMemberOutput }, metadata: _metadata }, null, _instanceExtraInitializers);
123
+ __esDecorate(this, null, _followMembers_decorators, { kind: "method", name: "followMembers", static: false, private: false, access: { has: obj => "followMembers" in obj, get: obj => obj.followMembers }, metadata: _metadata }, null, _instanceExtraInitializers);
124
+ __esDecorate(this, null, _modelDirectory_decorators, { kind: "method", name: "modelDirectory", static: false, private: false, access: { has: obj => "modelDirectory" in obj, get: obj => obj.modelDirectory }, metadata: _metadata }, null, _instanceExtraInitializers);
125
+ __esDecorate(this, null, _followModelDirectory_decorators, { kind: "method", name: "followModelDirectory", static: false, private: false, access: { has: obj => "followModelDirectory" in obj, get: obj => obj.followModelDirectory }, metadata: _metadata }, null, _instanceExtraInitializers);
126
+ __esDecorate(this, null, _memberDirectory_decorators, { kind: "method", name: "memberDirectory", static: false, private: false, access: { has: obj => "memberDirectory" in obj, get: obj => obj.memberDirectory }, metadata: _metadata }, null, _instanceExtraInitializers);
127
+ __esDecorate(this, null, _followMemberDirectory_decorators, { kind: "method", name: "followMemberDirectory", static: false, private: false, access: { has: obj => "followMemberDirectory" in obj, get: obj => obj.followMemberDirectory }, metadata: _metadata }, null, _instanceExtraInitializers);
128
+ __esDecorate(this, null, _roster_decorators, { kind: "method", name: "roster", static: false, private: false, access: { has: obj => "roster" in obj, get: obj => obj.roster }, metadata: _metadata }, null, _instanceExtraInitializers);
129
+ __esDecorate(this, null, _activeDelegations_decorators, { kind: "method", name: "activeDelegations", static: false, private: false, access: { has: obj => "activeDelegations" in obj, get: obj => obj.activeDelegations }, metadata: _metadata }, null, _instanceExtraInitializers);
130
+ __esDecorate(this, null, _status_decorators, { kind: "method", name: "status", static: false, private: false, access: { has: obj => "status" in obj, get: obj => obj.status }, metadata: _metadata }, null, _instanceExtraInitializers);
131
+ __esDecorate(this, null, _sessions_decorators, { kind: "method", name: "sessions", static: false, private: false, access: { has: obj => "sessions" in obj, get: obj => obj.sessions }, metadata: _metadata }, null, _instanceExtraInitializers);
132
+ __esDecorate(this, null, _memberOf_decorators, { kind: "method", name: "memberOf", static: false, private: false, access: { has: obj => "memberOf" in obj, get: obj => obj.memberOf }, metadata: _metadata }, null, _instanceExtraInitializers);
133
+ __esDecorate(this, null, _harnessModel_decorators, { kind: "method", name: "harnessModel", static: false, private: false, access: { has: obj => "harnessModel" in obj, get: obj => obj.harnessModel }, metadata: _metadata }, null, _instanceExtraInitializers);
134
+ __esDecorate(this, null, _memberModel_decorators, { kind: "method", name: "memberModel", static: false, private: false, access: { has: obj => "memberModel" in obj, get: obj => obj.memberModel }, metadata: _metadata }, null, _instanceExtraInitializers);
135
+ __esDecorate(this, null, _setMemberModel_decorators, { kind: "method", name: "setMemberModel", static: false, private: false, access: { has: obj => "setMemberModel" in obj, get: obj => obj.setMemberModel }, metadata: _metadata }, null, _instanceExtraInitializers);
136
+ __esDecorate(this, null, _memberConfiguration_decorators, { kind: "method", name: "memberConfiguration", static: false, private: false, access: { has: obj => "memberConfiguration" in obj, get: obj => obj.memberConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
137
+ __esDecorate(this, null, _selectMemberConfiguration_decorators, { kind: "method", name: "selectMemberConfiguration", static: false, private: false, access: { has: obj => "selectMemberConfiguration" in obj, get: obj => obj.selectMemberConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
138
+ __esDecorate(this, null, _cancelMemberConfiguration_decorators, { kind: "method", name: "cancelMemberConfiguration", static: false, private: false, access: { has: obj => "cancelMemberConfiguration" in obj, get: obj => obj.cancelMemberConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
139
+ __esDecorate(this, null, _retryMemberConfiguration_decorators, { kind: "method", name: "retryMemberConfiguration", static: false, private: false, access: { has: obj => "retryMemberConfiguration" in obj, get: obj => obj.retryMemberConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
140
+ __esDecorate(this, null, _followMemberConfiguration_decorators, { kind: "method", name: "followMemberConfiguration", static: false, private: false, access: { has: obj => "followMemberConfiguration" in obj, get: obj => obj.followMemberConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
141
+ __esDecorate(this, null, _promptMember_decorators, { kind: "method", name: "promptMember", static: false, private: false, access: { has: obj => "promptMember" in obj, get: obj => obj.promptMember }, metadata: _metadata }, null, _instanceExtraInitializers);
142
+ __esDecorate(this, null, _memberInbox_decorators, { kind: "method", name: "memberInbox", static: false, private: false, access: { has: obj => "memberInbox" in obj, get: obj => obj.memberInbox }, metadata: _metadata }, null, _instanceExtraInitializers);
143
+ __esDecorate(this, null, _controlMemberInbox_decorators, { kind: "method", name: "controlMemberInbox", static: false, private: false, access: { has: obj => "controlMemberInbox" in obj, get: obj => obj.controlMemberInbox }, metadata: _metadata }, null, _instanceExtraInitializers);
144
+ __esDecorate(this, null, _stopMember_decorators, { kind: "method", name: "stopMember", static: false, private: false, access: { has: obj => "stopMember" in obj, get: obj => obj.stopMember }, metadata: _metadata }, null, _instanceExtraInitializers);
145
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
146
+ }
147
+ static inject = ['localAgent', 'sessions'];
148
+ constructor(ctx) {
149
+ super(ctx, 'localAgentGateway');
150
+ __runInitializers(this, _instanceExtraInitializers);
151
+ }
152
+ /**
153
+ * Follow one member's transient output with a complete reconnect baseline.
154
+ * @param childSessionId - mirrored session identity.
155
+ * @param signal - Remote-owned cancellation, including browser disconnects.
156
+ * @returns bounded incremental updates; final content remains in session history.
157
+ */
158
+ followMemberOutput(childSessionId, signal) {
159
+ return this.ctx.localAgent.liveStreams.follow(childSessionId, signal);
160
+ }
161
+ /** Shared browser stream: adding visible members does not consume more HTTP connections. */
162
+ followMembers(requests, signal) {
163
+ return mergeMemberFeeds(requests, (request, signal) => this.memberFeed(request, signal), signal);
164
+ }
165
+ async *memberFeed(request, signal) {
166
+ const memberId = request.memberId;
167
+ switch (request.channel) {
168
+ case 'output':
169
+ for await (const value of this.followMemberOutput(memberId, signal))
170
+ yield { memberId, channel: 'output', value };
171
+ break;
172
+ case 'configuration':
173
+ for await (const value of this.followMemberConfiguration(memberId, signal))
174
+ yield { memberId, channel: 'configuration', value };
175
+ break;
176
+ case 'directory':
177
+ for await (const value of this.followMemberDirectory(memberId, signal))
178
+ yield { memberId, channel: 'directory', value };
179
+ break;
180
+ }
181
+ }
182
+ directoryBroker(name, childSessionId) {
183
+ const harness = this.ctx.localAgent.get(name);
184
+ if (childSessionId !== undefined) {
185
+ const record = this.ctx.localAgent.getDelegation(childSessionId);
186
+ if (record === undefined || record.provider !== harness?.delegationProvider)
187
+ return undefined;
188
+ }
189
+ return harness?.modelBroker;
190
+ }
191
+ /**
192
+ * Read or explicitly refresh native model discovery, without changing a member.
193
+ * @param name - owning harness.
194
+ * @param childSessionId - member context, or undefined for the harness default.
195
+ * @param refresh - bypass the discovery TTL.
196
+ * @returns source-labelled discovery state, or null for an unavailable broker.
197
+ */
198
+ async modelDirectory(name, childSessionId, refresh) {
199
+ const broker = this.directoryBroker(name, childSessionId);
200
+ return await broker?.modelDirectory?.(childSessionId, refresh) ?? null;
201
+ }
202
+ /**
203
+ * Keep a currently open model picker synchronized with discovery completion.
204
+ * @param name - owning harness.
205
+ * @param childSessionId - member context, or undefined for the harness default.
206
+ * @param signal - Remote-owned cancellation.
207
+ * @returns directory baselines and subsequent snapshots.
208
+ */
209
+ async *followModelDirectory(name, childSessionId, signal) {
210
+ const broker = this.directoryBroker(name, childSessionId);
211
+ if (broker?.followModelDirectory !== undefined)
212
+ yield* broker.followModelDirectory(childSessionId, signal);
213
+ else {
214
+ const directory = await broker?.modelDirectory?.(childSessionId);
215
+ if (directory !== undefined && !signal.aborted)
216
+ yield directory;
217
+ }
218
+ }
219
+ /** Resolve directory ownership from the recorded member, never a UI provider guess. */
220
+ async memberDirectory(childSessionId, refresh) {
221
+ const record = this.ctx.localAgent.getDelegation(childSessionId) ?? this.ctx.localAgent.memberBinding?.(childSessionId);
222
+ const broker = record === undefined ? undefined : this.ctx.localAgent.harnessForProvider(record.provider)?.modelBroker;
223
+ return await broker?.modelDirectory?.(childSessionId, refresh) ?? null;
224
+ }
225
+ async *followMemberDirectory(childSessionId, signal) {
226
+ const record = this.ctx.localAgent.getDelegation(childSessionId) ?? this.ctx.localAgent.memberBinding?.(childSessionId);
227
+ const broker = record === undefined ? undefined : this.ctx.localAgent.harnessForProvider(record.provider)?.modelBroker;
228
+ if (broker?.followModelDirectory !== undefined)
229
+ yield* broker.followModelDirectory(childSessionId, signal);
230
+ else {
231
+ const directory = await broker?.modelDirectory?.(childSessionId);
232
+ if (directory !== undefined && !signal.aborted)
233
+ yield directory;
234
+ }
235
+ }
236
+ /**
237
+ * Registered harnesses in registration order.
238
+ * @returns the roster rows.
239
+ */
240
+ roster() {
241
+ return this.ctx.localAgent.roster();
242
+ }
243
+ /**
244
+ * The child session ids with an in-flight delegation run (the
245
+ * active-delegation registry's key set). Surfaces that render one-shot
246
+ * subagent rows poll this to mark a row as actually running — the official
247
+ * session summary's `running` flag is agent-based and stays false for
248
+ * external CLI one-shots, which have no live agent — and to offer the
249
+ * stop verb that dispatches `/local-agent stop <childSessionId>`.
250
+ * @returns the in-flight child session ids.
251
+ */
252
+ activeDelegations() {
253
+ return this.ctx.localAgent.activeDelegations();
254
+ }
255
+ /**
256
+ * One harness's auth status, in the default scope or in a named one.
257
+ * @param name - the harness name.
258
+ * @param scope - the named scope to report on; absent means the default
259
+ * scope, so a client written before scopes existed gets exactly the
260
+ * snapshot it always got.
261
+ * @returns the status snapshot.
262
+ */
263
+ status(name, scope) {
264
+ return this.ctx.localAgent.statusOf(name, scope);
265
+ }
266
+ /**
267
+ * One harness's scoped session records, optionally narrowed to the sessions
268
+ * whose working directory is a given dsh session's cwd — the delegations a
269
+ * session's workspace actually produced, so one project's kimi sessions do
270
+ * not surface in another project's session.
271
+ * @param name - the harness name.
272
+ * @param sessionId - optional dsh session whose cwd filters the records.
273
+ * @returns the matching session records.
274
+ */
275
+ async sessions(name, sessionId) {
276
+ const records = await this.ctx.localAgent.sessionsOf(name);
277
+ if (sessionId === undefined)
278
+ return records;
279
+ const cwd = this.ctx.sessions.get(SessionId(sessionId))?.header.cwd;
280
+ if (cwd === undefined)
281
+ return records;
282
+ return records.filter(record => record.workDir === cwd);
283
+ }
284
+ /**
285
+ * The member channel's membership check: the delegation view for one dsh
286
+ * child session, or null when the family never delegated it. The composer
287
+ * chain elects on the session snapshot alone (one-shot subagent), then
288
+ * confirms membership through this Remote — a null answer renders the same
289
+ * read-only panel the official composer shows, never a writable box.
290
+ * The CLI-session resume handle (`cliSessionId`) deliberately stays off the
291
+ * wire: the resume facade resolves it host-side from the record.
292
+ * @param childSessionId - the dsh child session id being viewed.
293
+ * @returns the delegation view, or null for a non-member session.
294
+ */
295
+ memberOf(childSessionId) {
296
+ const registry = this.ctx.localAgent;
297
+ const record = registry.getDelegation(childSessionId);
298
+ if (record === undefined)
299
+ return null;
300
+ const harness = registry.harnessForProvider(record.provider);
301
+ return {
302
+ childSessionId: record.childSessionId,
303
+ provider: record.provider,
304
+ parentSessionId: record.parentSessionId,
305
+ ...harness === undefined ? {} : { harnessDisplayName: harness.displayName },
306
+ };
307
+ }
308
+ /**
309
+ * The model surface of one harness without a member — the settings card's
310
+ * "what would a round run with" read. Null when the harness is unknown or
311
+ * exposes no model broker: the card then keeps its free-text field exactly
312
+ * as before brokers existed. The core fills `lastObserved` from the
313
+ * delegation records (the harness's own provider) when the broker's answer
314
+ * carries none — display context for the cli-builtin layer, never a layer —
315
+ * and appends it to `choices` when no broker choice lists it, so the card's
316
+ * menu offers what last ran instead of staying empty.
317
+ * @param name - the harness name.
318
+ * @returns the layer-by-layer surface, or null.
319
+ */
320
+ async harnessModel(name) {
321
+ const harness = this.ctx.localAgent.get(name);
322
+ if (harness?.modelBroker === undefined)
323
+ return null;
324
+ const info = await harness.modelBroker.modelInfo();
325
+ // A harness without a delegation provider has no records to observe from.
326
+ const observed = harness.delegationProvider === undefined
327
+ ? undefined
328
+ : this.ctx.localAgent.latestObservedModel(harness.delegationProvider);
329
+ return withObservedChoice(info.lastObserved !== undefined || observed === undefined
330
+ ? info
331
+ : { ...info, lastObserved: observed });
332
+ }
333
+ /**
334
+ * The model surface of one member — the composer's picker read. The
335
+ * delegation record's requested model rides in from the core so the broker
336
+ * can rank it between the override and the settings layer; the record's
337
+ * OBSERVED model fills `lastObserved` when the broker's answer carries none
338
+ * (a broker that names one itself always wins — spread order: the broker's
339
+ * answer first, the core's fill only over an absent field) and joins
340
+ * `choices` as the last entry when no broker choice lists it, so a member
341
+ * that ran once has a one-item pick list instead of an empty menu. Null for a
342
+ * non-member session or a brokerless harness.
343
+ * @param childSessionId - the dsh child session id of the member.
344
+ * @returns the layer-by-layer surface, or null.
345
+ */
346
+ async memberModel(childSessionId) {
347
+ const registry = this.ctx.localAgent;
348
+ const observed = registry.getDelegation(childSessionId);
349
+ const record = observed ?? registry.memberBinding?.(childSessionId);
350
+ if (record === undefined)
351
+ return null;
352
+ const broker = registry.harnessForProvider(record.provider)?.modelBroker;
353
+ if (broker === undefined)
354
+ return null;
355
+ let info = await broker.modelInfo(childSessionId, record.model);
356
+ if (broker.configurationAdapter !== undefined) {
357
+ const configuration = registry.memberConfiguration(childSessionId);
358
+ info = { ...info, configuration, switchable: configuration.lockedReason === undefined };
359
+ delete info.reason;
360
+ if (configuration.lockedReason !== undefined)
361
+ info.reason = configuration.lockedReason;
362
+ if (configuration.current.resolved.model !== undefined)
363
+ info.effective = configuration.current.resolved.model;
364
+ }
365
+ return withObservedChoice(info.lastObserved !== undefined || observed?.observedModel === undefined
366
+ ? info
367
+ : { ...info, lastObserved: observed?.observedModel });
368
+ }
369
+ /**
370
+ * Switch a member's session-level model (the composer's picker write). The
371
+ * override outranks the delegation's recorded model and the settings
372
+ * layer; with the live driver on it retires the member's resident runtime
373
+ * so the NEXT round respawns onto the new model — the CLI session itself
374
+ * (its rollout) carries over. Failures arrive structured, never raw.
375
+ * @param childSessionId - the dsh child session id of the member.
376
+ * @param model - the model identifier, or undefined to clear the override
377
+ * (the member then follows the settings layer again).
378
+ * @returns `{ ok: true }` once applied, or a structured error.
379
+ */
380
+ async setMemberModel(childSessionId, model) {
381
+ const registry = this.ctx.localAgent;
382
+ const record = registry.getDelegation(childSessionId);
383
+ if (record === undefined) {
384
+ return { ok: false, error: `localAgent: no delegation recorded for child session ${childSessionId}` };
385
+ }
386
+ const broker = registry.harnessForProvider(record.provider)?.modelBroker;
387
+ if (broker === undefined) {
388
+ return { ok: false, error: `localAgent: ${record.provider} exposes no model broker` };
389
+ }
390
+ try {
391
+ if (broker.configurationAdapter === undefined)
392
+ await broker.setMemberModel(childSessionId, model);
393
+ else
394
+ await registry.setMemberModel(childSessionId, model);
395
+ }
396
+ catch (error) {
397
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
398
+ }
399
+ return { ok: true };
400
+ }
401
+ async memberConfiguration(childSessionId) {
402
+ return this.ctx.localAgent.memberConfiguration(childSessionId);
403
+ }
404
+ async selectMemberConfiguration(childSessionId, requestId, expectedRevision, selection) {
405
+ return this.ctx.localAgent.selectMemberConfiguration(childSessionId, requestId, expectedRevision, selection);
406
+ }
407
+ async cancelMemberConfiguration(childSessionId, requestId, expectedRevision) {
408
+ return this.ctx.localAgent.cancelMemberConfiguration(childSessionId, requestId, expectedRevision);
409
+ }
410
+ async retryMemberConfiguration(childSessionId, expectedRevision) {
411
+ await this.ctx.localAgent.retryMemberConfiguration(childSessionId, expectedRevision);
412
+ }
413
+ followMemberConfiguration(childSessionId, signal) {
414
+ return this.ctx.localAgent.followMemberConfiguration(childSessionId, signal);
415
+ }
416
+ /**
417
+ * Send one human-authored follow-up to a family member: continue the
418
+ * member's SAME CLI session inside the SAME dsh child session. The child
419
+ * session id is the membership proof — the user opened the real child
420
+ * session, and the recorded delegation is the authorization source — so
421
+ * there is no model-forged handle surface; the resume handle never enters
422
+ * the prompt text. The prompt goes through the facade
423
+ * ({@link LocalAgentRegistry.resume}) unchanged: ownership check, resume
424
+ * lock, reattach, and run tracking all apply.
425
+ * @param childSessionId - the dsh child session id of the member.
426
+ * @param text - the human's follow-up message.
427
+ * @returns `{ ok: true }` once the run started, or a structured error
428
+ * (unknown member, parent not live, resume in flight) for the composer to
429
+ * render inline — raw exceptions never cross the wire.
430
+ */
431
+ async promptMember(childSessionId, text, requestId) {
432
+ try {
433
+ return { ok: true, requestId: this.ctx.localAgent.enqueueMemberInput(childSessionId, text, requestId ?? randomUUID()) };
434
+ }
435
+ catch (error) {
436
+ return { ok: false, error: String(error) };
437
+ }
438
+ }
439
+ memberInbox(childSessionId) { return this.ctx.localAgent.readMemberInbox(childSessionId); }
440
+ controlMemberInbox(childSessionId, action, requestId, outcome, evidence) {
441
+ try {
442
+ this.ctx.localAgent.readMemberInbox(childSessionId);
443
+ const inbox = this.ctx.localAgent.memberInbox;
444
+ if (action === 'pause')
445
+ inbox.pause(childSessionId);
446
+ else if (action === 'resume')
447
+ this.ctx.localAgent.resumeMemberInbox(childSessionId);
448
+ else if (action === 'cancel' && requestId !== undefined)
449
+ inbox.cancel(childSessionId, requestId);
450
+ else if (action === 'reconcile' && requestId !== undefined && outcome !== undefined && evidence !== undefined)
451
+ inbox.reconcile(childSessionId, requestId, outcome, evidence);
452
+ else
453
+ throw new Error('Invalid member inbox control');
454
+ return { ok: true };
455
+ }
456
+ catch (error) {
457
+ return { ok: false, error: String(error) };
458
+ }
459
+ }
460
+ /**
461
+ * Interrupt a member's in-flight run (the composer's Stop).
462
+ * @param childSessionId - the dsh child session id of the member.
463
+ * @returns whether an in-flight run was found and signalled.
464
+ */
465
+ stopMember(childSessionId) {
466
+ return this.ctx.localAgent.cancel(childSessionId);
467
+ }
468
+ };
469
+ })();
470
+ export default LocalAgentGateway;