@abot-ai/runtime 1.8.0 → 1.8.1

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 (119) hide show
  1. package/README.md +216 -222
  2. package/dist/src/capabilities/tool-definition-validator/definition-parser.js +8 -0
  3. package/dist/src/capabilities/tool-types.d.ts +4 -0
  4. package/dist/src/model-gateway/protocol/message-contract.d.ts +1 -0
  5. package/dist/src/model-gateway/protocol/message-contract.js +1 -1
  6. package/dist/src/model-gateway/server/chat-handler.js +5 -7
  7. package/dist/src/model-gateway/server/chat-stream-response.d.ts +7 -0
  8. package/dist/src/model-gateway/server/chat-stream-response.js +25 -0
  9. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.d.ts +2 -2
  10. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.js +2 -2
  11. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/prepared-execution.js +17 -11
  12. package/dist/src/runtime/capabilities/tool-availability.js +6 -0
  13. package/dist/src/runtime/context/capability-brief.d.ts +2 -2
  14. package/dist/src/runtime/context/capability-brief.js +3 -3
  15. package/dist/src/runtime/context/capability-descriptions.d.ts +3 -2
  16. package/dist/src/runtime/context/capability-descriptions.js +57 -20
  17. package/dist/src/runtime/long-term-memory/conversation-authoring/context.d.ts +6 -1
  18. package/dist/src/runtime/long-term-memory/conversation-authoring/context.js +51 -25
  19. package/dist/src/runtime/long-term-memory/initial-context.d.ts +17 -0
  20. package/dist/src/runtime/long-term-memory/initial-context.js +57 -0
  21. package/dist/src/runtime/long-term-memory/projection.js +1 -1
  22. package/dist/src/runtime/orchestration/role-calls/candidate-validation.js +2 -1
  23. package/dist/src/runtime/orchestration/role-calls/checkpoint-state.d.ts +1 -1
  24. package/dist/src/runtime/orchestration/role-calls/checkpoint-state.js +5 -2
  25. package/dist/src/runtime/orchestration/role-calls/contracts.d.ts +2 -1
  26. package/dist/src/runtime/orchestration/role-calls/ledger.d.ts +2 -1
  27. package/dist/src/runtime/orchestration/role-calls/ledger.js +2 -2
  28. package/dist/src/runtime/orchestration/role-calls/memory-recall-contract.d.ts +7 -0
  29. package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.d.ts +2 -0
  30. package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.js +88 -0
  31. package/dist/src/runtime/orchestration/role-calls/reducer.d.ts +1 -1
  32. package/dist/src/runtime/orchestration/role-calls/reducer.js +2 -1
  33. package/dist/src/runtime/orchestration/worker-capabilities/contracts.d.ts +3 -1
  34. package/dist/src/runtime/orchestration/worker-capabilities/contracts.js +1 -1
  35. package/dist/src/runtime/orchestration/worker-capabilities/execution/approval-group.js +5 -1
  36. package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.d.ts +5 -0
  37. package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.js +31 -0
  38. package/dist/src/runtime/plugins/manifest-projection.js +3 -0
  39. package/dist/src/runtime/request/capability-execution-freshness.js +6 -1
  40. package/dist/src/runtime/request/execution-agent-root-execution.js +11 -1
  41. package/dist/src/runtime/request/root-contract.d.ts +2 -0
  42. package/dist/src/runtime/request/root-execution-kernel.js +1 -0
  43. package/dist/src/runtime/request/runner.js +9 -3
  44. package/dist/src/runtime/request/supervisor-root-execution.js +6 -0
  45. package/dist/src/runtime/steps/execution-agent/contracts.d.ts +10 -0
  46. package/dist/src/runtime/steps/execution-agent/decision-parsing.js +13 -1
  47. package/dist/src/runtime/steps/execution-agent/direct-response-configuration.d.ts +3 -0
  48. package/dist/src/runtime/steps/execution-agent/direct-response-configuration.js +64 -0
  49. package/dist/src/runtime/steps/execution-agent/direct-response-contract.d.ts +7 -0
  50. package/dist/src/runtime/steps/execution-agent/direct-response-contract.js +56 -0
  51. package/dist/src/runtime/steps/execution-agent/direct-response-policy.d.ts +9 -0
  52. package/dist/src/runtime/steps/execution-agent/direct-response-policy.js +30 -0
  53. package/dist/src/runtime/steps/execution-agent/direct-response-prompt.d.ts +7 -0
  54. package/dist/src/runtime/steps/execution-agent/direct-response-prompt.js +43 -0
  55. package/dist/src/runtime/steps/execution-agent/format.js +2 -0
  56. package/dist/src/runtime/steps/execution-agent/input.d.ts +2 -0
  57. package/dist/src/runtime/steps/execution-agent/input.js +22 -1
  58. package/dist/src/runtime/steps/execution-agent/plugin-catalog.d.ts +4 -0
  59. package/dist/src/runtime/steps/execution-agent/plugin-catalog.js +8 -0
  60. package/dist/src/runtime/steps/execution-agent/prompt.d.ts +1 -0
  61. package/dist/src/runtime/steps/execution-agent/prompt.js +3 -4
  62. package/dist/src/runtime/steps/execution-agent/response-run.js +5 -11
  63. package/dist/src/runtime/steps/execution-agent/run.js +4 -1
  64. package/dist/src/runtime/steps/execution-agent/state-context.d.ts +2 -3
  65. package/dist/src/runtime/steps/execution-agent/state-context.js +2 -39
  66. package/dist/src/runtime/steps/planner-decision/capability-brief.d.ts +2 -0
  67. package/dist/src/runtime/steps/planner-decision/prompt.js +26 -49
  68. package/dist/src/runtime/steps/supervisor-decision/input.d.ts +1 -0
  69. package/dist/src/runtime/steps/supervisor-decision/input.js +5 -0
  70. package/dist/src/runtime/steps/supervisor-decision/prompt.d.ts +1 -0
  71. package/dist/src/runtime/steps/supervisor-decision/prompt.js +6 -2
  72. package/dist/src/runtime/steps/supervisor-decision/run.d.ts +1 -0
  73. package/dist/src/runtime/steps/supervisor-decision/run.js +4 -0
  74. package/dist/src/runtime/steps/supervisor-response/run.d.ts +2 -0
  75. package/dist/src/runtime/steps/supervisor-response/run.js +3 -6
  76. package/dist/src/web-ui/app/ARCHITECTURE.md +1 -1
  77. package/dist/src/web-ui/app/app.js +1 -0
  78. package/dist/src/web-ui/app/components/automations/timeline.js +3 -2
  79. package/dist/src/web-ui/app/components/dashboard/compact-layout.js +137 -0
  80. package/dist/src/web-ui/app/components/dashboard/icons.js +5 -0
  81. package/dist/src/web-ui/app/components/dashboard/widget-card.js +85 -0
  82. package/dist/src/web-ui/app/components/dashboard/widget-dialog.js +83 -0
  83. package/dist/src/web-ui/app/components/dashboard/widget-summaries.js +155 -0
  84. package/dist/src/web-ui/app/components/dashboard/workspace.js +28 -4
  85. package/dist/src/web-ui/app/components/operations-summary.js +2 -1
  86. package/dist/src/web-ui/app/components/passive-learning/home-widget-preview.js +32 -0
  87. package/dist/src/web-ui/app/components/passive-learning/home.js +4 -1
  88. package/dist/src/web-ui/app/components/schedules/details.js +3 -2
  89. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -1
  90. package/dist/src/web-ui/app/components/spark-chat/settings.js +1 -1
  91. package/dist/src/web-ui/app/components/system-host/home-widget-permission-preview.js +75 -0
  92. package/dist/src/web-ui/app/components/system-host/home-widget-summary.js +93 -0
  93. package/dist/src/web-ui/app/components/system-host/macos-permission-rendering.js +2 -2
  94. package/dist/src/web-ui/app/components/system-host/native-windows-access.js +1 -1
  95. package/dist/src/web-ui/app/components/system-host/rendering.js +3 -3
  96. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +2 -2
  97. package/dist/src/web-ui/app/computer-access-feature.js +13 -1
  98. package/dist/src/web-ui/app/configuration-feature.js +2 -0
  99. package/dist/src/web-ui/app/controllers/operations-controller.js +2 -1
  100. package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +1 -1
  101. package/dist/src/web-ui/app/dashboard-feature.js +9 -0
  102. package/dist/src/web-ui/app/lib/reasoning-controls.js +6 -1
  103. package/dist/src/web-ui/app/passive-learning-feature.js +2 -2
  104. package/dist/src/web-ui/app/styles/95-home-widgets.css +109 -0
  105. package/dist/src/web-ui/app/styles.css +1 -0
  106. package/docs/plugins.md +37 -32
  107. package/package.json +1 -1
  108. package/plugins/capability-brief/plugin.json +1 -1
  109. package/plugins/code-outline/plugin.json +1 -1
  110. package/plugins/document-reader/plugin.json +1 -1
  111. package/plugins/exec/plugin.json +1 -1
  112. package/plugins/filesystem/plugin.json +1 -1
  113. package/plugins/json-inspector/plugin.json +1 -1
  114. package/plugins/local-search/plugin.json +1 -1
  115. package/plugins/memory/plugin.json +1 -1
  116. package/plugins/project-orientation/plugin.json +1 -1
  117. package/plugins/system/plugin.json +1 -1
  118. package/plugins/system-probe/plugin.json +1 -1
  119. package/plugins/web/plugin.json +1 -1
