@genesislcap/ai-assistant 15.56.0 → 15.58.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 +438 -8
- package/dist/ai-assistant.d.ts +120 -4
- package/dist/chat-driver.cjs +60 -9
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +60 -9
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +238 -3
- package/dist/dts/components/agent-session/agent-session.d.ts +9 -0
- package/dist/dts/components/agent-session/agent-session.d.ts.map +1 -1
- package/dist/dts/components/ai-driver/ai-driver.d.ts +31 -2
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +18 -2
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +15 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/config/config.d.ts +21 -0
- package/dist/dts/config/config.d.ts.map +1 -1
- package/dist/dts/config/define-stateful-agent.d.ts +6 -0
- package/dist/dts/config/define-stateful-agent.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +21 -0
- 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/persistence/resume-verdict.d.ts +32 -0
- package/dist/dts/state/persistence/resume-verdict.d.ts.map +1 -0
- package/dist/dts/state/persistence/session-persister.d.ts +34 -1
- package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
- package/dist/dts/state/persistence/session-snapshot.d.ts +19 -0
- package/dist/dts/state/persistence/session-snapshot.d.ts.map +1 -1
- package/dist/dts/utils/message-partition.d.ts +9 -1
- package/dist/dts/utils/message-partition.d.ts.map +1 -1
- package/dist/esm/components/agent-session/agent-session.js +14 -0
- package/dist/esm/components/chat-driver/chat-driver.js +12 -5
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +34 -2
- package/dist/esm/config/define-stateful-agent.js +1 -0
- package/dist/esm/main/main.js +101 -22
- package/dist/esm/state/debug-event-log.js +4 -0
- package/dist/esm/state/persistence/resume-verdict.js +20 -0
- package/dist/esm/state/persistence/session-persister.js +55 -15
- package/dist/esm/state/persistence/session-snapshot.js +67 -0
- package/dist/esm/utils/message-partition.js +11 -2
- package/package.json +17 -17
package/dist/ai-assistant.d.ts
CHANGED
|
@@ -449,6 +449,8 @@ export declare class AgentSession {
|
|
|
449
449
|
* activation, then deleted so a later re-activation starts fresh.
|
|
450
450
|
*/
|
|
451
451
|
private restoredStates;
|
|
452
|
+
/** The tail of the activation queue — see {@link AgentSession.activate}. */
|
|
453
|
+
private activation;
|
|
452
454
|
constructor(deps: AgentSessionDeps);
|
|
453
455
|
/** The active agent, or `undefined` before the first activation and after a release. */
|
|
454
456
|
getActive(): AgentConfig | undefined;
|
|
@@ -481,8 +483,15 @@ export declare class AgentSession {
|
|
|
481
483
|
*
|
|
482
484
|
* Re-activating the same agent by name is not a switch: no hooks fire, no lock moves, and no
|
|
483
485
|
* handoff is recorded. That guard matters because a per-turn re-resolve calls through here.
|
|
486
|
+
*
|
|
487
|
+
* Single-flight (GENC-1662): calls run one after another, never interleaved. `active` is only
|
|
488
|
+
* set once the hooks have finished, so two overlapping calls for the same agent would otherwise
|
|
489
|
+
* both see a switch and run `onActivate` twice — and a restored `init` would be overwritten by a
|
|
490
|
+
* fresh one that finished later. That overlap became possible when a restore started activating
|
|
491
|
+
* the flow owner outside a turn, where a send can land mid-activation.
|
|
484
492
|
*/
|
|
485
493
|
activate(agent: AgentConfig): Promise<AgentTransition>;
|
|
494
|
+
private activateNow;
|
|
486
495
|
/**
|
|
487
496
|
* Release the active agent: fire `onDeactivate` and drop the flow lock.
|
|
488
497
|
*
|
|
@@ -767,7 +776,7 @@ export declare interface AiDriver extends EventTarget {
|
|
|
767
776
|
* `turnSignal`. A continuation after the user stopped that message is not
|
|
768
777
|
* part of it, and gets a fresh one.
|
|
769
778
|
*/
|
|
770
|
-
continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult>;
|
|
779
|
+
continueFromHistory(transientPrimer?: ChatMessage[], options?: ContinueFromHistoryOptions): Promise<ChatDriverResult>;
|
|
771
780
|
/**
|
|
772
781
|
* Resolve a pending blocking interaction with the given result.
|
|
773
782
|
*/
|
|
@@ -803,6 +812,35 @@ export declare interface AiDriver extends EventTarget {
|
|
|
803
812
|
* shipped drivers implement it and a host no longer has to feature-detect before restoring.
|
|
804
813
|
*/
|
|
805
814
|
primeRestoredAgentState(snapshots: Record<string, unknown>): void;
|
|
815
|
+
/**
|
|
816
|
+
* Whether a restore can bring back the flow `agentName` owns (GENC-1662): the agent is configured
|
|
817
|
+
* here. Pure — no activation. A restore re-activates only an owner this answers `true` for.
|
|
818
|
+
*
|
|
819
|
+
* Optional: a driver without it never re-activates or resumes.
|
|
820
|
+
*
|
|
821
|
+
* @beta
|
|
822
|
+
*/
|
|
823
|
+
canRestoreFlowOwner?(agentName: string): boolean;
|
|
824
|
+
/**
|
|
825
|
+
* Whether a restored flow owned by `agentName` should also RESUME — run a turn on its own — when
|
|
826
|
+
* the reload interrupted one (GENC-1662): the agent is configured here and has not opted out with
|
|
827
|
+
* `resumeOnRestore: false`. Pure. Lets the restore pick its divider wording.
|
|
828
|
+
*
|
|
829
|
+
* @beta
|
|
830
|
+
*/
|
|
831
|
+
canResumeRestoredFlow?(agentName: string): boolean;
|
|
832
|
+
/**
|
|
833
|
+
* Bring a restored session's flow back to life (GENC-1662). Activates the flow owner — a
|
|
834
|
+
* stateful agent, the only kind that holds a flow — so its `init({ restored })` runs now rather
|
|
835
|
+
* than on the next message, then, when `resumeNote` is given and the agent has not opted out,
|
|
836
|
+
* runs one turn from the restored history with the note in the tail of its first model call.
|
|
837
|
+
*
|
|
838
|
+
* Returns the turn's result when one ran, `undefined` otherwise (no flow owner, the owner is not
|
|
839
|
+
* configured, or no note). Never throws for those cases.
|
|
840
|
+
*
|
|
841
|
+
* @beta
|
|
842
|
+
*/
|
|
843
|
+
resumeRestoredFlow?(resumeNote?: string): Promise<ChatDriverResult | undefined>;
|
|
806
844
|
/**
|
|
807
845
|
* Return the full, unredacted conversation history.
|
|
808
846
|
*/
|
|
@@ -1434,6 +1472,27 @@ declare interface BaseAgentConfig {
|
|
|
1434
1472
|
* @beta
|
|
1435
1473
|
*/
|
|
1436
1474
|
notResumableMessage?: string;
|
|
1475
|
+
/**
|
|
1476
|
+
* Whether a restored session whose flow this agent owns continues on its own after a page reload
|
|
1477
|
+
* (GENC-1662). Defaults to `true`; set `false` to keep the old behaviour of waiting for the user.
|
|
1478
|
+
*
|
|
1479
|
+
* Only meaningful on a STATEFUL agent (one with `onActivate`/`onDeactivate`, e.g. built with
|
|
1480
|
+
* `defineStatefulAgent`) — only those own a flow, so on any other agent this is a no-op.
|
|
1481
|
+
*
|
|
1482
|
+
* Applies when the reload interrupted a turn: an unanswered tool call (often one waiting on a
|
|
1483
|
+
* widget, which is a promise inside a running handler and cannot be persisted, so the restore
|
|
1484
|
+
* trims it), tool results the model had not yet answered, or a user message with no reply yet.
|
|
1485
|
+
* With this on, the restore runs one turn from the restored history, with a note in the tail of
|
|
1486
|
+
* its first model call saying what was cut. That turn is a fresh model decision — it usually asks
|
|
1487
|
+
* the same question again, but may word it differently or pick another valid action.
|
|
1488
|
+
*
|
|
1489
|
+
* A restored flow owner is re-activated either way, so its `init({ restored })` runs straight
|
|
1490
|
+
* after the reload rather than on the next message. Never consulted for a session restored as
|
|
1491
|
+
* interrupted ({@link BaseAgentConfig.resumable} returned `false`).
|
|
1492
|
+
*
|
|
1493
|
+
* @beta
|
|
1494
|
+
*/
|
|
1495
|
+
resumeOnRestore?: boolean;
|
|
1437
1496
|
/**
|
|
1438
1497
|
* Tokens this agent wants kept free for one of its turns (GENC-1567).
|
|
1439
1498
|
* Overrides `chatConfig.context.reserveTokens` while this agent is active;
|
|
@@ -2559,9 +2618,13 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
|
|
|
2559
2618
|
private invokeSubAgent;
|
|
2560
2619
|
/**
|
|
2561
2620
|
* Continue the tool loop from current history without appending a new user message.
|
|
2562
|
-
* Used by OrchestratingDriver after an agent handoff.
|
|
2621
|
+
* Used by OrchestratingDriver after an agent handoff, and to resume a restored flow (GENC-1662).
|
|
2622
|
+
*
|
|
2623
|
+
* `options.tailNote` rides the framed tail of the FIRST model call only — after the history, where
|
|
2624
|
+
* a note about the conversation belongs — and is dropped once the model has answered, so it
|
|
2625
|
+
* cannot go stale over the rest of the loop. Contrast `transientPrimer`, which leads the request.
|
|
2563
2626
|
*/
|
|
2564
|
-
continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult>;
|
|
2627
|
+
continueFromHistory(transientPrimer?: ChatMessage[], options?: ContinueFromHistoryOptions): Promise<ChatDriverResult>;
|
|
2565
2628
|
private runToolLoop;
|
|
2566
2629
|
/**
|
|
2567
2630
|
* Append prose the DRIVER wrote rather than the model — a failure notice, a limit explanation,
|
|
@@ -2879,6 +2942,19 @@ declare interface ContextReserveResolution {
|
|
|
2879
2942
|
basis: 'locked' | 'reachable-max';
|
|
2880
2943
|
}
|
|
2881
2944
|
|
|
2945
|
+
/**
|
|
2946
|
+
* Options for `continueFromHistory` (GENC-1662).
|
|
2947
|
+
*
|
|
2948
|
+
* @beta
|
|
2949
|
+
*/
|
|
2950
|
+
export declare interface ContinueFromHistoryOptions {
|
|
2951
|
+
/**
|
|
2952
|
+
* A note for the model, placed in the framed tail of the first model call only — after the
|
|
2953
|
+
* history it describes — and dropped once the model has answered.
|
|
2954
|
+
*/
|
|
2955
|
+
tailNote?: string;
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2882
2958
|
/** A model used during a recorded cost session. */
|
|
2883
2959
|
export declare interface CostSessionModelEntry {
|
|
2884
2960
|
model: string;
|
|
@@ -4945,6 +5021,22 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
4945
5021
|
* persistence is (now) on.
|
|
4946
5022
|
*/
|
|
4947
5023
|
private initPersistenceForNewStore;
|
|
5024
|
+
/**
|
|
5025
|
+
* Whether the session restored for `key` is no longer the one on screen (GENC-1662): switched in
|
|
5026
|
+
* place, or the element disconnected, while the load was in flight.
|
|
5027
|
+
*/
|
|
5028
|
+
private isRestoredSessionStale;
|
|
5029
|
+
/**
|
|
5030
|
+
* Re-activate a restored flow owner (GENC-1662), so a stateful agent's `init({ restored })` — and
|
|
5031
|
+
* anything the host hangs off it, like a progress stepper — runs straight after the reload
|
|
5032
|
+
* instead of on the next message.
|
|
5033
|
+
*/
|
|
5034
|
+
private reactivateRestoredFlow;
|
|
5035
|
+
/**
|
|
5036
|
+
* Run the turn a reload interrupted (GENC-1662), shown as busy exactly as a send is — or, when it
|
|
5037
|
+
* cannot run, withdraw the resume the restore divider promised.
|
|
5038
|
+
*/
|
|
5039
|
+
private resumeInterruptedTurn;
|
|
4948
5040
|
triggerFileInput(): void;
|
|
4949
5041
|
handleFileSelect(e: Event): void;
|
|
4950
5042
|
removeAttachment(attachment: ChatAttachment): void;
|
|
@@ -4991,6 +5083,11 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
4991
5083
|
*/
|
|
4992
5084
|
private _pendingSendPrompt?;
|
|
4993
5085
|
private send;
|
|
5086
|
+
/**
|
|
5087
|
+
* The post-turn settle shared by `send()` and a resumed restore turn: back to idle through
|
|
5088
|
+
* the session ref captured at turn start, then the cleanup the state setter would have done.
|
|
5089
|
+
*/
|
|
5090
|
+
private settleAfterTurn;
|
|
4994
5091
|
onChatHeaderMouseDown(e: MouseEvent): void;
|
|
4995
5092
|
handleInteractionCompleted(e: Event): void;
|
|
4996
5093
|
/**
|
|
@@ -5490,9 +5587,22 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
|
|
|
5490
5587
|
getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
|
|
5491
5588
|
sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
|
|
5492
5589
|
private runOrchestratedTurn;
|
|
5493
|
-
continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult>;
|
|
5590
|
+
continueFromHistory(transientPrimer?: ChatMessage[], options?: ContinueFromHistoryOptions): Promise<ChatDriverResult>;
|
|
5494
5591
|
/** {@inheritDoc AiDriver.primeRestoredAgentState} */
|
|
5495
5592
|
primeRestoredAgentState(snapshots: Record<string, unknown>): void;
|
|
5593
|
+
/** {@inheritDoc AiDriver.canRestoreFlowOwner} */
|
|
5594
|
+
canRestoreFlowOwner(agentName: string): boolean;
|
|
5595
|
+
/** {@inheritDoc AiDriver.canResumeRestoredFlow} */
|
|
5596
|
+
canResumeRestoredFlow(agentName: string): boolean;
|
|
5597
|
+
/**
|
|
5598
|
+
* {@inheritDoc AiDriver.resumeRestoredFlow}
|
|
5599
|
+
*
|
|
5600
|
+
* Installs the flow owner directly rather than through `handleTurn`: there is no user message
|
|
5601
|
+
* to classify, and a restored lock already says which agent owns the flow. `continueFromHistory`
|
|
5602
|
+
* on its own would not do — it neither routes nor installs, so it would run on whatever agent
|
|
5603
|
+
* happened to be installed (none, straight after a reload).
|
|
5604
|
+
*/
|
|
5605
|
+
resumeRestoredFlow(resumeNote?: string): Promise<ChatDriverResult | undefined>;
|
|
5496
5606
|
/**
|
|
5497
5607
|
* {@inheritDoc AiDriver.getContextReserve}
|
|
5498
5608
|
*
|
|
@@ -6400,6 +6510,12 @@ export declare interface StatefulAgentInit<S> {
|
|
|
6400
6510
|
* `false`. Falls back to a built-in default when omitted.
|
|
6401
6511
|
*/
|
|
6402
6512
|
notResumableMessage?: string;
|
|
6513
|
+
/**
|
|
6514
|
+
* Whether this agent's flow continues on its own when a page reload interrupted one of its turns
|
|
6515
|
+
* — see `AgentConfig.resumeOnRestore`, which this is passed straight through to. Defaults to
|
|
6516
|
+
* `true`. A stateful agent is the only kind this applies to, since only it owns a flow.
|
|
6517
|
+
*/
|
|
6518
|
+
resumeOnRestore?: boolean;
|
|
6403
6519
|
}
|
|
6404
6520
|
|
|
6405
6521
|
/**
|
package/dist/chat-driver.cjs
CHANGED
|
@@ -4114,6 +4114,10 @@ var META_EVENT_IMPORTANCE = {
|
|
|
4114
4114
|
"session.switched": "low",
|
|
4115
4115
|
"session.switch-deferred": "low",
|
|
4116
4116
|
"persistence.restored": "normal",
|
|
4117
|
+
// Whether a restored flow will be re-activated and resumed (GENC-1662), and how much the trim cut.
|
|
4118
|
+
"persistence.resume-planned": "normal",
|
|
4119
|
+
// A planned resume that did not run, and why (GENC-1662) — the divider was put back to plain.
|
|
4120
|
+
"persistence.resume-withdrawn": "normal",
|
|
4117
4121
|
"persistence.suppressed": "normal",
|
|
4118
4122
|
"persistence.not-resumable": "normal",
|
|
4119
4123
|
"driver.wired": "low",
|
|
@@ -4907,6 +4911,8 @@ var AgentSession = class {
|
|
|
4907
4911
|
* activation, then deleted so a later re-activation starts fresh.
|
|
4908
4912
|
*/
|
|
4909
4913
|
this.restoredStates = {};
|
|
4914
|
+
/** The tail of the activation queue — see {@link AgentSession.activate}. */
|
|
4915
|
+
this.activation = Promise.resolve();
|
|
4910
4916
|
}
|
|
4911
4917
|
/** The active agent, or `undefined` before the first activation and after a release. */
|
|
4912
4918
|
getActive() {
|
|
@@ -4955,8 +4961,19 @@ var AgentSession = class {
|
|
|
4955
4961
|
*
|
|
4956
4962
|
* Re-activating the same agent by name is not a switch: no hooks fire, no lock moves, and no
|
|
4957
4963
|
* handoff is recorded. That guard matters because a per-turn re-resolve calls through here.
|
|
4958
|
-
|
|
4959
|
-
|
|
4964
|
+
*
|
|
4965
|
+
* Single-flight (GENC-1662): calls run one after another, never interleaved. `active` is only
|
|
4966
|
+
* set once the hooks have finished, so two overlapping calls for the same agent would otherwise
|
|
4967
|
+
* both see a switch and run `onActivate` twice — and a restored `init` would be overwritten by a
|
|
4968
|
+
* fresh one that finished later. That overlap became possible when a restore started activating
|
|
4969
|
+
* the flow owner outside a turn, where a send can land mid-activation.
|
|
4970
|
+
*/
|
|
4971
|
+
activate(agent) {
|
|
4972
|
+
const run = this.activation.then(() => this.activateNow(agent));
|
|
4973
|
+
this.activation = run.catch(() => void 0);
|
|
4974
|
+
return run;
|
|
4975
|
+
}
|
|
4976
|
+
async activateNow(agent) {
|
|
4960
4977
|
const previousAgent = this.active;
|
|
4961
4978
|
const switched = !previousAgent || previousAgent.name !== agent.name;
|
|
4962
4979
|
const transition = { previousAgent, switched };
|
|
@@ -7517,9 +7534,13 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
7517
7534
|
}
|
|
7518
7535
|
/**
|
|
7519
7536
|
* Continue the tool loop from current history without appending a new user message.
|
|
7520
|
-
* Used by OrchestratingDriver after an agent handoff.
|
|
7537
|
+
* Used by OrchestratingDriver after an agent handoff, and to resume a restored flow (GENC-1662).
|
|
7538
|
+
*
|
|
7539
|
+
* `options.tailNote` rides the framed tail of the FIRST model call only — after the history, where
|
|
7540
|
+
* a note about the conversation belongs — and is dropped once the model has answered, so it
|
|
7541
|
+
* cannot go stale over the rest of the loop. Contrast `transientPrimer`, which leads the request.
|
|
7521
7542
|
*/
|
|
7522
|
-
async continueFromHistory(transientPrimer) {
|
|
7543
|
+
async continueFromHistory(transientPrimer, options) {
|
|
7523
7544
|
if (this.busy) return { reason: "done" };
|
|
7524
7545
|
this.busy = true;
|
|
7525
7546
|
if (this.messageController.signal.aborted) this.beginMessage();
|
|
@@ -7541,7 +7562,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
7541
7562
|
this.activityBus.publish("tool-loop-start", void 0);
|
|
7542
7563
|
let result = { reason: "done" };
|
|
7543
7564
|
try {
|
|
7544
|
-
result = await this.runToolLoop("", void 0, transientPrimer);
|
|
7565
|
+
result = await this.runToolLoop("", void 0, transientPrimer, options?.tailNote);
|
|
7545
7566
|
return result;
|
|
7546
7567
|
} catch (e) {
|
|
7547
7568
|
logger2.error("ChatDriver error:", e);
|
|
@@ -7578,7 +7599,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
7578
7599
|
// splitting threads that state through signatures rather than removing it. `turn-setup.ts`
|
|
7579
7600
|
// (docs/code-health.md §11.3) is the intended carve-up.
|
|
7580
7601
|
// oxlint-disable-next-line complexity, max-lines-per-function
|
|
7581
|
-
async runToolLoop(userInput, attachments, transientPrimer) {
|
|
7602
|
+
async runToolLoop(userInput, attachments, transientPrimer, tailNote) {
|
|
7582
7603
|
if (!this.systemPrompt) {
|
|
7583
7604
|
logger2.warn(
|
|
7584
7605
|
"ChatDriver: no systemPrompt set. The assistant will have no instructions \u2014 provide a systemPrompt via agents config or the foundation-ai-assistant property."
|
|
@@ -7639,7 +7660,10 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
7639
7660
|
${MALFORMED_CALL_NUDGE}` : emptyResponseAttempts > 0 ? `
|
|
7640
7661
|
|
|
7641
7662
|
${EMPTY_RESPONSE_NUDGE}` : "";
|
|
7642
|
-
const
|
|
7663
|
+
const firstCallNote = tailNote && iterations === 1 ? `
|
|
7664
|
+
|
|
7665
|
+
${tailNote}` : "";
|
|
7666
|
+
const frameworkSystemSuffix = `${foldSuffix}${firstCallNote}${retryNudge}`;
|
|
7643
7667
|
const primer = normalizeForProvider([
|
|
7644
7668
|
...this.primerHistory ?? [],
|
|
7645
7669
|
...transientPrimer ?? []
|
|
@@ -8698,13 +8722,39 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
8698
8722
|
}
|
|
8699
8723
|
return lastResult?.reason === "done" ? lastResult : { reason: "done" };
|
|
8700
8724
|
}
|
|
8701
|
-
async continueFromHistory(transientPrimer) {
|
|
8702
|
-
return this.chatDriver.continueFromHistory(transientPrimer);
|
|
8725
|
+
async continueFromHistory(transientPrimer, options) {
|
|
8726
|
+
return this.chatDriver.continueFromHistory(transientPrimer, options);
|
|
8703
8727
|
}
|
|
8704
8728
|
/** {@inheritDoc AiDriver.primeRestoredAgentState} */
|
|
8705
8729
|
primeRestoredAgentState(snapshots) {
|
|
8706
8730
|
this.agentSession.primeRestoredStates(snapshots);
|
|
8707
8731
|
}
|
|
8732
|
+
/** {@inheritDoc AiDriver.canRestoreFlowOwner} */
|
|
8733
|
+
canRestoreFlowOwner(agentName) {
|
|
8734
|
+
return this.agents.some((a) => a.name === agentName);
|
|
8735
|
+
}
|
|
8736
|
+
/** {@inheritDoc AiDriver.canResumeRestoredFlow} */
|
|
8737
|
+
canResumeRestoredFlow(agentName) {
|
|
8738
|
+
const agent = this.agents.find((a) => a.name === agentName);
|
|
8739
|
+
return !!agent && agent.resumeOnRestore !== false;
|
|
8740
|
+
}
|
|
8741
|
+
/**
|
|
8742
|
+
* {@inheritDoc AiDriver.resumeRestoredFlow}
|
|
8743
|
+
*
|
|
8744
|
+
* Installs the flow owner directly rather than through `handleTurn`: there is no user message
|
|
8745
|
+
* to classify, and a restored lock already says which agent owns the flow. `continueFromHistory`
|
|
8746
|
+
* on its own would not do — it neither routes nor installs, so it would run on whatever agent
|
|
8747
|
+
* happened to be installed (none, straight after a reload).
|
|
8748
|
+
*/
|
|
8749
|
+
async resumeRestoredFlow(resumeNote) {
|
|
8750
|
+
const owner = this.agentSession.getFlowOwner();
|
|
8751
|
+
const agent = owner ? this.agents.find((a) => a.name === owner) : void 0;
|
|
8752
|
+
if (!agent) return void 0;
|
|
8753
|
+
this.cancelled = false;
|
|
8754
|
+
await this.installAgent(agent);
|
|
8755
|
+
if (!resumeNote || agent.resumeOnRestore === false || this.cancelled) return void 0;
|
|
8756
|
+
return this.chatDriver.continueFromHistory(void 0, { tailNote: resumeNote });
|
|
8757
|
+
}
|
|
8708
8758
|
/**
|
|
8709
8759
|
* {@inheritDoc AiDriver.getContextReserve}
|
|
8710
8760
|
*
|
|
@@ -9179,6 +9229,7 @@ function defineStatefulAgent(opts) {
|
|
|
9179
9229
|
onUnresolvedTool: wrappedOnUnresolvedTool,
|
|
9180
9230
|
resumable: wrappedResumable,
|
|
9181
9231
|
notResumableMessage: opts.notResumableMessage,
|
|
9232
|
+
resumeOnRestore: opts.resumeOnRestore,
|
|
9182
9233
|
contextReserve: opts.contextReserve,
|
|
9183
9234
|
onActivate: async (ctx) => {
|
|
9184
9235
|
state = await opts.init(ctx);
|