@springbrand/agent-runtime 0.2.0-alpha.69 → 0.2.0-alpha.70

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@springbrand/agent-runtime",
3
- "version": "0.2.0-alpha.69",
3
+ "version": "0.2.0-alpha.70",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -60,6 +60,8 @@ export interface RuntimeAgentConfigContext<
60
60
  readonly parentPath: readonly RuntimeAgentPathStep[];
61
61
  /** Runtime 根据 Agent facet 父子关系自动判定,不是外部配置项。 */
62
62
  readonly role: RuntimeAgentRole;
63
+ /** Current/preparing Submission and durable identities that may still resume. */
64
+ readonly submission?: { readonly id: string | undefined; readonly unfinishedIds: readonly string[] };
63
65
  /** 向当前 Agent facet 的已连接客户端发送实时消息。 */
64
66
  broadcast(message: string): void;
65
67
  /**
@@ -449,10 +449,15 @@ export function defineRuntimeAgent<
449
449
  return this.ensureConfig();
450
450
  }
451
451
 
452
- protected async prepareRuntimeForSubmission(): Promise<void> {
452
+ protected async prepareRuntimeForSubmission(submissionId: string): Promise<void> {
453
453
  const beforeSubmission = definition.beforeSubmission as RuntimeAgentDefinitionBase<Env, Config, Command, Change>["beforeSubmission"];
454
- const changed = await beforeSubmission?.(this.createDefinitionContext());
455
- await this.ensureConfig(undefined, changed === true);
454
+ try {
455
+ const changed = await beforeSubmission?.(this.createDefinitionContext(undefined, submissionId));
456
+ await this.ensureConfig(undefined, changed === true);
457
+ } catch (error) {
458
+ this.hasLoadedRuntime = false;
459
+ throw error;
460
+ }
456
461
  }
457
462
 
458
463
  // 作用:加载默认 Runtime,或切换到调用方指定的 key。
@@ -669,6 +674,9 @@ export function defineRuntimeAgent<
669
674
  // Host 的会话列表把装配后的第一次投影当作「facet 已就绪」的信号。
670
675
  await this.broadcastApprovals();
671
676
  })().catch((error) => {
677
+ // A failed replacement must be retried even when Host inputs have
678
+ // not changed again since that failed attempt.
679
+ this.hasLoadedRuntime = false;
672
680
  logRuntimeLoadFailure("runtime", error);
673
681
  this.runtimeLoad.fail();
674
682
  throw error;
@@ -831,6 +839,7 @@ export function defineRuntimeAgent<
831
839
 
832
840
  protected createDefinitionContext(
833
841
  runtimeConfig?: { value: Config },
842
+ submissionId?: string,
834
843
  ): RuntimeAgentPlanningContext<
835
844
  Env,
836
845
  Command,
@@ -849,6 +858,10 @@ export function defineRuntimeAgent<
849
858
  get role() {
850
859
  return agent.role;
851
860
  },
861
+ get submission() {
862
+ const current = agent.submissionContext;
863
+ return { ...current, id: submissionId ?? current.id };
864
+ },
852
865
  broadcast: (message) => agent.broadcast(message),
853
866
  ...(agent.role === "primary"
854
867
  ? {
package/src/runtime.ts CHANGED
@@ -418,9 +418,15 @@ export abstract class AgentRuntimeKernel<
418
418
 
419
419
  protected abstract ensureRuntimeReady(): Promise<void>;
420
420
  /** Runs only before the first pin of a newly activated Submission. */
421
- protected prepareRuntimeForSubmission(): Promise<void> {
421
+ protected prepareRuntimeForSubmission(_submissionId: string): Promise<void> {
422
422
  return this.ensureRuntimeReady();
423
423
  }
424
+ protected get submissionContext() {
425
+ return {
426
+ id: this.submissions.currentActive()?.submissionId ?? this.db.submissions.findRunning()?.submissionId,
427
+ unfinishedIds: this.db.submissions.listUnfinishedIds(),
428
+ };
429
+ }
424
430
 
425
431
  /** Let the Host prepare a validated client response before Tool settlement. */
426
432
  protected prepareToolInteractionResponse(
@@ -1535,11 +1541,11 @@ export abstract class AgentRuntimeKernel<
1535
1541
  // 作用:为新 Submission 生成包含当前 Context 的不可变装配描述。
1536
1542
  // 调用:Submission 通过去重和忙碌检查后,在真正写入前调用。
1537
1543
  // 原因:把动态 Context 和执行档位固定在准入时,恢复时才能按原配置继续。
1538
- private async admissionPin(fresh: boolean): Promise<{
1544
+ private async admissionPin(fresh: boolean, submissionId: string): Promise<{
1539
1545
  revision: string;
1540
1546
  descriptor: string;
1541
1547
  }> {
1542
- if (fresh) await this.prepareRuntimeForSubmission();
1548
+ if (fresh) await this.prepareRuntimeForSubmission(submissionId);
1543
1549
  else await this.ensureRuntimeReady();
1544
1550
  return this.currentAssemblyPin();
1545
1551
  }
@@ -1592,7 +1598,7 @@ export abstract class AgentRuntimeKernel<
1592
1598
  if (submission.assemblyRevision || submission.assemblyDescriptor) {
1593
1599
  throw new Error("Submission assembly pin is incomplete");
1594
1600
  }
1595
- const { revision, descriptor } = await this.admissionPin(mode === 'fresh');
1601
+ const { revision, descriptor } = await this.admissionPin(mode === 'fresh', submission.submissionId);
1596
1602
  this.db.submissions.pinAssembly(
1597
1603
  submission.submissionId,
1598
1604
  revision,