@tomflow/proflow-execution-runtime 0.1.21 → 0.1.23

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,17 @@
1
1
  # @tomflow/proflow-execution-runtime
2
2
 
3
+ ## 0.1.23
4
+
5
+ ### Patch Changes
6
+
7
+ - fix(runtime): detect stale live package versions
8
+
9
+ ## 0.1.22
10
+
11
+ ### Patch Changes
12
+
13
+ - fix(runtime): normalize monitor locator identity
14
+
3
15
  ## 0.1.21
4
16
 
5
17
  ### Patch Changes
@@ -1,4 +1,18 @@
1
1
  import { type ModuleCommandContext } from "@tomflow/proflow-module-contract";
2
+ export declare function classifyExecutionRuntimeLiveProbe(input: {
3
+ running: boolean;
4
+ observedModuleVersion?: string;
5
+ expectedModuleVersion: string;
6
+ }): {
7
+ runtimeStatus: "RUNNING" | "STOPPED" | "FAILED";
8
+ issue?: {
9
+ scope: "RUNTIME";
10
+ code: "RUNTIME_VERSION_MISMATCH";
11
+ message: string;
12
+ relatedModuleRefs: string[];
13
+ nextCommand: "platform start";
14
+ };
15
+ };
2
16
  export declare const behaviorAdapter: {
3
17
  readonly install: (context: ModuleCommandContext) => Promise<{
4
18
  result: {
@@ -6,7 +20,7 @@ export declare const behaviorAdapter: {
6
20
  ok: true;
7
21
  status: "SUCCEEDED";
8
22
  moduleRef: "execution-runtime";
9
- moduleVersion: "0.1.21";
23
+ moduleVersion: "0.1.23";
10
24
  data: {
11
25
  endpoint: string;
12
26
  transportCredentialFile: string;
@@ -23,7 +37,7 @@ export declare const behaviorAdapter: {
23
37
  readonly ok: true;
24
38
  readonly status: "SUCCEEDED";
25
39
  readonly moduleRef: "execution-runtime";
26
- readonly moduleVersion: "0.1.21";
40
+ readonly moduleVersion: "0.1.23";
27
41
  };
28
42
  observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
29
43
  }>;
@@ -33,10 +47,10 @@ export declare const behaviorAdapter: {
33
47
  ok: true;
34
48
  status: "SUCCEEDED";
35
49
  moduleRef: "execution-runtime";
36
- moduleVersion: "0.1.21";
50
+ moduleVersion: "0.1.23";
37
51
  data: {
38
52
  setupStatus: "READY";
39
- runtimeStatus: "RUNNING" | "STOPPED";
53
+ runtimeStatus: "FAILED" | "RUNNING" | "STOPPED";
40
54
  issues?: {
41
55
  scope: "RUNTIME";
42
56
  code: string;
@@ -54,7 +68,7 @@ export declare const behaviorAdapter: {
54
68
  ok: true;
55
69
  status: "SUCCEEDED";
56
70
  moduleRef: "execution-runtime";
57
- moduleVersion: "0.1.21";
71
+ moduleVersion: "0.1.23";
58
72
  data: {
59
73
  endpoint: string;
60
74
  transportCredentialFile: string;
@@ -71,7 +85,7 @@ export declare const behaviorAdapter: {
71
85
  ok: true;
72
86
  status: "SUCCEEDED";
73
87
  moduleRef: "execution-runtime";
74
- moduleVersion: "0.1.21";
88
+ moduleVersion: "0.1.23";
75
89
  data: {
76
90
  docs: string;
77
91
  };
@@ -84,7 +98,7 @@ export declare const behaviorAdapter: {
84
98
  ok: true;
85
99
  status: "SUCCEEDED";
86
100
  moduleRef: "execution-runtime";
87
- moduleVersion: "0.1.21";
101
+ moduleVersion: "0.1.23";
88
102
  data: unknown;
89
103
  };
90
104
  observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
@@ -92,7 +106,7 @@ export declare const behaviorAdapter: {
92
106
  result: {
93
107
  contract: "deployment.result.v1";
94
108
  moduleRef: "execution-runtime";
95
- moduleVersion: "0.1.21";
109
+ moduleVersion: "0.1.23";
96
110
  ok: false;
97
111
  status: "FAILED";
98
112
  error: {
@@ -109,7 +123,7 @@ export declare const behaviorAdapter: {
109
123
  readonly ok: true;
110
124
  readonly status: "SUCCEEDED";
111
125
  readonly moduleRef: "execution-runtime";
112
- readonly moduleVersion: "0.1.21";
126
+ readonly moduleVersion: "0.1.23";
113
127
  };
114
128
  observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
115
129
  } | {
@@ -118,11 +132,11 @@ export declare const behaviorAdapter: {
118
132
  readonly ok: true;
119
133
  readonly status: "SUCCEEDED";
120
134
  readonly moduleRef: "execution-runtime";
121
- readonly moduleVersion: "0.1.21";
135
+ readonly moduleVersion: "0.1.23";
122
136
  } | {
123
137
  contract: "deployment.result.v1";
124
138
  moduleRef: "execution-runtime";
125
- moduleVersion: "0.1.21";
139
+ moduleVersion: "0.1.23";
126
140
  ok: false;
127
141
  status: "FAILED";
128
142
  error: {
@@ -53,19 +53,55 @@ async function startupDependencies(context) {
53
53
  const browserExecutorConfigPath = factString(browser, "browserExecutorConfigPath");
54
54
  return browserExecutorConfigPath ? { browserExecutorConfigPath } : undefined;
55
55
  }
56
- async function running(context) {
56
+ export function classifyExecutionRuntimeLiveProbe(input) {
57
+ if (!input.running)
58
+ return { runtimeStatus: "STOPPED" };
59
+ if (input.observedModuleVersion !== input.expectedModuleVersion)
60
+ return {
61
+ runtimeStatus: "FAILED",
62
+ issue: {
63
+ scope: "RUNTIME",
64
+ code: "RUNTIME_VERSION_MISMATCH",
65
+ message: `execution-runtime 运行版本 ${input.observedModuleVersion ?? "unknown"} 与当前安装版本 ${input.expectedModuleVersion} 不一致`,
66
+ relatedModuleRefs: [],
67
+ nextCommand: "platform start",
68
+ },
69
+ };
70
+ return { runtimeStatus: "RUNNING" };
71
+ }
72
+ async function probeRunningRuntime(context) {
57
73
  const own = await readOwnFacts(context);
58
74
  if (!own)
59
- return false;
75
+ return { running: false };
60
76
  try {
61
- return (await fetch(`${own.endpoint}/health`, {
77
+ const response = await fetch(`${own.endpoint}/ready`, {
62
78
  signal: AbortSignal.timeout(2_000),
63
- })).ok;
79
+ });
80
+ let body;
81
+ try {
82
+ body = await response.json();
83
+ }
84
+ catch {
85
+ body = undefined;
86
+ }
87
+ const observedModuleVersion = typeof body === "object" &&
88
+ body !== null &&
89
+ !Array.isArray(body) &&
90
+ typeof Reflect.get(body, "moduleVersion") === "string"
91
+ ? String(Reflect.get(body, "moduleVersion"))
92
+ : undefined;
93
+ return {
94
+ running: true,
95
+ ...(observedModuleVersion ? { observedModuleVersion } : {}),
96
+ };
64
97
  }
65
98
  catch {
66
- return false;
99
+ return { running: false };
67
100
  }
68
101
  }
102
+ async function running(context) {
103
+ return (await probeRunningRuntime(context)).running;
104
+ }
69
105
  async function compose(context) {
70
106
  const own = await ownFacts(context);
71
107
  const browser = await readModuleSharedFacts(context, "execution-browser-extension");
@@ -96,6 +132,7 @@ async function compose(context) {
96
132
  config: parseExecutionRuntimeProcessConfig({
97
133
  host: url.hostname,
98
134
  port: Number(url.port),
135
+ moduleVersion: descriptor.moduleVersion,
99
136
  databasePath: own.databasePath,
100
137
  projectRoot: own.projectRoot,
101
138
  artifactRoot: own.artifactRoot,
@@ -131,27 +168,35 @@ export const behaviorAdapter = {
131
168
  },
132
169
  status: async (context) => {
133
170
  const startup = await startupDependencies(context);
171
+ const probe = await probeRunningRuntime(context);
172
+ const runtime = classifyExecutionRuntimeLiveProbe({
173
+ running: probe.running,
174
+ ...(probe.observedModuleVersion
175
+ ? { observedModuleVersion: probe.observedModuleVersion }
176
+ : {}),
177
+ expectedModuleVersion: descriptor.moduleVersion,
178
+ });
179
+ const issues = [
180
+ ...(runtime.issue ? [runtime.issue] : []),
181
+ ...(!startup
182
+ ? [
183
+ {
184
+ scope: "RUNTIME",
185
+ code: "UPSTREAM_NOT_READY",
186
+ message: "等待 execution-browser-extension 发布 Browser Executor client 配置",
187
+ relatedModuleRefs: ["execution-browser-extension"],
188
+ nextCommand: "platform setup",
189
+ },
190
+ ]
191
+ : []),
192
+ ];
134
193
  return {
135
194
  result: {
136
195
  ...base,
137
196
  data: {
138
197
  setupStatus: "READY",
139
- runtimeStatus: (await running(context))
140
- ? "RUNNING"
141
- : "STOPPED",
142
- ...(!startup
143
- ? {
144
- issues: [
145
- {
146
- scope: "RUNTIME",
147
- code: "UPSTREAM_NOT_READY",
148
- message: "等待 execution-browser-extension 发布 Browser Executor client 配置",
149
- relatedModuleRefs: ["execution-browser-extension"],
150
- nextCommand: "platform setup",
151
- },
152
- ],
153
- }
154
- : {}),
198
+ runtimeStatus: runtime.runtimeStatus,
199
+ ...(issues.length > 0 ? { issues } : {}),
155
200
  },
156
201
  },
157
202
  observedEffects: [],
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "execution-runtime";
5
5
  readonly packageName: "@tomflow/proflow-execution-runtime";
6
- readonly moduleVersion: "0.1.21";
6
+ readonly moduleVersion: "0.1.23";
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: "execution-runtime",
5
5
  packageName: "@tomflow/proflow-execution-runtime",
6
- moduleVersion: "0.1.21",
6
+ moduleVersion: "0.1.23",
7
7
  kind: "service",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
package/dist/src/index.js CHANGED
@@ -88,6 +88,31 @@ function protectedValue(value, key = "") {
88
88
  protectedValue(item, childKey),
89
89
  ]));
90
90
  }
91
+ function stableMonitorLocator(value, kind) {
92
+ if (typeof value !== "string")
93
+ return value;
94
+ let parsed;
95
+ try {
96
+ parsed = new URL(value);
97
+ }
98
+ catch {
99
+ return value;
100
+ }
101
+ if (parsed.protocol !== "https:" ||
102
+ parsed.hostname !== "chatgpt.com" ||
103
+ parsed.search ||
104
+ parsed.hash)
105
+ return value;
106
+ const match = kind === "conversation"
107
+ ? /^\/g\/(g-p-[a-f0-9]{32})(?:-[a-z0-9-]+)?\/c\/([^/?#]+)\/?$/i.exec(parsed.pathname)
108
+ : /^\/g\/(g-p-[a-f0-9]{32})(?:-[a-z0-9-]+)?(?:\/project)?\/?$/i.exec(parsed.pathname);
109
+ if (!match)
110
+ return value;
111
+ const projectRef = match[1].toLowerCase();
112
+ return kind === "conversation"
113
+ ? `${parsed.origin}/g/${projectRef}/c/${match[2]}`
114
+ : `${parsed.origin}/g/${projectRef}`;
115
+ }
91
116
  function stableEffectInput(request) {
92
117
  if (request.capability !== "monitor.chat.submit" && request.capability !== "monitor.chat.create")
93
118
  return request.input;
@@ -95,6 +120,13 @@ function stableEffectInput(request) {
95
120
  // Legacy revision fences are admission facts, not physical-effect identity.
96
121
  delete effect.expectedRunVersion;
97
122
  delete effect.configRevision;
123
+ // ChatGPT may add/remove a human-readable Project slug while preserving the
124
+ // stable g-p-* project identity. That presentation change must not fork a
125
+ // durable Monitor effect or block same-effect reconciliation.
126
+ if (request.capability === "monitor.chat.submit")
127
+ effect.conversationLocator = stableMonitorLocator(effect.conversationLocator, "conversation");
128
+ else
129
+ effect.projectLocator = stableMonitorLocator(effect.projectLocator, "project");
98
130
  return effect;
99
131
  }
100
132
  export function executionInputFingerprint(input) {
@@ -5,6 +5,7 @@ export type ExecutionRuntimeProcessConfig = {
5
5
  artifactRoot: string;
6
6
  host: string;
7
7
  port: number;
8
+ moduleVersion?: string;
8
9
  exactNetworkTargets: string[];
9
10
  browserExecutorConfigPath?: string;
10
11
  transportCredentialFile?: string;
@@ -28,6 +29,7 @@ export type ExecutionRuntimeProcessStatus = {
28
29
  readiness: "READY" | "NOT_READY";
29
30
  accepting: boolean;
30
31
  inFlight: number;
32
+ moduleVersion: string | null;
31
33
  databasePath: string;
32
34
  localExecutor: "READY" | "UNAVAILABLE";
33
35
  browserExecutor: "READY" | "UNAVAILABLE";
@@ -42,6 +42,9 @@ export function parseExecutionRuntimeProcessConfig(value) {
42
42
  const port = input.port === undefined ? 0 : Number(input.port);
43
43
  if (!Number.isInteger(port) || port < 0 || port > 65_535)
44
44
  throw new TypeError("port must be an integer from 0 through 65535");
45
+ const moduleVersion = input.moduleVersion === undefined
46
+ ? undefined
47
+ : string(input.moduleVersion, "moduleVersion");
45
48
  const exactNetworkTargets = input.exactNetworkTargets ?? [];
46
49
  const browserExecutorConfigPath = input.browserExecutorConfigPath === undefined
47
50
  ? undefined
@@ -95,6 +98,7 @@ export function parseExecutionRuntimeProcessConfig(value) {
95
98
  artifactRoot,
96
99
  host: input.host === undefined ? "127.0.0.1" : string(input.host, "host"),
97
100
  port,
101
+ ...(moduleVersion ? { moduleVersion } : {}),
98
102
  exactNetworkTargets: [...exactNetworkTargets],
99
103
  ...(browserExecutorConfigPath ? { browserExecutorConfigPath } : {}),
100
104
  ...(transportCredentialFile ? { transportCredentialFile } : {}),
@@ -198,6 +202,7 @@ export async function createExecutionRuntimeProcess(input) {
198
202
  : "NOT_READY",
199
203
  accepting,
200
204
  inFlight: active.size,
205
+ moduleVersion: input.config.moduleVersion ?? null,
201
206
  databasePath: input.config.databasePath,
202
207
  localExecutor: runtime ? "READY" : "UNAVAILABLE",
203
208
  browserExecutor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-execution-runtime",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -24,10 +24,10 @@
24
24
  "SETUP.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@tomflow/proflow-execution-browser-extension": "^0.1.76",
28
27
  "@tomflow/proflow-execution-contracts": "^0.1.12",
29
- "@tomflow/proflow-execution-local": "^0.1.16",
28
+ "@tomflow/proflow-execution-browser-extension": "^0.1.78",
30
29
  "@tomflow/proflow-model-contracts": "^0.1.10",
30
+ "@tomflow/proflow-execution-local": "^0.1.16",
31
31
  "@tomflow/proflow-module-contract": "^0.1.13"
32
32
  },
33
33
  "devDependencies": {
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "execution-runtime",
5
5
  "packageName": "@tomflow/proflow-execution-runtime",
6
- "moduleVersion": "0.1.21",
6
+ "moduleVersion": "0.1.23",
7
7
  "kind": "service",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",