@tomflow/proflow-platform-host 0.1.18 → 0.1.19

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @tomflow/proflow-platform-host
2
2
 
3
+ ## 0.1.19
4
+
5
+ ### Patch Changes
6
+
7
+ - Release the verified Real-3 B1 task recovery, exact execution identity, durable observer resume, bounded gateway error, and matching Agent Action contract fixes.
8
+
3
9
  ## 0.1.18
4
10
 
5
11
  ### Patch Changes
@@ -6,7 +6,7 @@ export declare const behaviorAdapter: {
6
6
  ok: true;
7
7
  status: "SUCCEEDED";
8
8
  moduleRef: "platform-host";
9
- moduleVersion: "0.1.18";
9
+ moduleVersion: "0.1.19";
10
10
  data: {
11
11
  endpoint: string;
12
12
  stateRoot: string;
@@ -24,7 +24,7 @@ export declare const behaviorAdapter: {
24
24
  readonly ok: true;
25
25
  readonly status: "SUCCEEDED";
26
26
  readonly moduleRef: "platform-host";
27
- readonly moduleVersion: "0.1.18";
27
+ readonly moduleVersion: "0.1.19";
28
28
  };
29
29
  observedEffects: string[];
30
30
  }>;
@@ -34,7 +34,7 @@ export declare const behaviorAdapter: {
34
34
  ok: true;
35
35
  status: "SUCCEEDED";
36
36
  moduleRef: "platform-host";
37
- moduleVersion: "0.1.18";
37
+ moduleVersion: "0.1.19";
38
38
  data: {
39
39
  setupStatus: "READY";
40
40
  runtimeStatus: "RUNNING" | "STOPPED";
@@ -55,7 +55,7 @@ export declare const behaviorAdapter: {
55
55
  ok: true;
56
56
  status: "SUCCEEDED";
57
57
  moduleRef: "platform-host";
58
- moduleVersion: "0.1.18";
58
+ moduleVersion: "0.1.19";
59
59
  data: {
60
60
  endpoint: string;
61
61
  stateRoot: string;
@@ -73,7 +73,7 @@ export declare const behaviorAdapter: {
73
73
  ok: true;
74
74
  status: "SUCCEEDED";
75
75
  moduleRef: "platform-host";
76
- moduleVersion: "0.1.18";
76
+ moduleVersion: "0.1.19";
77
77
  data: {
78
78
  docs: string;
79
79
  };
@@ -86,7 +86,7 @@ export declare const behaviorAdapter: {
86
86
  ok: true;
87
87
  status: "SUCCEEDED";
88
88
  moduleRef: "platform-host";
89
- moduleVersion: "0.1.18";
89
+ moduleVersion: "0.1.19";
90
90
  data: {
91
91
  host: string;
92
92
  port: number;
@@ -97,7 +97,7 @@ export declare const behaviorAdapter: {
97
97
  result: {
98
98
  contract: "deployment.result.v1";
99
99
  moduleRef: "platform-host";
100
- moduleVersion: "0.1.18";
100
+ moduleVersion: "0.1.19";
101
101
  ok: false;
102
102
  status: "FAILED";
103
103
  error: {
@@ -114,7 +114,7 @@ export declare const behaviorAdapter: {
114
114
  readonly ok: true;
115
115
  readonly status: "SUCCEEDED";
116
116
  readonly moduleRef: "platform-host";
117
- readonly moduleVersion: "0.1.18";
117
+ readonly moduleVersion: "0.1.19";
118
118
  };
119
119
  observedEffects: string[];
120
120
  } | {
@@ -123,11 +123,11 @@ export declare const behaviorAdapter: {
123
123
  readonly ok: true;
124
124
  readonly status: "SUCCEEDED";
125
125
  readonly moduleRef: "platform-host";
126
- readonly moduleVersion: "0.1.18";
126
+ readonly moduleVersion: "0.1.19";
127
127
  } | {
128
128
  contract: "deployment.result.v1";
129
129
  moduleRef: "platform-host";
130
- moduleVersion: "0.1.18";
130
+ moduleVersion: "0.1.19";
131
131
  ok: false;
132
132
  status: "FAILED";
133
133
  error: {
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "platform-host";
5
5
  readonly packageName: "@tomflow/proflow-platform-host";
6
- readonly moduleVersion: "0.1.18";
6
+ readonly moduleVersion: "0.1.19";
7
7
  readonly kind: "service";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "platform-host",
5
5
  packageName: "@tomflow/proflow-platform-host",
6
- moduleVersion: "0.1.18",
6
+ moduleVersion: "0.1.19",
7
7
  kind: "service",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
@@ -192,6 +192,7 @@ export type PlatformHostTaskDriverPorts = {
192
192
  } | null;
193
193
  canDrive: boolean;
194
194
  blockedReason: string | null;
195
+ resumeSignalRef: string | null;
195
196
  }>;
196
197
  getNodeContext(taskId: string, nodeId: string): Promise<{
197
198
  task: {
package/dist/src/index.js CHANGED
@@ -324,6 +324,11 @@ function string(value, name) {
324
324
  throw new TypeError(`${name} must be a non-empty string`);
325
325
  return value;
326
326
  }
327
+ function positiveInteger(value, name) {
328
+ if (!Number.isInteger(value) || Number(value) <= 0)
329
+ throw new TypeError(`${name} must be a positive integer`);
330
+ return Number(value);
331
+ }
327
332
  function unwrap(result) {
328
333
  if (!result.ok || result.data === undefined)
329
334
  throw new Error(`OWNER_CONTRACT_FAILED:${JSON.stringify(result.error)}`);
@@ -628,6 +633,37 @@ async function constructGraph(config, executionCredential, modelCredential) {
628
633
  }
629
634
  return rawRecord;
630
635
  };
636
+ const admissionError = (code, httpStatus = 403) => {
637
+ throw Object.assign(new Error(code), { httpStatus });
638
+ };
639
+ const admitExactNodeExecution = async (input, authenticatedRoleRef) => {
640
+ const taskId = string(input.taskId, "taskId");
641
+ const nodeId = string(input.nodeId, "nodeId");
642
+ const runNo = positiveInteger(input.runNo, "runNo");
643
+ const workerRef = await admitTaskParticipant(taskId, authenticatedRoleRef);
644
+ await agent.validateWorker({ authenticatedRoleRef, taskId, workerRef });
645
+ const taskFact = taskFacts(taskId);
646
+ const nodeContext = unwrap(task.queries.getNodeContext({ taskId, nodeId }));
647
+ if (taskFact.status !== "ACTIVE")
648
+ admissionError("EXECUTION_TASK_NOT_ACTIVE");
649
+ if (taskFact.currentNodeId !== nodeId)
650
+ admissionError("EXECUTION_NODE_NOT_CURRENT");
651
+ if (nodeContext.node.status !== "IN_PROGRESS")
652
+ admissionError("EXECUTION_NODE_NOT_RUNNING");
653
+ if (nodeContext.node.runNo !== runNo)
654
+ admissionError("EXECUTION_GENERATION_MISMATCH");
655
+ const nodeBinding = taskFact.roleBindings.find((binding) => binding.agentPackageRef === nodeContext.node.requiredAgentPackageRef);
656
+ if (!nodeBinding)
657
+ throw Object.assign(new Error("TASK_ROLE_BINDING_REQUIRED"), {
658
+ httpStatus: 403,
659
+ });
660
+ if (nodeBinding.roleRef !== authenticatedRoleRef)
661
+ admissionError("EXECUTION_ROLE_SCOPE_MISMATCH");
662
+ if (nodeBinding.workerRef !== workerRef ||
663
+ nodeContext.node.workerRef !== workerRef)
664
+ admissionError("EXECUTION_WORKER_SCOPE_MISMATCH");
665
+ return { taskId, nodeId, runNo, workerRef };
666
+ };
631
667
  const route = async (operationId, authenticatedRoleRef, rawInput, context) => {
632
668
  const role = agent.getRegisteredRole(authenticatedRoleRef);
633
669
  if (!roleOperations[role.agentPackageRef]?.has(operationId))
@@ -690,23 +726,16 @@ async function constructGraph(config, executionCredential, modelCredential) {
690
726
  return taskResult;
691
727
  }
692
728
  if (operationId === "executeCapability") {
693
- const taskId = typeof input.taskId === "string" ? input.taskId : undefined;
694
- let canonicalWorkerRef;
695
- if (taskId) {
696
- canonicalWorkerRef = await admitTaskParticipant(taskId, authenticatedRoleRef, typeof input.workerRef === "string" ? input.workerRef : undefined);
697
- await agent.validateWorker({
698
- authenticatedRoleRef,
699
- taskId,
700
- workerRef: canonicalWorkerRef,
701
- });
702
- }
729
+ const scope = await admitExactNodeExecution(input, authenticatedRoleRef);
730
+ const { workerRef: _suppliedWorkerRef, projectRoot: _suppliedProjectRoot, roleRef: _suppliedRoleRef, callerRef: _suppliedCallerRef, ...ownerInput } = input;
703
731
  const result = await execution.invoke(operationId, {
704
- ...input,
732
+ ...ownerInput,
705
733
  callerRef: authenticatedRoleRef,
706
734
  roleRef: authenticatedRoleRef,
707
- ...(canonicalWorkerRef !== undefined
708
- ? { workerRef: canonicalWorkerRef }
709
- : {}),
735
+ taskId: scope.taskId,
736
+ nodeId: scope.nodeId,
737
+ runNo: scope.runNo,
738
+ workerRef: scope.workerRef,
710
739
  });
711
740
  // A normal Action may complete synchronously inside the current Worker Turn.
712
741
  // Do not manufacture a Browser RESUME for every terminal Execution record.
@@ -858,14 +887,14 @@ async function constructGraph(config, executionCredential, modelCredential) {
858
887
  return false;
859
888
  if (request.runNo !== nodeContext.node.runNo)
860
889
  return false;
861
- if (!browserCapability &&
862
- nodeContext.node.status !== "IN_PROGRESS")
890
+ if (!browserCapability && nodeContext.node.status !== "IN_PROGRESS")
863
891
  return false;
864
892
  const nodeBinding = taskFact.roleBindings.find((candidate) => candidate.agentPackageRef ===
865
893
  nodeContext.node.requiredAgentPackageRef);
866
894
  if (!nodeBinding?.workerRef)
867
895
  return false;
868
- const scopedRoleRef = request.roleRef ?? (internalBrowserCaller ? undefined : request.callerRef);
896
+ const scopedRoleRef = request.roleRef ??
897
+ (internalBrowserCaller ? undefined : request.callerRef);
869
898
  if (scopedRoleRef !== nodeBinding.roleRef)
870
899
  return false;
871
900
  if (request.workerRef !== nodeBinding.workerRef)
@@ -903,6 +932,7 @@ async function constructGraph(config, executionCredential, modelCredential) {
903
932
  const resumeWake = nodeContext.node.status === "IN_PROGRESS" &&
904
933
  (trigger === "RECOVERY_RESUME" ||
905
934
  trigger === "EXECUTION_RESULT_READY" ||
935
+ trigger === "TASK_RESUMED" ||
906
936
  trigger === "PEER_REPLY_READY");
907
937
  if (!readyWake && !resumeWake)
908
938
  return false;
@@ -1157,6 +1187,22 @@ async function constructGraph(config, executionCredential, modelCredential) {
1157
1187
  actorRef: "extension:human",
1158
1188
  idempotencyKey: string(value.idempotencyKey, "idempotencyKey"),
1159
1189
  }));
1190
+ if (operation === "message.acknowledge")
1191
+ return unwrap(task.commands.acknowledgeMessage({
1192
+ messageId: string(value.messageId, "messageId"),
1193
+ ...(typeof value.resolution === "string"
1194
+ ? { resolution: value.resolution }
1195
+ : {}),
1196
+ actorRef: "extension:human",
1197
+ idempotencyKey: string(value.idempotencyKey, "idempotencyKey"),
1198
+ }));
1199
+ if (operation === "task.resume")
1200
+ return unwrap(task.commands.resumeTask({
1201
+ taskId: string(value.taskId, "taskId"),
1202
+ expectedTaskVersion: positiveInteger(value.expectedTaskVersion, "expectedTaskVersion"),
1203
+ actorRef: "extension:human",
1204
+ idempotencyKey: string(value.idempotencyKey, "idempotencyKey"),
1205
+ }));
1160
1206
  if (operation === "node.reopen")
1161
1207
  return unwrap(task.commands.reopenNode({
1162
1208
  taskId: string(value.taskId, "taskId"),
@@ -1458,15 +1504,16 @@ async function constructGraph(config, executionCredential, modelCredential) {
1458
1504
  });
1459
1505
  return admitExecutionRead(authenticatedRoleRef, record);
1460
1506
  }
1461
- const taskId = typeof value.taskId === "string" ? value.taskId : undefined;
1462
- let canonicalWorkerRef;
1463
- if (taskId)
1464
- canonicalWorkerRef = await admitTaskParticipant(taskId, authenticatedRoleRef, typeof value.workerRef === "string" ? value.workerRef : undefined);
1507
+ const scope = await admitExactNodeExecution(value, authenticatedRoleRef);
1508
+ const { workerRef: _suppliedWorkerRef, projectRoot: _suppliedProjectRoot, roleRef: _suppliedRoleRef, callerRef: _suppliedCallerRef, ...ownerInput } = value;
1465
1509
  const record = await execution.invoke("lookupExecutionIntent", {
1466
- ...value,
1510
+ ...ownerInput,
1467
1511
  callerRef: authenticatedRoleRef,
1468
1512
  roleRef: authenticatedRoleRef,
1469
- ...(canonicalWorkerRef ? { workerRef: canonicalWorkerRef } : {}),
1513
+ taskId: scope.taskId,
1514
+ nodeId: scope.nodeId,
1515
+ runNo: scope.runNo,
1516
+ workerRef: scope.workerRef,
1470
1517
  });
1471
1518
  return admitExecutionRead(authenticatedRoleRef, record);
1472
1519
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-platform-host",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -25,18 +25,18 @@
25
25
  "dependencies": {
26
26
  "zod": "4.1.12",
27
27
  "@tomflow/proflow-agent-runtime": "^0.1.13",
28
- "@tomflow/proflow-execution-browser-extension": "^0.1.42",
29
28
  "@tomflow/proflow-execution-contracts": "^0.1.10",
29
+ "@tomflow/proflow-execution-browser-extension": "^0.1.45",
30
30
  "@tomflow/proflow-module-contract": "^0.1.13",
31
31
  "@tomflow/proflow-task-migration-runner": "^0.1.11",
32
- "@tomflow/proflow-task-store-sqlite": "^0.1.11",
33
- "@tomflow/proflow-task-orchestration": "^0.1.10"
32
+ "@tomflow/proflow-task-orchestration": "^0.1.11",
33
+ "@tomflow/proflow-task-store-sqlite": "^0.1.11"
34
34
  },
35
35
  "devDependencies": {
36
- "@tomflow/proflow-agent-gateway": "^0.1.15",
37
- "@tomflow/proflow-deployment-conformance": "^0.1.13",
36
+ "@tomflow/proflow-agent-gateway": "^0.1.16",
38
37
  "@tomflow/proflow-execution-runtime": "^0.1.18",
39
- "@tomflow/proflow-model-runtime": "^0.1.24"
38
+ "@tomflow/proflow-model-runtime": "^0.1.24",
39
+ "@tomflow/proflow-deployment-conformance": "^0.1.13"
40
40
  },
41
41
  "description": "Provides the ProFlow local application composition root that binds Task, Agent, Execution and Model owner transports.",
42
42
  "keywords": [
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "platform-host",
5
5
  "packageName": "@tomflow/proflow-platform-host",
6
- "moduleVersion": "0.1.18",
6
+ "moduleVersion": "0.1.19",
7
7
  "kind": "service",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",