@@ -0,0 +1,25 @@
1
+ export async function writeChatStreamResponse(params) {
2
+ const { invocation, response, abortSignal } = params;
3
+ let hasEmittedEvent = false;
4
+ response.setHeader("Content-Type", "application/x-ndjson; charset=utf-8");
5
+ response.setHeader("Cache-Control", "no-cache");
6
+ try {
7
+ await invocation.stream({
8
+ emit(event) {
9
+ response.write(`${JSON.stringify(event)}\n`);
10
+ hasEmittedEvent = true;
11
+ },
12
+ });
13
+ }
14
+ catch (error) {
15
+ if (abortSignal.aborted)
16
+ return;
17
+ // Before the first write, the handler can still send its normal HTTP error.
18
+ if (!hasEmittedEvent)
19
+ throw error;
20
+ console.error(error);
21
+ response.end(`${JSON.stringify({ type: "error", error: "server error" })}\n`);
22
+ return;
23
+ }
24
+ response.end();
25
+ }
@@ -1,8 +1,8 @@
1
1
  import type { CapabilityAdapterResult } from "../../orchestration/capability-adapters/index.js";
2
2
  import type { WorkerCapabilityAdapterResult, WorkerCapabilityExecutionFreshness } from "../../orchestration/worker-capabilities/index.js";
3
3
  import type { PayloadLifecycleEmitter } from "./payload-observability.js";
4
- export declare const STEERING_SUPERSEDED_BEFORE_EXTERNAL_EXECUTION: "steering_superseded_before_external_execution";
5
- export declare const STEERING_SUPERSEDED_SUMMARY = "steering_superseded_before_external_execution: No external execution occurred because a newer active-request update superseded this capability invocation.";
4
+ import { STEERING_SUPERSEDED_BEFORE_EXTERNAL_EXECUTION, STEERING_SUPERSEDED_SUMMARY } from "../../orchestration/worker-capabilities/execution/execution-freshness.js";
5
+ export { STEERING_SUPERSEDED_BEFORE_EXTERNAL_EXECUTION, STEERING_SUPERSEDED_SUMMARY, };
6
6
  export type PayloadLifecycleContext = Readonly<Omit<Parameters<PayloadLifecycleEmitter["emitPayloadLifecycle"]>[0], "phase" | "errorCode">>;
