@tomflow/proflow-agent-gateway 0.1.15 → 0.1.17
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 +12 -0
- package/dist/deployment/adapter.d.ts +10 -10
- package/dist/deployment/adapter.js +2 -2
- package/dist/deployment/descriptor.d.ts +1 -4
- package/dist/deployment/descriptor.js +1 -5
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +5 -1
- package/dist/src/process.js +105 -14
- package/package.json +7 -8
- package/proflow.module.json +1 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @tomflow/proflow-agent-gateway
|
|
2
2
|
|
|
3
|
+
## 0.1.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Close the Real-3 runtime reconciliation, health, browser effect-result boundary, observer pagination, and standalone execution-runtime configuration gaps for final human acceptance.
|
|
8
|
+
|
|
9
|
+
## 0.1.16
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Release the verified Real-3 B1 task recovery, exact execution identity, durable observer resume, bounded gateway error, and matching Agent Action contract fixes.
|
|
14
|
+
|
|
3
15
|
## 0.1.15
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -6,7 +6,7 @@ export declare const behaviorAdapter: {
|
|
|
6
6
|
ok: true;
|
|
7
7
|
status: "SUCCEEDED";
|
|
8
8
|
moduleRef: "agent-gateway";
|
|
9
|
-
moduleVersion: "0.1.
|
|
9
|
+
moduleVersion: "0.1.17";
|
|
10
10
|
data: {
|
|
11
11
|
localBaseUrl: string;
|
|
12
12
|
publicBaseUrl?: string;
|
|
@@ -20,7 +20,7 @@ export declare const behaviorAdapter: {
|
|
|
20
20
|
readonly ok: true;
|
|
21
21
|
readonly status: "SUCCEEDED";
|
|
22
22
|
readonly moduleRef: "agent-gateway";
|
|
23
|
-
readonly moduleVersion: "0.1.
|
|
23
|
+
readonly moduleVersion: "0.1.17";
|
|
24
24
|
};
|
|
25
25
|
observedEffects: string[];
|
|
26
26
|
}>;
|
|
@@ -30,7 +30,7 @@ export declare const behaviorAdapter: {
|
|
|
30
30
|
ok: true;
|
|
31
31
|
status: "SUCCEEDED";
|
|
32
32
|
moduleRef: "agent-gateway";
|
|
33
|
-
moduleVersion: "0.1.
|
|
33
|
+
moduleVersion: "0.1.17";
|
|
34
34
|
data: {
|
|
35
35
|
setupStatus: "BLOCKED" | "READY";
|
|
36
36
|
runtimeStatus: "RUNNING" | "STOPPED";
|
|
@@ -51,7 +51,7 @@ export declare const behaviorAdapter: {
|
|
|
51
51
|
ok: true;
|
|
52
52
|
status: "SUCCEEDED";
|
|
53
53
|
moduleRef: "agent-gateway";
|
|
54
|
-
moduleVersion: "0.1.
|
|
54
|
+
moduleVersion: "0.1.17";
|
|
55
55
|
data: {
|
|
56
56
|
localBaseUrl: string;
|
|
57
57
|
publicBaseUrl?: string;
|
|
@@ -66,7 +66,7 @@ export declare const behaviorAdapter: {
|
|
|
66
66
|
ok: true;
|
|
67
67
|
status: "SUCCEEDED";
|
|
68
68
|
moduleRef: "agent-gateway";
|
|
69
|
-
moduleVersion: "0.1.
|
|
69
|
+
moduleVersion: "0.1.17";
|
|
70
70
|
data: {
|
|
71
71
|
docs: string;
|
|
72
72
|
};
|
|
@@ -79,7 +79,7 @@ export declare const behaviorAdapter: {
|
|
|
79
79
|
ok: true;
|
|
80
80
|
status: "SUCCEEDED";
|
|
81
81
|
moduleRef: "agent-gateway";
|
|
82
|
-
moduleVersion: "0.1.
|
|
82
|
+
moduleVersion: "0.1.17";
|
|
83
83
|
data: {
|
|
84
84
|
host: string;
|
|
85
85
|
port: number;
|
|
@@ -90,7 +90,7 @@ export declare const behaviorAdapter: {
|
|
|
90
90
|
result: {
|
|
91
91
|
contract: "deployment.result.v1";
|
|
92
92
|
moduleRef: "agent-gateway";
|
|
93
|
-
moduleVersion: "0.1.
|
|
93
|
+
moduleVersion: "0.1.17";
|
|
94
94
|
ok: false;
|
|
95
95
|
status: "FAILED";
|
|
96
96
|
error: {
|
|
@@ -107,7 +107,7 @@ export declare const behaviorAdapter: {
|
|
|
107
107
|
readonly ok: true;
|
|
108
108
|
readonly status: "SUCCEEDED";
|
|
109
109
|
readonly moduleRef: "agent-gateway";
|
|
110
|
-
readonly moduleVersion: "0.1.
|
|
110
|
+
readonly moduleVersion: "0.1.17";
|
|
111
111
|
};
|
|
112
112
|
observedEffects: string[];
|
|
113
113
|
} | {
|
|
@@ -116,11 +116,11 @@ export declare const behaviorAdapter: {
|
|
|
116
116
|
readonly ok: true;
|
|
117
117
|
readonly status: "SUCCEEDED";
|
|
118
118
|
readonly moduleRef: "agent-gateway";
|
|
119
|
-
readonly moduleVersion: "0.1.
|
|
119
|
+
readonly moduleVersion: "0.1.17";
|
|
120
120
|
} | {
|
|
121
121
|
contract: "deployment.result.v1";
|
|
122
122
|
moduleRef: "agent-gateway";
|
|
123
|
-
moduleVersion: "0.1.
|
|
123
|
+
moduleVersion: "0.1.17";
|
|
124
124
|
ok: false;
|
|
125
125
|
status: "FAILED";
|
|
126
126
|
error: {
|
|
@@ -56,8 +56,8 @@ async function running(context) {
|
|
|
56
56
|
if (!own)
|
|
57
57
|
return false;
|
|
58
58
|
try {
|
|
59
|
-
return (await fetch(`${own.localBaseUrl}/
|
|
60
|
-
signal: AbortSignal.timeout(
|
|
59
|
+
return (await fetch(`${own.localBaseUrl}/health`, {
|
|
60
|
+
signal: AbortSignal.timeout(2_000),
|
|
61
61
|
})).ok;
|
|
62
62
|
}
|
|
63
63
|
catch {
|
|
@@ -3,7 +3,7 @@ export declare const descriptor: {
|
|
|
3
3
|
readonly contractVersion: "1.0.0";
|
|
4
4
|
readonly moduleRef: "agent-gateway";
|
|
5
5
|
readonly packageName: "@tomflow/proflow-agent-gateway";
|
|
6
|
-
readonly moduleVersion: "0.1.
|
|
6
|
+
readonly moduleVersion: "0.1.17";
|
|
7
7
|
readonly kind: "service";
|
|
8
8
|
readonly templateVersion: "1.0.0";
|
|
9
9
|
readonly platformCompatibility: ">=1.0.0 <2.0.0";
|
|
@@ -21,9 +21,6 @@ export declare const descriptor: {
|
|
|
21
21
|
}, {
|
|
22
22
|
readonly contractRef: "task-orchestration";
|
|
23
23
|
readonly versionRange: ">=1.0.0 <2.0.0";
|
|
24
|
-
}, {
|
|
25
|
-
readonly contractRef: "execution";
|
|
26
|
-
readonly versionRange: ">=1.0.0 <2.0.0";
|
|
27
24
|
}, {
|
|
28
25
|
readonly contractRef: "platform-host";
|
|
29
26
|
readonly versionRange: ">=1.0.0 <2.0.0";
|
|
@@ -3,7 +3,7 @@ export const descriptor = {
|
|
|
3
3
|
contractVersion: "1.0.0",
|
|
4
4
|
moduleRef: "agent-gateway",
|
|
5
5
|
packageName: "@tomflow/proflow-agent-gateway",
|
|
6
|
-
moduleVersion: "0.1.
|
|
6
|
+
moduleVersion: "0.1.17",
|
|
7
7
|
kind: "service",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
|
@@ -26,10 +26,6 @@ export const descriptor = {
|
|
|
26
26
|
contractRef: "task-orchestration",
|
|
27
27
|
versionRange: ">=1.0.0 <2.0.0",
|
|
28
28
|
},
|
|
29
|
-
{
|
|
30
|
-
contractRef: "execution",
|
|
31
|
-
versionRange: ">=1.0.0 <2.0.0",
|
|
32
|
-
},
|
|
33
29
|
{
|
|
34
30
|
contractRef: "platform-host",
|
|
35
31
|
versionRange: ">=1.0.0 <2.0.0",
|
package/dist/src/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type GatewayOwnerPorts = {
|
|
|
9
9
|
authenticateBearer(credential: string): Promise<string>;
|
|
10
10
|
route(operationId: string, authenticatedRoleRef: string, input: unknown, context?: {
|
|
11
11
|
signal: AbortSignal;
|
|
12
|
+
deadlineAt: string;
|
|
12
13
|
fileMaterializationInputs?: readonly ExternalFileMaterializationInput[];
|
|
13
14
|
}): Promise<unknown>;
|
|
14
15
|
lookupResult?(operationId: string, authenticatedRoleRef: string, input: unknown): Promise<unknown>;
|
package/dist/src/index.js
CHANGED
|
@@ -331,11 +331,15 @@ export async function createAgentGateway(options) {
|
|
|
331
331
|
canonicalBody.content.length > 0)
|
|
332
332
|
throw new AgentGatewayError("OPENAI_FILE_INPUT_CONFLICT");
|
|
333
333
|
}
|
|
334
|
-
const
|
|
334
|
+
const actionTimeoutMs = Math.min(40_000, options.actionTimeoutMs ?? 40_000);
|
|
335
|
+
const propagationReserveMs = Math.min(1_500, Math.max(100, Math.floor(actionTimeoutMs / 10)));
|
|
336
|
+
const deadlineAt = new Date(now() + Math.max(1, actionTimeoutMs - propagationReserveMs)).toISOString();
|
|
337
|
+
const actionSignal = AbortSignal.timeout(actionTimeoutMs);
|
|
335
338
|
const operation = action.uncertain && options.owners.lookupResult
|
|
336
339
|
? options.owners.lookupResult(action.operationId, authenticatedRoleRef, canonicalBody)
|
|
337
340
|
: options.owners.route(action.operationId, authenticatedRoleRef, canonicalBody, {
|
|
338
341
|
signal: actionSignal,
|
|
342
|
+
deadlineAt,
|
|
339
343
|
...(fileMaterializationInputs === undefined
|
|
340
344
|
? {}
|
|
341
345
|
: { fileMaterializationInputs }),
|
package/dist/src/process.js
CHANGED
|
@@ -1,7 +1,77 @@
|
|
|
1
1
|
import { createHash, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
import { createAgentGateway } from "./index.js";
|
|
4
|
+
import { AgentGatewayError, createAgentGateway } from "./index.js";
|
|
5
|
+
const MAX_DOWNSTREAM_ERROR_BYTES = 8_192;
|
|
6
|
+
const safeDownstreamErrorCodes = new Set([
|
|
7
|
+
"INVALID_REQUEST",
|
|
8
|
+
"ROLE_OPERATION_DENIED",
|
|
9
|
+
"TASK_ROLE_BINDING_REQUIRED",
|
|
10
|
+
"TASK_WORKER_BINDING_MISMATCH",
|
|
11
|
+
"ROLE_NOT_TASK_PARTICIPANT",
|
|
12
|
+
"WORKER_IDENTITY_INVALID",
|
|
13
|
+
"WORKER_MISMATCH",
|
|
14
|
+
"TASK_TERMINAL",
|
|
15
|
+
"EXECUTION_TASK_NOT_ACTIVE",
|
|
16
|
+
"EXECUTION_NODE_NOT_CURRENT",
|
|
17
|
+
"EXECUTION_NODE_NOT_RUNNING",
|
|
18
|
+
"EXECUTION_GENERATION_MISMATCH",
|
|
19
|
+
"EXECUTION_ROLE_SCOPE_MISMATCH",
|
|
20
|
+
"EXECUTION_WORKER_SCOPE_MISMATCH",
|
|
21
|
+
"ROLE_TOOL_OPERATION_DENIED",
|
|
22
|
+
"DIRECT_TOOL_INPUT_INVALID",
|
|
23
|
+
"DIRECT_TOOL_DEADLINE_REQUIRED",
|
|
24
|
+
"LOCAL_TOOL_BRIDGE_UNAVAILABLE",
|
|
25
|
+
"LOCAL_TOOL_AUTH_INVALID",
|
|
26
|
+
"LOCAL_TOOL_INPUT_INVALID",
|
|
27
|
+
"LOCAL_TOOL_OFFLINE",
|
|
28
|
+
"LOCAL_TOOL_COMMAND_TIMEOUT",
|
|
29
|
+
"LOCAL_TOOL_RESULT_UNKNOWN",
|
|
30
|
+
"LOCAL_TOOL_PROVIDER_UNAVAILABLE",
|
|
31
|
+
"LOCAL_TOOL_SCOPE_DENIED",
|
|
32
|
+
"LOCAL_TOOL_COMMAND_FAILED",
|
|
33
|
+
]);
|
|
34
|
+
async function boundedDownstreamErrorCode(response) {
|
|
35
|
+
if (!response.body)
|
|
36
|
+
return null;
|
|
37
|
+
const reader = response.body.getReader();
|
|
38
|
+
const chunks = [];
|
|
39
|
+
let bytes = 0;
|
|
40
|
+
try {
|
|
41
|
+
while (true) {
|
|
42
|
+
const next = await reader.read();
|
|
43
|
+
if (next.done)
|
|
44
|
+
break;
|
|
45
|
+
bytes += next.value.byteLength;
|
|
46
|
+
if (bytes > MAX_DOWNSTREAM_ERROR_BYTES) {
|
|
47
|
+
await reader.cancel();
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
chunks.push(next.value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const merged = new Uint8Array(bytes);
|
|
57
|
+
let offset = 0;
|
|
58
|
+
for (const chunk of chunks) {
|
|
59
|
+
merged.set(chunk, offset);
|
|
60
|
+
offset += chunk.byteLength;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const value = JSON.parse(new TextDecoder().decode(merged));
|
|
64
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
65
|
+
return null;
|
|
66
|
+
const code = Reflect.get(value, "error");
|
|
67
|
+
return typeof code === "string" && safeDownstreamErrorCodes.has(code)
|
|
68
|
+
? code
|
|
69
|
+
: null;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
5
75
|
function record(value, name) {
|
|
6
76
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
7
77
|
throw new TypeError(`${name} must be an object`);
|
|
@@ -92,21 +162,41 @@ export async function createAgentGatewayProcess(input) {
|
|
|
92
162
|
const downstreamCredential = input.config.downstreamCredentialFile
|
|
93
163
|
? await readDownstreamCredential(input.config.downstreamCredentialFile)
|
|
94
164
|
: undefined;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
165
|
+
let response;
|
|
166
|
+
try {
|
|
167
|
+
response = await fetchImplementation(`${input.config.downstreamBaseUrl}${path}`, {
|
|
168
|
+
method: body === undefined ? "GET" : "POST",
|
|
169
|
+
headers: {
|
|
170
|
+
...(body === undefined
|
|
171
|
+
? {}
|
|
172
|
+
: { "content-type": "application/json" }),
|
|
173
|
+
...(downstreamCredential
|
|
174
|
+
? { authorization: `Bearer ${downstreamCredential}` }
|
|
175
|
+
: {}),
|
|
176
|
+
},
|
|
177
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
178
|
+
...(signal ? { signal } : {}),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
throw Object.assign(new AgentGatewayError(signal?.aborted
|
|
183
|
+
? "OPENAI_ACTION_TIMEOUT"
|
|
184
|
+
: "OWNER_SERVICE_UNAVAILABLE"), { httpStatus: signal?.aborted ? 504 : 503 });
|
|
185
|
+
}
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
const downstreamCode = await boundedDownstreamErrorCode(response);
|
|
188
|
+
const code = response.status >= 500 || response.status === 401
|
|
189
|
+
? "OWNER_SERVICE_UNAVAILABLE"
|
|
190
|
+
: (downstreamCode ??
|
|
191
|
+
(response.status === 400
|
|
192
|
+
? "INVALID_REQUEST"
|
|
193
|
+
: response.status === 403
|
|
194
|
+
? "ROLE_OPERATION_DENIED"
|
|
195
|
+
: "DOWNSTREAM_UNAVAILABLE"));
|
|
196
|
+
throw Object.assign(new AgentGatewayError(code), {
|
|
108
197
|
httpStatus: response.status,
|
|
109
198
|
});
|
|
199
|
+
}
|
|
110
200
|
return response.json();
|
|
111
201
|
};
|
|
112
202
|
const gateway = await createAgentGateway({
|
|
@@ -125,6 +215,7 @@ export async function createAgentGatewayProcess(input) {
|
|
|
125
215
|
return downstream(`/actions/${encodeURIComponent(operationId)}`, {
|
|
126
216
|
authenticatedRoleRef,
|
|
127
217
|
input: value,
|
|
218
|
+
deadlineAt: context?.deadlineAt,
|
|
128
219
|
...(context?.fileMaterializationInputs === undefined
|
|
129
220
|
? {}
|
|
130
221
|
: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomflow/proflow-agent-gateway",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -28,15 +28,14 @@
|
|
|
28
28
|
"@tomflow/proflow-module-contract": "^0.1.13"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@tomflow/proflow-
|
|
31
|
+
"@tomflow/proflow-execution-browser-extension": "^0.1.51",
|
|
32
32
|
"@tomflow/proflow-deployment-conformance": "^0.1.13",
|
|
33
|
-
"@tomflow/proflow-execution-
|
|
34
|
-
"@tomflow/proflow-
|
|
35
|
-
"@tomflow/proflow-
|
|
33
|
+
"@tomflow/proflow-execution-runtime": "^0.1.19",
|
|
34
|
+
"@tomflow/proflow-agent-runtime": "^0.1.14",
|
|
35
|
+
"@tomflow/proflow-platform-host": "^0.1.23",
|
|
36
|
+
"@tomflow/proflow-task-orchestration": "^0.1.11",
|
|
36
37
|
"@tomflow/proflow-task-migration-runner": "^0.1.11",
|
|
37
|
-
"@tomflow/proflow-task-
|
|
38
|
-
"@tomflow/proflow-task-store-sqlite": "^0.1.11",
|
|
39
|
-
"@tomflow/proflow-execution-local": "^0.1.13"
|
|
38
|
+
"@tomflow/proflow-task-store-sqlite": "^0.1.12"
|
|
40
39
|
},
|
|
41
40
|
"description": "The sole Custom GPT Actions HTTP ingress and OpenAI transport anti-corruption layer.",
|
|
42
41
|
"keywords": [
|
package/proflow.module.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"contractVersion": "1.0.0",
|
|
4
4
|
"moduleRef": "agent-gateway",
|
|
5
5
|
"packageName": "@tomflow/proflow-agent-gateway",
|
|
6
|
-
"moduleVersion": "0.1.
|
|
6
|
+
"moduleVersion": "0.1.17",
|
|
7
7
|
"kind": "service",
|
|
8
8
|
"templateVersion": "1.0.0",
|
|
9
9
|
"platformCompatibility": ">=1.0.0 <2.0.0",
|
|
@@ -26,10 +26,6 @@
|
|
|
26
26
|
"contractRef": "task-orchestration",
|
|
27
27
|
"versionRange": ">=1.0.0 <2.0.0"
|
|
28
28
|
},
|
|
29
|
-
{
|
|
30
|
-
"contractRef": "execution",
|
|
31
|
-
"versionRange": ">=1.0.0 <2.0.0"
|
|
32
|
-
},
|
|
33
29
|
{
|
|
34
30
|
"contractRef": "platform-host",
|
|
35
31
|
"versionRange": ">=1.0.0 <2.0.0"
|