@genesislcap/ai-assistant 15.58.1 → 15.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-assistant.api.json +10096 -6986
- package/dist/ai-assistant.d.ts +545 -101
- package/dist/chat-driver.cjs +624 -207
- package/dist/chat-driver.cjs.map +4 -4
- package/dist/chat-driver.mjs +624 -207
- package/dist/chat-driver.mjs.map +4 -4
- package/dist/custom-elements.json +1836 -378
- package/dist/dts/components/agent-session/agent-session.d.ts +19 -3
- package/dist/dts/components/agent-session/agent-session.d.ts.map +1 -1
- package/dist/dts/components/ai-driver/ai-driver.d.ts +120 -10
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
- package/dist/dts/components/ai-driver/base-driver-decorator.d.ts +103 -0
- package/dist/dts/components/ai-driver/base-driver-decorator.d.ts.map +1 -0
- package/dist/dts/components/ai-driver/index.d.ts +3 -1
- package/dist/dts/components/ai-driver/index.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +84 -8
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/interaction-controller.d.ts +37 -3
- package/dist/dts/components/chat-driver/interaction-controller.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +30 -93
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/index.d.ts +4 -1
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +4 -4
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/state/debug-event-log.d.ts +1 -1
- package/dist/dts/state/debug-event-log.d.ts.map +1 -1
- package/dist/dts/state/interaction-context.d.ts +7 -1
- package/dist/dts/state/interaction-context.d.ts.map +1 -1
- package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
- package/dist/dts/suggestions/generate-suggestions.d.ts.map +1 -1
- package/dist/dts/types/handler-capability.d.ts +28 -0
- package/dist/dts/types/handler-capability.d.ts.map +1 -0
- package/dist/dts/types/interaction-context.d.ts +16 -0
- package/dist/dts/types/interaction-context.d.ts.map +1 -1
- package/dist/dts/types/interaction-interceptor.d.ts +109 -0
- package/dist/dts/types/interaction-interceptor.d.ts.map +1 -0
- package/dist/dts/utils/delegated-message.d.ts +52 -0
- package/dist/dts/utils/delegated-message.d.ts.map +1 -0
- package/dist/dts/utils/history-transform.d.ts.map +1 -1
- package/dist/esm/components/agent-session/agent-session.js +17 -0
- package/dist/esm/components/ai-driver/ai-driver.js +21 -1
- package/dist/esm/components/ai-driver/base-driver-decorator.js +211 -0
- package/dist/esm/components/ai-driver/index.js +2 -1
- package/dist/esm/components/chat-driver/chat-driver.js +195 -14
- package/dist/esm/components/chat-driver/interaction-controller.js +168 -14
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +72 -196
- package/dist/esm/index.js +1 -0
- package/dist/esm/main/main.js +79 -77
- package/dist/esm/state/debug-event-log.js +7 -2
- package/dist/esm/state/interaction-context.js +11 -0
- package/dist/esm/state/persistence/session-persister.js +5 -6
- package/dist/esm/suggestions/generate-suggestions.js +8 -1
- package/dist/esm/types/handler-capability.js +1 -0
- package/dist/esm/types/interaction-interceptor.js +1 -0
- package/dist/esm/utils/delegated-message.js +25 -0
- package/dist/esm/utils/history-transform.js +12 -1
- package/package.json +17 -17
|
@@ -3,10 +3,12 @@ import { AIServiceError, BudgetExhaustedError } from '@genesislcap/foundation-ai
|
|
|
3
3
|
import { validateStaticAgentProviders } from '../../config/validate-providers';
|
|
4
4
|
import { recordMetaEvent } from '../../state/debug-event-log';
|
|
5
5
|
import { reachesProvider } from '../../utils/context-tokens';
|
|
6
|
+
import { DEFAULT_DELEGATE_FRAMING, frameDelegatedContent, } from '../../utils/delegated-message';
|
|
6
7
|
import { transformHistoryForAgent } from '../../utils/history-transform';
|
|
7
8
|
import { logger } from '../../utils/logger';
|
|
8
9
|
import { messageUsage } from '../../utils/sum-usage';
|
|
9
|
-
import {
|
|
10
|
+
import { BaseDriverDecorator } from '../ai-driver/base-driver-decorator';
|
|
11
|
+
import { ChatDriver, REQUEST_CONTINUATION_TOOL } from '../chat-driver/chat-driver';
|
|
10
12
|
const DEFAULT_MAX_HANDOFFS = 3;
|
|
11
13
|
const DEFAULT_CLASSIFIER_HISTORY_LENGTH = 4;
|
|
12
14
|
const DEFAULT_CLASSIFIER_RETRIES = 2;
|
|
@@ -146,9 +148,19 @@ function buildFallbackSystemPrompt(fallback, specialists) {
|
|
|
146
148
|
* and `ChatDriver`, classifying each user message and routing it to the right
|
|
147
149
|
* specialist — each with its own focused system prompt, tools, and primer.
|
|
148
150
|
*
|
|
151
|
+
* A {@link BaseDriverDecorator} over the `ChatDriver` it constructs (GENC-1485, GENC-1660): every
|
|
152
|
+
* `AiDriver` member and event it does not override passes straight through. Its inner driver is
|
|
153
|
+
* always one it built, never a composition choice, because routing reaches `ChatDriver`-only
|
|
154
|
+
* members (`installAgent`, `agentSession`, `getHistory`, `setProviderHistoryTransform`, the
|
|
155
|
+
* release flag and the `report…` exits). Other decorators go outside it.
|
|
156
|
+
*
|
|
149
157
|
* @beta
|
|
150
158
|
*/
|
|
151
|
-
export class OrchestratingDriver extends
|
|
159
|
+
export class OrchestratingDriver extends BaseDriverDecorator {
|
|
160
|
+
/** The inner driver this one built and routes onto. */
|
|
161
|
+
get chatDriver() {
|
|
162
|
+
return this.inner;
|
|
163
|
+
}
|
|
152
164
|
/**
|
|
153
165
|
* The stateful-agent contract (§7.1): active agent, user pin, flow lock, restored state, and
|
|
154
166
|
* the `onActivate` / `onDeactivate` hooks.
|
|
@@ -173,7 +185,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
173
185
|
}
|
|
174
186
|
constructor(providerRegistry, agents, options = {}) {
|
|
175
187
|
var _a, _b, _c, _d;
|
|
176
|
-
super();
|
|
188
|
+
super(OrchestratingDriver.createInner(providerRegistry, agents, options));
|
|
177
189
|
this.providerRegistry = providerRegistry;
|
|
178
190
|
this.agents = agents;
|
|
179
191
|
/**
|
|
@@ -198,10 +210,6 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
198
210
|
this.classifierHistoryLength =
|
|
199
211
|
(_c = options.classifierHistoryLength) !== null && _c !== void 0 ? _c : DEFAULT_CLASSIFIER_HISTORY_LENGTH;
|
|
200
212
|
this.classifierRetries = (_d = options.classifierRetries) !== null && _d !== void 0 ? _d : DEFAULT_CLASSIFIER_RETRIES;
|
|
201
|
-
// Static-name validation: walk every agent (and nested sub-agents). Any
|
|
202
|
-
// `provider: '<name>'` that isn't registered, or resolves to a provider
|
|
203
|
-
// without `chat()`, throws now rather than at first turn.
|
|
204
|
-
validateStaticAgentProviders(agents, providerRegistry);
|
|
205
213
|
// Specialists drive the classifier. `excludeFromClassifier` agents are still
|
|
206
214
|
// resolvable by name (so manual pinning works) but never auto-routed.
|
|
207
215
|
this.specialists = agents.filter(isSpecialist).filter((a) => !a.excludeFromClassifier);
|
|
@@ -212,151 +220,28 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
212
220
|
const rawFallback = fallbacks[0];
|
|
213
221
|
this.fallback = rawFallback
|
|
214
222
|
? Object.assign(Object.assign({}, rawFallback), { systemPrompt: buildFallbackSystemPrompt(rawFallback, this.specialists) }) : undefined;
|
|
215
|
-
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Build the inner driver, after validating the agents' providers, so a bad config throws before
|
|
226
|
+
* a driver exists to subscribe to the registry. Static because it runs before `super()`.
|
|
227
|
+
*/
|
|
228
|
+
static createInner(providerRegistry, agents, options = {}) {
|
|
229
|
+
var _a;
|
|
230
|
+
// Static-name validation: walk every agent (and nested sub-agents). Any
|
|
231
|
+
// `provider: '<name>'` that isn't registered, or resolves to a provider
|
|
232
|
+
// without `chat()`, throws now rather than at first turn.
|
|
233
|
+
validateStaticAgentProviders(agents, providerRegistry);
|
|
234
|
+
return new ChatDriver(providerRegistry, {
|
|
216
235
|
maxToolIterations: options.maxToolIterations,
|
|
217
236
|
maxFoldOperations: options.maxFoldOperations,
|
|
218
237
|
maxTurnSnapshots: options.maxTurnSnapshots,
|
|
219
|
-
sessionKey:
|
|
238
|
+
sessionKey: (_a = options.sessionKey) !== null && _a !== void 0 ? _a : '',
|
|
220
239
|
activityBus: options.activityBus,
|
|
221
240
|
budgetExhaustedMessage: options.budgetExhaustedMessage,
|
|
222
241
|
aiServiceErrorMessages: options.aiServiceErrorMessages,
|
|
223
|
-
//
|
|
242
|
+
// A release ends this driver's handoff loop, so it acts on the flag itself; see the option.
|
|
224
243
|
deferAgentRelease: true,
|
|
225
244
|
});
|
|
226
|
-
// Proxy events from the shared driver
|
|
227
|
-
this.chatDriver.addEventListener('history-updated', (e) => {
|
|
228
|
-
this.dispatchEvent(new CustomEvent('history-updated', { detail: e.detail }));
|
|
229
|
-
});
|
|
230
|
-
this.chatDriver.addEventListener('sub-agent-history-updated', (e) => {
|
|
231
|
-
this.dispatchEvent(new CustomEvent('sub-agent-history-updated', { detail: e.detail }));
|
|
232
|
-
});
|
|
233
|
-
this.chatDriver.addEventListener('sub-agent-start', (e) => {
|
|
234
|
-
this.dispatchEvent(new CustomEvent('sub-agent-start', { detail: e.detail }));
|
|
235
|
-
});
|
|
236
|
-
this.chatDriver.addEventListener('sub-agent-stop', (e) => {
|
|
237
|
-
this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: e.detail }));
|
|
238
|
-
});
|
|
239
|
-
this.chatDriver.addEventListener('interaction-start', (e) => {
|
|
240
|
-
this.dispatchEvent(new CustomEvent('interaction-start', { detail: e.detail }));
|
|
241
|
-
});
|
|
242
|
-
this.chatDriver.addEventListener('interaction-stop', (e) => {
|
|
243
|
-
this.dispatchEvent(new CustomEvent('interaction-stop', { detail: e.detail }));
|
|
244
|
-
});
|
|
245
|
-
this.chatDriver.addEventListener('provider-changed', (e) => {
|
|
246
|
-
this.dispatchEvent(new CustomEvent('provider-changed', { detail: e.detail }));
|
|
247
|
-
});
|
|
248
|
-
// Post-resolve external cost. The host only ever holds THIS wrapper (`createDriver` returns
|
|
249
|
-
// one for any non-empty `agents`), so an event the inner driver raises and this list omits is
|
|
250
|
-
// an event the host never sees: `recordExternalCost` still delegates and the money still lands
|
|
251
|
-
// on the message, but the totals never refresh and the save is never scheduled — and in the
|
|
252
|
-
// flow this exists for the interaction is the last thing in the session, so "stale until the
|
|
253
|
-
// next history change" means permanently. Reviewer catch on #2474.
|
|
254
|
-
this.chatDriver.addEventListener('external-cost-recorded', (e) => {
|
|
255
|
-
this.dispatchEvent(new CustomEvent('external-cost-recorded', { detail: e.detail }));
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
resolveInteraction(interactionId, result) {
|
|
259
|
-
this.chatDriver.resolveInteraction(interactionId, result);
|
|
260
|
-
}
|
|
261
|
-
/** Delegated for the same reason as `resolveInteraction`: the history that owns the
|
|
262
|
-
* interaction — and therefore the cost — lives on the wrapped driver, not here. */
|
|
263
|
-
recordExternalCost(interactionId, costUsd) {
|
|
264
|
-
return this.chatDriver.recordExternalCost(interactionId, costUsd);
|
|
265
|
-
}
|
|
266
|
-
getInteractionContext(interactionId) {
|
|
267
|
-
return this.chatDriver.getInteractionContext(interactionId);
|
|
268
|
-
}
|
|
269
|
-
isBusy() {
|
|
270
|
-
return this.chatDriver.isBusy();
|
|
271
|
-
}
|
|
272
|
-
/** Currently active provider name from the underlying ChatDriver. */
|
|
273
|
-
getActiveProviderName() {
|
|
274
|
-
return this.chatDriver.getActiveProviderName();
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Pins routing to a specific agent by name. While pinned, the classifier is
|
|
278
|
-
* skipped and the continuation tool is hidden from the agent's tool list, so
|
|
279
|
-
* the agent cannot quietly hand back to the orchestrator. Pass `null` to
|
|
280
|
-
* return to automatic routing.
|
|
281
|
-
*/
|
|
282
|
-
setPinnedAgent(name) {
|
|
283
|
-
this.agentSession.setPinned(name);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Set the flow-owner lock — used to restore state from Redux on driver
|
|
287
|
-
* reconstruction (agents-array changes, pop-in/pop-out). Not intended for
|
|
288
|
-
* external callers to manipulate routing; that's what `setPinnedAgent` is
|
|
289
|
-
* for.
|
|
290
|
-
*/
|
|
291
|
-
setFlowOwner(name) {
|
|
292
|
-
this.agentSession.setFlowOwner(name);
|
|
293
|
-
}
|
|
294
|
-
loadHistory(messages) {
|
|
295
|
-
this.chatDriver.loadHistory(messages);
|
|
296
|
-
}
|
|
297
|
-
getRawHistory() {
|
|
298
|
-
return this.chatDriver.getHistory();
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Delegates to the inner {@link ChatDriver} — condensation policies are registered there, so it
|
|
302
|
-
* is the only object that knows which payloads the model has stopped seeing (GENC-1566).
|
|
303
|
-
*
|
|
304
|
-
* **This forward is the whole feature, for any multi-agent host.** `AiDriver` declares
|
|
305
|
-
* `getHistoryForPersistence` optional, and `SessionPersister` calls it through `?.`, falling back
|
|
306
|
-
* to {@link OrchestratingDriver.getRawHistory}. This class does NOT extend `ChatDriver` — it
|
|
307
|
-
* wraps one — so without an explicit forward the optional call resolves to `undefined` and every
|
|
308
|
-
* host on an orchestrating driver silently keeps persisting the full payloads. Measured exactly
|
|
309
|
-
* that way on a Create run: 10 `context.condensed` events fired, and the session still stored
|
|
310
|
-
* the two largest `read_context` results at 26,907 and 23,060 chars. The method existed, the
|
|
311
|
-
* tests passed, and the feature did nothing.
|
|
312
|
-
*/
|
|
313
|
-
getHistoryForPersistence() {
|
|
314
|
-
return this.chatDriver.getHistoryForPersistence();
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Delegates to the inner {@link ChatDriver}, which owns the condensation registry and clocks
|
|
318
|
-
* (GENC-1632). The forward matters for the same reason as `getHistoryForPersistence` above: the
|
|
319
|
-
* persister reaches it through `?.`, so a missing forward would compile, pass the ChatDriver
|
|
320
|
-
* tests, and do nothing for every orchestrated host — which is every host with an agents array.
|
|
321
|
-
*/
|
|
322
|
-
getCondensePoliciesForPersistence(messages) {
|
|
323
|
-
return this.chatDriver.getCondensePoliciesForPersistence(messages);
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Delegates to the inner {@link ChatDriver} (GENC-1632). The deferred activation stamp it
|
|
327
|
-
* performs is taken by the inner driver's `installAgent`, which this driver's own
|
|
328
|
-
* `installAgent` always reaches, so nothing extra is needed here.
|
|
329
|
-
*/
|
|
330
|
-
restoreCondensePolicies(entries) {
|
|
331
|
-
return this.chatDriver.restoreCondensePolicies(entries);
|
|
332
|
-
}
|
|
333
|
-
/** {@inheritDoc AiDriver.setContextGuard} */
|
|
334
|
-
setContextGuard(policy) {
|
|
335
|
-
this.chatDriver.setContextGuard(policy);
|
|
336
|
-
}
|
|
337
|
-
/** {@inheritDoc AiDriver.compact} */
|
|
338
|
-
compact(options) {
|
|
339
|
-
return this.chatDriver.compact(options);
|
|
340
|
-
}
|
|
341
|
-
/** {@inheritDoc AiDriver.canCompact} */
|
|
342
|
-
canCompact(options) {
|
|
343
|
-
return this.chatDriver.canCompact(options);
|
|
344
|
-
}
|
|
345
|
-
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
346
|
-
getPreambleTokens() {
|
|
347
|
-
return this.chatDriver.getPreambleTokens();
|
|
348
|
-
}
|
|
349
|
-
/** {@inheritDoc AiDriver.getCompactionPlan} */
|
|
350
|
-
getCompactionPlan(options) {
|
|
351
|
-
return this.chatDriver.getCompactionPlan(options);
|
|
352
|
-
}
|
|
353
|
-
/** Delegates to the inner {@link ChatDriver} — turns are captured there. */
|
|
354
|
-
getTurnSnapshots() {
|
|
355
|
-
return this.chatDriver.getTurnSnapshots();
|
|
356
|
-
}
|
|
357
|
-
/** Delegates to the inner {@link ChatDriver} — interactions resolve there, so it holds the buffer. */
|
|
358
|
-
getExternalDiagnostics() {
|
|
359
|
-
return this.chatDriver.getExternalDiagnostics();
|
|
360
245
|
}
|
|
361
246
|
getSuggestions(history, prompt, count, allAgentInfo) {
|
|
362
247
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -375,10 +260,18 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
375
260
|
return this.chatDriver.getSuggestions(history, prompt, count, agentInfo);
|
|
376
261
|
});
|
|
377
262
|
}
|
|
378
|
-
sendMessage(input, attachments) {
|
|
263
|
+
sendMessage(input, attachments, options) {
|
|
379
264
|
return __awaiter(this, void 0, void 0, function* () {
|
|
265
|
+
var _a;
|
|
266
|
+
// Who it is from travels with every copy of the message this method makes (GENC-1660).
|
|
267
|
+
const delegated = (options === null || options === void 0 ? void 0 : options.delegate)
|
|
268
|
+
? {
|
|
269
|
+
delegate: options.delegate,
|
|
270
|
+
delegateFraming: (_a = options.delegateFraming) !== null && _a !== void 0 ? _a : DEFAULT_DELEGATE_FRAMING,
|
|
271
|
+
}
|
|
272
|
+
: {};
|
|
380
273
|
try {
|
|
381
|
-
return yield this.runOrchestratedTurn(input, attachments);
|
|
274
|
+
return yield this.runOrchestratedTurn(input, attachments, options, delegated);
|
|
382
275
|
}
|
|
383
276
|
catch (e) {
|
|
384
277
|
// The classifier calls the provider directly, outside any ChatDriver turn,
|
|
@@ -398,7 +291,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
398
291
|
// snapshot, and the history sent to the model once the budget is raised.
|
|
399
292
|
const pendingUserMessage = this.userMessageAppended
|
|
400
293
|
? undefined
|
|
401
|
-
: Object.assign({ role: 'user', content: input }, (attachments ? { attachments } : {}));
|
|
294
|
+
: Object.assign(Object.assign({ role: 'user', content: input }, (attachments ? { attachments } : {})), delegated);
|
|
402
295
|
if (e instanceof BudgetExhaustedError) {
|
|
403
296
|
return this.chatDriver.reportBudgetExhausted(e, pendingUserMessage);
|
|
404
297
|
}
|
|
@@ -410,7 +303,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
410
303
|
}
|
|
411
304
|
});
|
|
412
305
|
}
|
|
413
|
-
runOrchestratedTurn(input, attachments) {
|
|
306
|
+
runOrchestratedTurn(input, attachments, options, delegated) {
|
|
414
307
|
return __awaiter(this, void 0, void 0, function* () {
|
|
415
308
|
this.cancelled = false;
|
|
416
309
|
this.userMessageAppended = false;
|
|
@@ -418,7 +311,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
418
311
|
// Emit the user message immediately so the UI reflects it during the classify
|
|
419
312
|
// round-trip — without this the chat appears frozen until classify returns.
|
|
420
313
|
this.dispatchEvent(new CustomEvent('history-updated', {
|
|
421
|
-
detail: [...history, { role: 'user', content: input, attachments }],
|
|
314
|
+
detail: [...history, Object.assign({ role: 'user', content: input, attachments }, delegated)],
|
|
422
315
|
}));
|
|
423
316
|
const pinned = this.resolvePinnedAgent();
|
|
424
317
|
if (!pinned)
|
|
@@ -432,7 +325,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
432
325
|
routed = { agent: pinned, decision: 'pinned' };
|
|
433
326
|
}
|
|
434
327
|
else {
|
|
435
|
-
routed = yield this.classify(input, history, this.activeAgent);
|
|
328
|
+
routed = yield this.classify(delegated.delegate ? frameDelegatedContent(input, delegated.delegateFraming) : input, history, this.activeAgent);
|
|
436
329
|
}
|
|
437
330
|
let currentAgent = routed.agent;
|
|
438
331
|
let isHandoff = false;
|
|
@@ -503,7 +396,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
503
396
|
// handoff classify) sees the append as done.
|
|
504
397
|
this.userMessageAppended = true;
|
|
505
398
|
// oxlint-disable-next-line no-await-in-loop
|
|
506
|
-
result = yield this.chatDriver.sendMessage(input, attachments);
|
|
399
|
+
result = yield this.chatDriver.sendMessage(input, attachments, options);
|
|
507
400
|
}
|
|
508
401
|
lastResult = result;
|
|
509
402
|
// Release check: a stateful agent called `releaseAgent` from a terminal
|
|
@@ -559,20 +452,11 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
559
452
|
// install — leaves it shown only by the optimistic dispatch above, and it would vanish on the
|
|
560
453
|
// next update and from a reload. Kept, as the budget wall keeps it (see sendMessage).
|
|
561
454
|
if (this.cancelled && !this.userMessageAppended) {
|
|
562
|
-
this.chatDriver.reportStoppedBeforeTurn(Object.assign({ role: 'user', content: input }, (attachments ? { attachments } : {})));
|
|
455
|
+
this.chatDriver.reportStoppedBeforeTurn(Object.assign(Object.assign({ role: 'user', content: input }, (attachments ? { attachments } : {})), delegated));
|
|
563
456
|
}
|
|
564
457
|
return (lastResult === null || lastResult === void 0 ? void 0 : lastResult.reason) === 'done' ? lastResult : { reason: 'done' };
|
|
565
458
|
});
|
|
566
459
|
}
|
|
567
|
-
continueFromHistory(transientPrimer, options) {
|
|
568
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
569
|
-
return this.chatDriver.continueFromHistory(transientPrimer, options);
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
/** {@inheritDoc AiDriver.primeRestoredAgentState} */
|
|
573
|
-
primeRestoredAgentState(snapshots) {
|
|
574
|
-
this.agentSession.primeRestoredStates(snapshots);
|
|
575
|
-
}
|
|
576
460
|
/** {@inheritDoc AiDriver.canRestoreFlowOwner} */
|
|
577
461
|
canRestoreFlowOwner(agentName) {
|
|
578
462
|
return this.agents.some((a) => a.name === agentName);
|
|
@@ -589,6 +473,10 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
589
473
|
* to classify, and a restored lock already says which agent owns the flow. `continueFromHistory`
|
|
590
474
|
* on its own would not do — it neither routes nor installs, so it would run on whatever agent
|
|
591
475
|
* happened to be installed (none, straight after a reload).
|
|
476
|
+
*
|
|
477
|
+
* Looks the owner up in its own agents list, so the `agent` argument is not needed and is
|
|
478
|
+
* ignored; and does not delegate to the inner driver's resume, which would install the agent
|
|
479
|
+
* undecorated.
|
|
592
480
|
*/
|
|
593
481
|
resumeRestoredFlow(resumeNote) {
|
|
594
482
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -659,19 +547,12 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
659
547
|
}
|
|
660
548
|
return winner ? Object.assign(Object.assign({}, winner), { agentName, basis: 'reachable-max' }) : undefined;
|
|
661
549
|
}
|
|
662
|
-
/** {@inheritDoc AiDriver.getActiveAgent} */
|
|
663
|
-
getActiveAgent() {
|
|
664
|
-
return this.agentSession.getActive();
|
|
665
|
-
}
|
|
666
550
|
installAgent(agent) {
|
|
667
551
|
return __awaiter(this, void 0, void 0, function* () {
|
|
668
552
|
// The transition — handoff record, lifecycle hooks, restored state, flow lock — belongs to
|
|
669
|
-
// the session
|
|
670
|
-
// what the transcript says happened.
|
|
671
|
-
const { previousAgent
|
|
672
|
-
if (flowOwnerChangedTo !== undefined) {
|
|
673
|
-
this.dispatchEvent(new CustomEvent('flow-owner-changed', { detail: flowOwnerChangedTo }));
|
|
674
|
-
}
|
|
553
|
+
// the session, and the inner driver raises its events (GENC-1485). What is left below is this
|
|
554
|
+
// driver's own job: what the agent may route to, and what the transcript says happened.
|
|
555
|
+
const { previousAgent } = yield this.agentSession.activate(agent);
|
|
675
556
|
// Terminal agents do not get the cross-agent handoff tool. Four cases:
|
|
676
557
|
// • fallback — already a leaf; handoff would loop
|
|
677
558
|
// • user-pinned — user explicitly selected this agent; do not auto-route away
|
|
@@ -707,13 +588,12 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
707
588
|
this.chatDriver.setProviderHistoryTransform((h) => transformHistoryForAgent(h, agent.name));
|
|
708
589
|
this.chatDriver.installAgent(agentToApply);
|
|
709
590
|
this.dispatchEvent(new CustomEvent('orchestrating-stop'));
|
|
710
|
-
this.dispatchEvent(new CustomEvent('agent-changed', { detail: agent }));
|
|
711
591
|
});
|
|
712
592
|
}
|
|
713
593
|
/**
|
|
714
|
-
* Release the current stateful agent: fire `onDeactivate
|
|
715
|
-
*
|
|
716
|
-
* unlocked state. Called automatically when a tool handler invokes
|
|
594
|
+
* Release the current stateful agent: fire `onDeactivate` and clear the flow-owner lock. The
|
|
595
|
+
* inner driver raises the events from the session's transition, so the host (and Redux) reflect
|
|
596
|
+
* the unlocked state (GENC-1485). Called automatically when a tool handler invokes
|
|
717
597
|
* `context.releaseAgent`.
|
|
718
598
|
*
|
|
719
599
|
* The user-pin (`pinnedAgentName`) is intentionally *not* cleared — a user
|
|
@@ -723,14 +603,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
723
603
|
*/
|
|
724
604
|
releaseActiveAgent() {
|
|
725
605
|
return __awaiter(this, void 0, void 0, function* () {
|
|
726
|
-
|
|
727
|
-
if (!released)
|
|
728
|
-
return;
|
|
729
|
-
if (released.flowOwnerChangedTo !== undefined) {
|
|
730
|
-
this.dispatchEvent(new CustomEvent('flow-owner-changed', { detail: released.flowOwnerChangedTo }));
|
|
731
|
-
}
|
|
732
|
-
this.dispatchEvent(new CustomEvent('agent-released', { detail: released.previousAgent }));
|
|
733
|
-
this.dispatchEvent(new CustomEvent('agent-changed', { detail: undefined }));
|
|
606
|
+
yield this.agentSession.release();
|
|
734
607
|
});
|
|
735
608
|
}
|
|
736
609
|
/**
|
|
@@ -755,6 +628,7 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
755
628
|
yield this.agentSession.dispose();
|
|
756
629
|
// Tear down the inner driver too, so any in-flight provider request aborts.
|
|
757
630
|
yield this.chatDriver.dispose();
|
|
631
|
+
this.detach();
|
|
758
632
|
});
|
|
759
633
|
}
|
|
760
634
|
/**
|
|
@@ -796,9 +670,12 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
796
670
|
.filter((m) => { var _a; return !!((_a = m.content) === null || _a === void 0 ? void 0 : _a.trim()); })
|
|
797
671
|
.slice(-this.classifierHistoryLength)
|
|
798
672
|
.map((m) => {
|
|
799
|
-
var _a;
|
|
673
|
+
var _a, _b;
|
|
800
674
|
const speaker = m.role === 'user' ? 'User' : 'Assistant';
|
|
801
|
-
|
|
675
|
+
// A delegated message is framed for the router as for every model (GENC-1660).
|
|
676
|
+
const content = m.role === 'user' && m.delegate
|
|
677
|
+
? frameDelegatedContent((_a = m.content) !== null && _a !== void 0 ? _a : '', m.delegateFraming)
|
|
678
|
+
: ((_b = m.content) !== null && _b !== void 0 ? _b : '');
|
|
802
679
|
const body = content.length > CLASSIFIER_MESSAGE_CHARS
|
|
803
680
|
? `${content.slice(0, CLASSIFIER_MESSAGE_CHARS)}…`
|
|
804
681
|
: content;
|
|
@@ -1019,20 +896,19 @@ export class OrchestratingDriver extends EventTarget {
|
|
|
1019
896
|
}
|
|
1020
897
|
}
|
|
1021
898
|
/**
|
|
1022
|
-
*
|
|
899
|
+
* The orchestrator in a driver's decorator stack, or `undefined` when there is none (a bare
|
|
900
|
+
* `ChatDriver`, possibly decorated).
|
|
1023
901
|
*
|
|
1024
|
-
* **The one place in the package that tests for this type** (`docs/code-health.md`
|
|
1025
|
-
*
|
|
1026
|
-
* flow-owner lock, the context guard
|
|
1027
|
-
*
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1030
|
-
* Lives beside the class rather than on the assistant element because two modules
|
|
1031
|
-
* need it: the element (for its own driver) and the session persister (for the
|
|
1032
|
-
* driver it restores into), and a private element accessor cannot serve both.
|
|
902
|
+
* **The one place in the package that tests for this type** (`docs/code-health.md` §11.2
|
|
903
|
+
* constraint 3). Since GENC-1660 nothing behavioural goes through it: the agent pin, the
|
|
904
|
+
* flow-owner lock, the context guard and the lifecycle events are all reached on `AiDriver`
|
|
905
|
+
* itself, which every decorator forwards. What is left is labelling — the host's `driverKind`
|
|
906
|
+
* in its log lines — and it looks through decorators so that label stays true behind one.
|
|
1033
907
|
*
|
|
1034
908
|
* @internal
|
|
1035
909
|
*/
|
|
1036
910
|
export function asOrchestrator(driver) {
|
|
1037
|
-
|
|
911
|
+
if (!driver)
|
|
912
|
+
return undefined;
|
|
913
|
+
return BaseDriverDecorator.layers(driver).find((layer) => layer instanceof OrchestratingDriver);
|
|
1038
914
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export * from './provider/ai-provider-switcher';
|
|
|
17
17
|
export * from './provider/tiered-provider-switcher';
|
|
18
18
|
export * from './provider/assistant-app-settings';
|
|
19
19
|
export * from './utils/tool-fold';
|
|
20
|
+
export { DEFAULT_DELEGATE_FRAMING, isDelegated, } from './utils/delegated-message';
|
|
20
21
|
export { assistantSettingsSectionTitleStyles } from './styles/settings-section';
|
|
21
22
|
// MARKDOWN_EXPORTPARTS travels with the component: a host rendering `<ai-chat-markdown>` in its
|
|
22
23
|
// own shadow root has to forward its parts, and hand-copying the list is how it drifts.
|