7
7
  export declare function rejectPayloadLifecycle(params: {
8
8
  executor: PayloadLifecycleEmitter;
@@ -1,7 +1,7 @@
1
1
  import { boundedSummary, requireCapabilityAdapterResult, } from "./result-observer.js";
2
2
  import { createRegisteredToolWorkerFailureOutcomeFingerprint } from "./failure-outcome-fingerprint.js";
3
- export const STEERING_SUPERSEDED_BEFORE_EXTERNAL_EXECUTION = "steering_superseded_before_external_execution";
4
- export const STEERING_SUPERSEDED_SUMMARY = "steering_superseded_before_external_execution: No external execution occurred because a newer active-request update superseded this capability invocation.";
3
+ import { STEERING_SUPERSEDED_BEFORE_EXTERNAL_EXECUTION, STEERING_SUPERSEDED_SUMMARY, } from "../../orchestration/worker-capabilities/execution/execution-freshness.js";
4
+ export { STEERING_SUPERSEDED_BEFORE_EXTERNAL_EXECUTION, STEERING_SUPERSEDED_SUMMARY, };
5
5
  export function rejectPayloadLifecycle(params) {
6
6
  const failed = params.executor.emitPayloadLifecycle({
7
7
  ...params.lifecycle,
@@ -1,9 +1,23 @@
1
1
  import { traceRegisteredToolWorkerCapabilityExecutionStarted, traceRegisteredToolWorkerCapabilityExecutionCompleted, traceRegisteredToolWorkerCapabilityExecutionFailed, } from "../registered-tool-worker-capability-diagnostics.js";
2
2
  import { executionFreshnessRejection } from "./payload-lifecycle.js";
3
+ import { payloadRejection } from "./payload-rejection.js";
3
4
  import { RegisteredToolWorkerCapabilityExecutionError } from "./errors.js";
4
5
  import { observeExternalResult, attachTargetReferences, } from "./result-observer.js";
5
6
  export function createPreparedWorkerInvocation(params, input, normalPreparation, selectedTargetReferences, payloadObservability) {
6
7
  const operationId = params.projection.operation.operationId;
8
+ const rejectBeforeExecution = (executionId, code, message) => {
9
+ payloadObservability.release(executionId);
10
+ const rejectedExecution = payloadRejection(code, message);
11
+ normalPreparation.emitRejection({
12
+ executionId,
13
+ executorIdentity: input.call,
14
+ errorCode: code,
15
+ });
16
+ return attachTargetReferences({
17
+ ...rejectedExecution.result,
18
+ exactResult: rejectedExecution.exactResult,
19
+ }, selectedTargetReferences);
20
+ };
7
21
  return Object.freeze({
8
22
  actionFingerprint: normalPreparation.actionFingerprint,
9
23
  acceptedControls: normalPreparation.acceptedControls,
@@ -18,22 +32,14 @@ export function createPreparedWorkerInvocation(params, input, normalPreparation,
18
32
  : {}),
19
33
  applyApprovalDecision: normalPreparation.applyApprovalDecision,
20
34
  onAdmitted: payloadObservability.release,
35
+ rejectBeforeExecution,
21
36
  execute: async (executionId) => {
22
37
  try {
23
38
  payloadObservability.release(executionId);
24
39
  traceRegisteredToolWorkerCapabilityExecutionStarted(params.diagnostic, operationId, input.call, executionId, input.intent.length, Object.keys(input.controls).length);
25
40
  const rejectedExecution = executionFreshnessRejection(input.executionFreshness);
26
- if (rejectedExecution) {
27
- normalPreparation.emitRejection({
28
- executionId,
29
- executorIdentity: input.call,
30
- errorCode: rejectedExecution.sourceIssueCode,
31
- });
32
- return attachTargetReferences({
33
- ...rejectedExecution.result,
34
- exactResult: rejectedExecution.exactResult,
35
- }, selectedTargetReferences);
36
- }
41
+ if (rejectedExecution)
42
+ return rejectBeforeExecution(executionId, rejectedExecution.sourceIssueCode, rejectedExecution.result.summary);
37
43
  const externalResult = await normalPreparation.execute(executionId, input.call, selectedTargetReferences);
38
44
  const observed = observeExternalResult(externalResult, params.projection.operation.effect, input.call.parentCallId === null, selectedTargetReferences);
39
45
  const observedResult = observed.result;
@@ -3,6 +3,12 @@ export function projectAvailableTools(registrations) {
3
3
  return undefined;
4
4
  const entries = registrations.flatMap((registration) => registration.contract.operations.map((operation) => Object.freeze({
5
5
  toolName: registration.toolName,
6
+ ...(registration.definition.pluginName !== undefined
7
+ ? { pluginName: registration.definition.pluginName }
8
+ : {}),
9
+ ...(registration.definition.pluginDescription !== undefined
10
+ ? { pluginDescription: registration.definition.pluginDescription }
11
+ : {}),
6
12
  operationId: operation.operationId,
7
13
  summary: operation.summary,
8
14
  catalogGroups: Object.freeze([
@@ -1,10 +1,10 @@
1
1
  import type { ChatMessage, ModelTokenEstimationConfig } from "../../model-gateway/types.js";
2
2
  import type { ToolAvailabilityEntry } from "../../capabilities/tool-types.js";
3
- import { type ToolAvailabilityOverviewGroup, type ToolAvailabilityOverviewLevel } from "../../plugin-sdk/tool-availability-overview.js";
3
+ import { type ToolAvailabilityOverviewGroup } from "../../plugin-sdk/tool-availability-overview.js";
4
4
  import type { projectRequestContext } from "./request-context.js";
5
5
  export declare const CAPABILITY_BRIEF_KIND = "runtime_capability_brief_v1";
6
6
  export declare const CAPABILITY_BRIEF_MAX_TOKENS = 512;
7
- export type CapabilityBriefLevel = ToolAvailabilityOverviewLevel | "descriptions" | "none";
7
+ export type CapabilityBriefLevel = "groups" | "descriptions" | "none";
8
8
  export type CapabilityBriefProjection = Readonly<{
9
9
  level: CapabilityBriefLevel;
10
10
  message?: ChatMessage;
@@ -1,6 +1,6 @@
1
1
  import { buildToolAvailabilityOverview, } from "../../plugin-sdk/tool-availability-overview.js";
2
2
  import { resolveCapabilityBriefHeadroom } from "./capability-brief-budget.js";
3
- import { buildCapabilityDescriptions } from "./capability-descriptions.js";
3
+ import { buildPluginDiscoveryCatalogText } from "./capability-descriptions.js";
4
4
  import { estimateMessageTokens } from "./token-estimator.js";
5
5
  export const CAPABILITY_BRIEF_KIND = "runtime_capability_brief_v1";
6
6
  export const CAPABILITY_BRIEF_MAX_TOKENS = 512;
@@ -22,12 +22,12 @@ export function projectCapabilityBriefAtHeadroom(params) {
22
22
  return omittedBrief(compactBudgetTokens, "empty_catalog");
23
23
  }
24
24
  const levels = hasCompleteCapabilityBriefEntries(params.entries, params.groups)
25
- ? ["descriptions", "detailed", "titles", "groups"]
25
+ ? ["descriptions", "groups"]
26
26
  : ["groups"];
27
27
  for (const level of levels) {
28
28
  const budgetTokens = level === "descriptions" ? headroom : compactBudgetTokens;
29
29
  const body = level === "descriptions"
30
- ? buildCapabilityDescriptions(params.entries ?? [])
30
+ ? buildPluginDiscoveryCatalogText(params.groups.map(({ groupId }) => groupId), params.entries)
31
31
  : buildToolAvailabilityOverview(params.entries ?? [], params.groups, level);
32
32
  const message = Object.freeze({
33
33
  role: "system",
@@ -1,3 +1,4 @@
1
1
  import type { ToolAvailabilityEntry } from "../../capabilities/tool-types.js";
2
- /** Complete request-registry facts; neither a selected subset nor tool schemas. */
3
- export declare function buildCapabilityDescriptions(entries: readonly ToolAvailabilityEntry[]): string;
2
+ export declare const PLUGIN_DISCOVERY_CATALOG_HEADER = "Tool groups:";
3
+ /** Passive discovery: selectable groups first, with plugin descriptions once. */
4
+ export declare function buildPluginDiscoveryCatalogText(catalogGroupIds: readonly string[], entries?: readonly ToolAvailabilityEntry[]): string;
@@ -1,23 +1,60 @@
1
- /** Complete request-registry facts; neither a selected subset nor tool schemas. */
2
- export function buildCapabilityDescriptions(entries) {
3
- const ordered = [...entries].sort(compareCapabilityDescriptions);
4
- return JSON.stringify(ordered.map(({ toolName, operationId, summary, catalogGroups }) => ({
5
- toolName,
6
- operationId,
7
- summary,
8
- catalogGroups: [...new Set(catalogGroups)].sort(compareAscii),
9
- })));
1
+ export const PLUGIN_DISCOVERY_CATALOG_HEADER = "Tool groups:";
2
+ /** Passive discovery: selectable groups first, with plugin descriptions once. */
3
+ export function buildPluginDiscoveryCatalogText(catalogGroupIds, entries = []) {
4
+ const offeredGroups = new Set(catalogGroupIds);
5
+ const toolsByGroup = new Map();
6
+ const descriptions = new Map();
7
+ for (const entry of entries) {
8
+ const groupIds = entry.catalogGroups.filter((id) => offeredGroups.has(id));
9
+ if (groupIds.length === 0)
10
+ continue;
11
+ // The empty owner denotes a native tool, never a fabricated plugin.
12
+ const owner = entry.pluginName ?? "";
13
+ for (const id of groupIds) {
14
+ const owners = toolsByGroup.get(id) ?? new Map();
15
+ const toolNames = owners.get(owner) ?? new Set();
16
+ toolNames.add(entry.toolName);
17
+ owners.set(owner, toolNames);
18
+ toolsByGroup.set(id, owners);
19
+ }
20
+ if (!entry.pluginName)
21
+ continue;
22
+ const description = descriptions.get(entry.pluginName)
23
+ || formatPluginDiscoveryDescription(entry.pluginDescription);
24
+ if (description)
25
+ descriptions.set(entry.pluginName, description);
26
+ }
27
+ const hasOfferedToolBindings = toolsByGroup.size > 0;
28
+ if (!hasOfferedToolBindings) {
29
+ return catalogGroupIds.length > 0
30
+ ? `${PLUGIN_DISCOVERY_CATALOG_HEADER} ${catalogGroupIds.join(", ")}`
31
+ : PLUGIN_DISCOVERY_CATALOG_HEADER;
32
+ }
33
+ const groupEntries = [...offeredGroups].sort().map((id) => {
34
+ const owners = toolsByGroup.get(id);
35
+ if (!owners)
36
+ return id;
37
+ const bindings = [...owners.keys()].sort().map((owner) => {
38
+ const names = [...owners.get(owner)].sort().map(formatPluginDiscoveryToolName).join(", ");
39
+ return owner ? `${owner} [${names}]` : names;
40
+ });
41
+ return `${id}: ${bindings.join(", ")}`;
42
+ });
43
+ const catalog = `${PLUGIN_DISCOVERY_CATALOG_HEADER} ${groupEntries.join(" | ")}`;
44
+ const pluginDescriptions = [...descriptions.keys()].sort().map((name) => `${name}: ${descriptions.get(name)}`);
45
+ return pluginDescriptions.length > 0
46
+ ? `${catalog}\nPlugin descriptions: ${pluginDescriptions.join(" | ")}`
47
+ : catalog;
10
48
  }
11
- function compareCapabilityDescriptions(left, right) {
12
- const byOperation = compareAscii(left.operationId, right.operationId);
13
- if (byOperation !== 0)
14
- return byOperation;
15
- return compareAscii(left.toolName, right.toolName);
49
+ function formatPluginDiscoveryToolName(name) {
50
+ return name.replace(/[%\\[\],;:|\s\u0000-\u001f\u007f]/gu, (character) => encodeURIComponent(character));
16
51
  }
17
- function compareAscii(left, right) {
18
- if (left < right)
19
- return -1;
20
- if (left > right)
21
- return 1;
22
- return 0;
52
+ function formatPluginDiscoveryDescription(description) {
53
+ if (description === undefined)
54
+ return undefined;
55
+ const normalized = description.replaceAll("|", "/").replace(/\s+/gu, " ").trim();
56
+ const characters = Array.from(normalized);
57
+ if (characters.length <= 160)
58
+ return normalized;
59
+ return `${characters.slice(0, 160).join("")}....`;
23
60
  }
@@ -1,7 +1,7 @@
1
1
  import type { ChatMessage } from "../../../model-gateway/types.js";
2
2
  import type { RequestExecutionScope } from "../../request/execution-scope.js";
3
3
  import type { RequestSteeringSnapshot } from "../../request/request-steering.js";
4
- import type { LearningKnowledgeEntry } from "../maturation/contracts.js";
4
+ import type { LearningKnowledgeEntry, LearningKnowledgeContext } from "../maturation/contracts.js";
5
5
  import type { ConversationMemoryEvidence } from "../maturation/evidence-contracts.js";
6
6
  export type ConversationMemoryAuthoringContext = Readonly<{
7
7
  evidence: ConversationMemoryEvidence;
@@ -12,3 +12,8 @@ export type ConversationMemoryAuthoringContext = Readonly<{
12
12
  export declare function canAuthorConversationMemory(request: Pick<RequestExecutionScope, "longTermMemory">, context: ConversationMemoryAuthoringContext | undefined): boolean;
13
13
  /** Request-local authoring reference; never part of ordinary recall or routing. */
14
14
  export declare function prepareConversationMemoryAuthoring(request: Pick<RequestExecutionScope, "longTermMemory" | "requestId" | "sessionId" | "prompt" | "abortSignal">, steering: RequestSteeringSnapshot): Promise<ConversationMemoryAuthoringContext | undefined>;
15
+ export declare function prepareConversationMemoryKnowledge(request: Pick<RequestExecutionScope, "longTermMemory" | "requestId" | "sessionId" | "prompt" | "abortSignal">, steering: RequestSteeringSnapshot): Promise<LearningKnowledgeContext | undefined>;
16
+ /** Shared deterministic binding for decision and response authoring. No retrieval. */
17
+ export declare function buildConversationMemoryAuthoringContext(request: Pick<RequestExecutionScope, "requestId" | "sessionId" | "prompt">, steering: RequestSteeringSnapshot, context: Pick<LearningKnowledgeContext, "entries" | "omitted" | "referenceTime">): ConversationMemoryAuthoringContext;
18
+ /** The same contract projection must precede ledger cloning and durable approval capture. */
19
+ export declare function projectConversationMemoryKnowledge(context: LearningKnowledgeContext): LearningKnowledgeContext;
@@ -10,6 +10,10 @@ export function canAuthorConversationMemory(request, context) {
10
10
  }
11
11
  /** Request-local authoring reference; never part of ordinary recall or routing. */
12
12
  export async function prepareConversationMemoryAuthoring(request, steering) {
13
+ const context = await prepareConversationMemoryKnowledge(request, steering);
14
+ return context ? buildConversationMemoryAuthoringContext(request, steering, context) : undefined;
15
+ }
16
+ export async function prepareConversationMemoryKnowledge(request, steering) {
13
17
  const learning = request.longTermMemory?.learning;
14
18
  if (!request.longTermMemory?.enabled || !learning)
15
19
  return undefined;
@@ -19,31 +23,7 @@ export async function prepareConversationMemoryAuthoring(request, steering) {
19
23
  abortSignal: request.abortSignal,
20
24
  debugRequestId: request.requestId,
21
25
  });
22
- const evidence = Object.freeze({
23
- sourceSessionId: request.sessionId,
24
- sourceRequestId: request.requestId,
25
- observedAt: context.referenceTime,
26
- evidenceDigest: createHash("sha256").update(JSON.stringify([
27
- request.prompt, ...steering.updates.map(({ text }) => text),
28
- ])).digest("hex"),
29
- });
30
- const entries = structuredClone(context.entries);
31
- const targets = new Map(entries.map((entry, index) => [`k${index + 1}`, Object.freeze(entry)]));
32
- return Object.freeze({
33
- evidence, targets,
34
- userMessages: Object.freeze([request.prompt, ...steering.updates.map(({ text }) => text)]),
35
- message: Object.freeze({ role: "system", content: JSON.stringify({
36
- kind: "conversation_memory_authoring_reference_v1",
37
- authority: "passive_memory_reference",
38
- purpose: "assess_lasting_user_knowledge_and_resolve_optional_update_targets",
39
- applicability: "memoryCandidates_only",
40
- presenceEffect: "not_user_intent_fresh_evidence_or_action_authority",
41
- targetPolicy: "null_creates_candidate_only_use_supplied_mutable_refs_for_updates",
42
- omitted: context.omitted,
43
- omissionMeaning: "unlisted_knowledge_is_unknown_and_cannot_be_targeted",
44
- entries: [...targets].map(([ref, { id: _id, version: _version, ...entry }]) => ({ ref, ...entry })),
45
- }) }),
46
- });
26
+ return context;
47
27
  }
48
28
  catch (error) {
49
29
  request.abortSignal.throwIfAborted();
@@ -53,3 +33,49 @@ export async function prepareConversationMemoryAuthoring(request, steering) {
53
33
  return undefined;
54
34
  }
55
35
  }
36
+ /** Shared deterministic binding for decision and response authoring. No retrieval. */
37
+ export function buildConversationMemoryAuthoringContext(request, steering, context) {
38
+ const evidence = Object.freeze({
39
+ sourceSessionId: request.sessionId,
40
+ sourceRequestId: request.requestId,
41
+ observedAt: context.referenceTime,
42
+ evidenceDigest: createHash("sha256").update(JSON.stringify([
43
+ request.prompt, ...steering.updates.map(({ text }) => text),
44
+ ])).digest("hex"),
45
+ });
46
+ // Project only contract fields, including when entries come from a saved checkpoint.
47
+ const entries = context.entries.map(projectConversationMemoryKnowledgeEntry);
48
+ const targets = new Map(entries.map((entry, index) => [`k${index + 1}`, Object.freeze(entry)]));
49
+ return Object.freeze({
50
+ evidence, targets,
51
+ userMessages: Object.freeze([request.prompt, ...steering.updates.map(({ text }) => text)]),
52
+ message: Object.freeze({ role: "system", content: JSON.stringify({
53
+ kind: "conversation_memory_authoring_reference_v1",
54
+ authority: "passive_memory_reference",
55
+ purpose: "assess_lasting_user_knowledge_and_resolve_optional_update_targets",
56
+ applicability: "memoryCandidates_only",
57
+ presenceEffect: "not_user_intent_fresh_evidence_or_action_authority",
58
+ targetPolicy: "null_creates_candidate_only_use_supplied_mutable_refs_for_updates",
59
+ omitted: context.omitted,
60
+ omissionMeaning: "unlisted_knowledge_is_unknown_and_cannot_be_targeted",
61
+ entries: [...targets].map(([ref, { id: _id, version: _version, ...entry }]) => ({ ref, ...entry })),
62
+ }) }),
63
+ });
64
+ }
65
+ /** The same contract projection must precede ledger cloning and durable approval capture. */
66
+ export function projectConversationMemoryKnowledge(context) {
67
+ return {
68
+ kind: context.kind, authority: context.authority, presenceEffect: context.presenceEffect,
69
+ repositoryRevision: context.repositoryRevision, knowledgeRevision: context.knowledgeRevision,
70
+ referenceTime: context.referenceTime, omitted: context.omitted,
71
+ entries: context.entries.map(projectConversationMemoryKnowledgeEntry),
72
+ };
73
+ }
74
+ function projectConversationMemoryKnowledgeEntry(entry) {
75
+ return {
76
+ kind: entry.kind, id: entry.id, version: entry.version,
77
+ content: entry.content, tags: [...entry.tags], mutable: entry.mutable,
78
+ score: entry.score, reason: entry.reason, certainty: entry.certainty,
79
+ lastReinforcedAt: entry.lastReinforcedAt, reconsiderAt: entry.reconsiderAt,
80
+ };
81
+ }
@@ -0,0 +1,17 @@
1
+ import type { RequestExecutionScope } from "../request/execution-scope.js";
2
+ import type { ChatMessage } from "../../model-gateway/types.js";
3
+ import { type RequestSteeringSnapshot } from "../request/request-steering.js";
4
+ import type { RoleInitialMemory } from "../orchestration/role-calls/memory-recall-contract.js";
5
+ /** Prepared once as part of the existing request ledger initialization. */
6
+ export declare function prepareInitialMemory(request: RequestExecutionScope, restored?: RoleInitialMemory): Promise<RoleInitialMemory | undefined>;
7
+ export declare function projectExecutionAgentMemory(request: RequestExecutionScope, initial: RoleInitialMemory | undefined, steering: RequestSteeringSnapshot): Readonly<{
8
+ memoryMessage: ChatMessage | undefined;
9
+ authoringContext: Readonly<{
10
+ evidence: import("./maturation/evidence-contracts.js").ConversationMemoryEvidence;
11
+ targets: ReadonlyMap<string, import("./maturation/contracts.js").LearningKnowledgeEntry>;
12
+ userMessages: readonly string[];
13
+ message: ChatMessage;
14
+ }> | undefined;
15
+ authoringEnabled: boolean;
16
+ }>;
17
+ export type ExecutionMemoryProjection = ReturnType<typeof projectExecutionAgentMemory>;
@@ -0,0 +1,57 @@
1
+ import { resolveRequestSteeringInbox } from "../request/request-steering.js";
2
+ import { retrieveResponseLongTermMemory } from "./response-context.js";
3
+ import { prepareConversationMemoryKnowledge, buildConversationMemoryAuthoringContext, canAuthorConversationMemory, projectConversationMemoryKnowledge, } from "./conversation-authoring/context.js";
4
+ /** Prepared once as part of the existing request ledger initialization. */
5
+ export async function prepareInitialMemory(request, restored) {
6
+ if (!usesInitialMemory(request))
7
+ return undefined;
8
+ if (restored !== undefined)
9
+ return restored;
10
+ request.abortSignal.throwIfAborted();
11
+ const steering = resolveRequestSteeringInbox(request.requestSteering).snapshot();
12
+ const message = await retrieveResponseLongTermMemory(request, steering);
13
+ request.abortSignal.throwIfAborted();
14
+ // EA prepares authoring targets at startup; Supervisor keeps its terminal step.
15
+ const knowledge = usesInitialExecutionMemory(request)
16
+ ? await prepareConversationMemoryKnowledge(request, steering)
17
+ : undefined;
18
+ request.abortSignal.throwIfAborted();
19
+ return Object.freeze({
20
+ ...(message ? { message: projectPersistentMemoryMessage(message) } : {}),
21
+ ...(knowledge ? { knowledge: projectConversationMemoryKnowledge(knowledge) } : {}),
22
+ });
23
+ }
24
+ function projectPersistentMemoryMessage(message) {
25
+ if (!message.attachments)
26
+ return message;
27
+ return { ...message, attachments: message.attachments.filter(isPersistentMemoryAttachment) };
28
+ }
29
+ function isPersistentMemoryAttachment(attachment) {
30
+ return attachment.toolEvidence === undefined;
31
+ }
32
+ function usesInitialMemory(request) {
33
+ if (!request.longTermMemory?.enabled)
34
+ return false;
35
+ if (request.executionPolicy.authority.id === "execution-agent-v1")
36
+ return true;
37
+ return request.executionPolicy.authority.id === "supervisor-worker-v1";
38
+ }
39
+ export function projectExecutionAgentMemory(request, initial, steering) {
40
+ if (!usesInitialExecutionMemory(request))
41
+ return { memoryMessage: undefined, authoringContext: undefined, authoringEnabled: false };
42
+ const authoringContext = initial?.knowledge
43
+ ? buildConversationMemoryAuthoringContext(request, steering, {
44
+ ...initial.knowledge, referenceTime: new Date().toISOString(),
45
+ })
46
+ : undefined;
47
+ return Object.freeze({
48
+ memoryMessage: initial?.message,
49
+ authoringContext,
50
+ authoringEnabled: canAuthorConversationMemory(request, authoringContext),
51
+ });
52
+ }
53
+ function usesInitialExecutionMemory(request) {
54
+ if (!request.longTermMemory?.enabled)
55
+ return false;
56
+ return request.executionPolicy.authority.id === "execution-agent-v1";
57
+ }
@@ -32,7 +32,7 @@ function serializeProjection(records) {
32
32
  return JSON.stringify({
33
33
  kind: LONG_TERM_MEMORY_MESSAGE_KIND,
34
34
  authority: "passive_reference",
35
- purpose: "support_personalized_terminal_response_authoring",
35
+ purpose: "support_root_decisions_and_response_authoring",
36
36
  memories: records.map((record) => ({
37
37
  content: record.content,
38
38
  tags: record.tags,
@@ -2,7 +2,7 @@ import { isRuntimeDelegateRoleId, RUNTIME_ROOT_ROLE_ID, RUNTIME_ROLE_IDS, } from
2
2
  import { createRoleCapabilitySelectionFingerprint, normalizeRoleCapabilitySelectionProjection, } from "./capability-selection-reconsideration.js";
3
3
  import { isRoleCapabilitySelectionSupervisionState, } from "./capability-selection-supervision.js";
4
4
  import { isValidRoleCapabilitySelectionSupervision } from "./capability-selection-supervision-validation.js";
5
- import { validateRoleMemoryRecalls } from "./memory-recall-state-validation.js";
5
+ import { hasInitialMemoryContext, validateRoleMemoryRecalls } from "./memory-recall-state-validation.js";
6
6
  import { isValidAdoptedModelWorkPlan } from "./work-plan-validation.js";
7
7
  import { isRoleOperationFingerprint, isRoleOperationOutcomeFingerprintForOutcome, isSameRoleOperationIdentity, replayRoleOperationSupervisionEvidence, } from "./operation-supervision.js";
8
8
  import { isIssuedRoleOperationSupervisionInterventionForRequest } from "./operation-supervision-issuance.js";
@@ -48,6 +48,7 @@ export function validateRoleCallState(state, policy) {
48
48
  !Array.isArray(state?.plans) ||
49
49
  !Array.isArray(state?.capabilityExecutions) ||
50
50
  !Array.isArray(state?.memoryRecalls) ||
51
+ !hasInitialMemoryContext(state?.initialMemory, policy.authority.id) ||
51
52
  !isRoleOperationSupervisionState(state?.operationSupervision) ||
52
53
  !isRoleCapabilitySelectionSupervisionState(state?.capabilitySelectionSupervision) ||
53
54
  !Number.isInteger(state?.callSequence) ||
@@ -1,4 +1,4 @@
1
1
  import type { RoleCallLedgerCheckpoint } from "./checkpoint-contract.js";
2
2
  import type { RoleCallPolicy, RoleCallState } from "./contracts.js";
3
3
  /** Hydrate only an admitted, parked capability; no model or reducer command replay. */
4
- export declare function restoreCheckpointState(checkpoint: RoleCallLedgerCheckpoint, requestId: string, policy: RoleCallPolicy): RoleCallState;
4
+ export declare function restoreCheckpointState(checkpoint: RoleCallLedgerCheckpoint, requestId: string, policy: RoleCallPolicy, initialMemory?: RoleCallState["initialMemory"]): RoleCallState;
@@ -4,14 +4,17 @@ import { validateRoleCallCandidate } from "./reducer.js";
4
4
  import { issueInitialRoleCapabilitySelectionSupervisionState } from "./capability-selection-supervision-issuance.js";
5
5
  import { restoreRoleOperationSupervisionIssuance } from "./operation-supervision-issuance.js";
6
6
  /** Hydrate only an admitted, parked capability; no model or reducer command replay. */
7
- export function restoreCheckpointState(checkpoint, requestId, policy) {
7
+ export function restoreCheckpointState(checkpoint, requestId, policy, initialMemory) {
8
8
  if (!isCheckpointEnvelope(checkpoint))
9
9
  throw new Error("role_call_checkpoint_invalid");
10
10
  if (!hasCheckpointRequestIdentity(checkpoint, requestId))
11
11
  throw new Error("role_call_checkpoint_request_mismatch");
12
12
  if (!hasCheckpointPolicy(checkpoint, policy))
13
13
  throw new Error("role_call_checkpoint_policy_mismatch");
14
- const state = seal(structuredClone(checkpoint.state));
14
+ const state = seal(structuredClone({ ...checkpoint.state,
15
+ ...(checkpoint.state.initialMemory === undefined && initialMemory !== undefined
16
+ ? { initialMemory } : {}),
17
+ }));
15
18
  if (!isParkedCapabilityState(state))
16
19
  throw new Error("role_call_checkpoint_not_parked");
17
20
  if (!issueInitialRoleCapabilitySelectionSupervisionState(state))
@@ -5,7 +5,7 @@ import type { RoleOperationFingerprint, RoleOperationOutcomeFingerprint, RoleOpe
5
5
  import type { RoleCapabilitySelectionSupervisionStage, RoleCapabilitySelectionSupervisionState, RoleCapabilitySelectionSupervisionTrigger } from "./capability-selection-supervision.js";
6
6
  import type { RoleCapabilitySelectionReconsiderationCause } from "./reconsideration-cause.js";
7
7
  import type { RoleCallResultReceipt } from "./result-receipt.js";
8
- import type { RoleMemoryRecall, RoleMemoryRecallCommand, RoleMemoryRecallCommitEffect, RoleMemoryRecallTransactions } from "./memory-recall-contract.js";
8
+ import type { RoleInitialMemory, RoleMemoryRecall, RoleMemoryRecallCommand, RoleMemoryRecallCommitEffect, RoleMemoryRecallTransactions } from "./memory-recall-contract.js";
9
9
  import type { AdoptedModelWorkPlan, UpdateModelWorkPlanCommand, ModelWorkPlanCommitEffect, ModelWorkPlanTransactions } from "./work-plan-contracts.js";
10
10
  export declare const ROLE_CALL_LEDGER_CONTRACT_VERSION = 18;
11
11
  export declare const ROLE_CALL_LEDGER_HEAD_KIND: "runtime_role_call_ledger_v18";
@@ -191,6 +191,7 @@ export type RoleCallState = Readonly<{
191
191
  plans: readonly RoleCallPlanState[];
192
192
  capabilityExecutions: readonly RoleCapabilityExecution[];
193
193
  memoryRecalls: readonly RoleMemoryRecall[];
194
+ initialMemory?: RoleInitialMemory;
194
195
  operationSupervision: RoleOperationSupervisionState;
195
196
  capabilitySelectionSupervision: RoleCapabilitySelectionSupervisionState;
196
197
  rootResponse: string | null;
@@ -1,9 +1,10 @@
1
1
  import type { RoleCallLedgerCheckpoint } from "./checkpoint-contract.js";
2
- import { type RoleCallLedger, type RoleCallLedgerHead, type RoleCallPolicyInput } from "./contracts.js";
2
+ import { type RoleCallLedger, type RoleCallLedgerHead, type RoleCallPolicyInput, type RoleCallState } from "./contracts.js";
3
3
  export declare function createRoleCallLedger(params: {
4
4
  requestId: string;
5
5
  policy: RoleCallPolicyInput;
6
6
  checkpoint?: RoleCallLedgerCheckpoint;
7
+ initialMemory?: RoleCallState["initialMemory"];
7
8
  }): RoleCallLedger;
8
9
  /** Confirms exact current-head ownership without trusting structural ledgers. */
9
10
  export declare function isCurrentRoleCallLedgerHead(ledger: RoleCallLedger, head: RoleCallLedgerHead): boolean;
@@ -15,8 +15,8 @@ const issuedRoleCallLedgerHeads = new WeakMap();
15
15
  export function createRoleCallLedger(params) {
16
16
  const policy = sealRoleCallPolicy(params.policy);
17
17
  const initialState = params.checkpoint
18
- ? restoreCheckpointState(params.checkpoint, params.requestId, policy)
19
- : createInitialRoleCallState(params.requestId);
18
+ ? restoreCheckpointState(params.checkpoint, params.requestId, policy, params.initialMemory)
19
+ : createInitialRoleCallState(params.requestId, params.initialMemory);
20
20
  const capabilitySelectionSupervisionIssuanceAuthority = resolveRoleCapabilitySelectionSupervisionIssuanceAuthority(initialState);
21
21
  if (!capabilitySelectionSupervisionIssuanceAuthority) {
22
22
  throw new Error("role_call_capability_selection_supervision_issuance_authority_missing");
@@ -1,3 +1,5 @@
1
+ import type { ChatMessage } from "../../../model-gateway/types.js";
2
+ import type { LearningKnowledgeContext } from "../../long-term-memory/maturation/contracts.js";
1
3
  import type { LongTermMemoryRecord } from "../../long-term-memory/contracts.js";
2
4
  import type { RoleCallTransactionInput, RoleCallTransactionResult } from "./contracts.js";
3
5
  export declare const ROLE_MEMORY_RECALL_QUERY_MAX_LENGTH = 1024;
@@ -49,3 +51,8 @@ export type RoleMemoryRecallTransactions = Readonly<{
49
51
  beginMemoryRecall(input: RoleCallTransactionInput<BeginRoleMemoryRecallCommand>): Promise<RoleCallTransactionResult<"memory_recall_begun", "memory_recall_transition_invalid">>;
50
52
  settleMemoryRecall(input: RoleCallTransactionInput<SettleRoleMemoryRecallCommand>): Promise<RoleCallTransactionResult<"memory_recall_settled", "memory_recall_transition_invalid">>;
51
53
  }>;
54
+ /** Initial automatic reference; never a model recall or an activation. */
55
+ export type RoleInitialMemory = Readonly<{
56
+ message?: ChatMessage;
57
+ knowledge?: LearningKnowledgeContext;
58
+ }>;
@@ -1,3 +1,5 @@
1
1
  import type { RoleCallState, RoleCallValidationIssue } from "./contracts.js";
2
2
  export declare function validateRoleMemoryRecalls(state: RoleCallState): RoleCallValidationIssue[];
3
3
  export declare function hasSettledMemoryRecallActivationRange(state: RoleCallState, callId: string, fromActivation: number, toActivation: number): boolean;
4
+ /** The existing checkpoint carries this passive startup field, never a model action. */
5
+ export declare function hasInitialMemoryContext(value: unknown, policyId: string): boolean;