@tomflow/proflow-agent-gateway 0.1.17 → 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 +14 -0
- package/dist/deployment/adapter.d.ts +10 -10
- package/dist/deployment/adapter.js +34 -1
- package/dist/deployment/descriptor.d.ts +1 -1
- package/dist/deployment/descriptor.js +1 -1
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +12 -0
- package/dist/src/process.d.ts +1 -0
- package/dist/src/process.js +151 -29
- package/package.json +7 -7
- package/proflow.module.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @tomflow/proflow-agent-gateway
|
|
2
2
|
|
|
3
|
+
## 0.1.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Preserve allowlisted downstream tool error codes across Gateway HTTP translation while keeping unknown failures opaque, and stop generic Gateway logs from fabricating side-effect state.
|
|
8
|
+
|
|
9
|
+
- Fail closed when the public Gateway role credential store becomes group/world-readable on POSIX systems.
|
|
10
|
+
|
|
11
|
+
## 0.1.18
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Aggregate Browser, Permission, Host-application, Provisioning, Direct Tool, and Gateway observability at stable runtime boundaries, preserving owner truth while enabling one operation-chain diagnosis path without logging sensitive payloads.
|
|
16
|
+
|
|
3
17
|
## 0.1.17
|
|
4
18
|
|
|
5
19
|
### 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.19";
|
|
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.19";
|
|
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.19";
|
|
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.19";
|
|
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.19";
|
|
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.19";
|
|
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.19";
|
|
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.19";
|
|
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.19";
|
|
120
120
|
} | {
|
|
121
121
|
contract: "deployment.result.v1";
|
|
122
122
|
moduleRef: "agent-gateway";
|
|
123
|
-
moduleVersion: "0.1.
|
|
123
|
+
moduleVersion: "0.1.19";
|
|
124
124
|
ok: false;
|
|
125
125
|
status: "FAILED";
|
|
126
126
|
error: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import {
|
|
2
|
+
import { appendFile, mkdir, stat, rename } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
4
|
import { deterministicLoopbackPort, readModuleSharedFacts, writeModuleSharedFacts, } from "@tomflow/proflow-module-contract";
|
|
4
5
|
import { descriptor } from "./descriptor.js";
|
|
5
6
|
const services = new Map();
|
|
@@ -72,6 +73,36 @@ async function compose(context) {
|
|
|
72
73
|
const credentialFile = join(deps.stateRoot, "agent", "secrets", "role-credentials.json");
|
|
73
74
|
if (!existsSync(credentialFile))
|
|
74
75
|
throw new Error("Agent role credential store is not materialized by Platform Host");
|
|
76
|
+
const logPath = join(deps.stateRoot, "logs", "agent-gateway", "events.jsonl");
|
|
77
|
+
let logTail = Promise.resolve();
|
|
78
|
+
let pendingLogs = 0;
|
|
79
|
+
const log = (entry) => {
|
|
80
|
+
if (pendingLogs >= 1000)
|
|
81
|
+
return;
|
|
82
|
+
pendingLogs++;
|
|
83
|
+
logTail = logTail
|
|
84
|
+
.catch(() => undefined)
|
|
85
|
+
.then(async () => {
|
|
86
|
+
await mkdir(dirname(logPath), { recursive: true, mode: 0o700 });
|
|
87
|
+
const target = entry.component === "agent-gateway-process"
|
|
88
|
+
? logPath.replace("events.jsonl", "lifecycle.jsonl")
|
|
89
|
+
: logPath;
|
|
90
|
+
const info = await stat(target).catch(() => null);
|
|
91
|
+
if (info &&
|
|
92
|
+
(info.size >= 5 * 1024 * 1024 ||
|
|
93
|
+
Date.now() - info.mtimeMs > 7 * 86400_000))
|
|
94
|
+
await rename(target, `${target}.1`);
|
|
95
|
+
await appendFile(target, `${JSON.stringify(entry)}\n`, {
|
|
96
|
+
encoding: "utf8",
|
|
97
|
+
mode: 0o600,
|
|
98
|
+
});
|
|
99
|
+
})
|
|
100
|
+
.catch(() => undefined)
|
|
101
|
+
.finally(() => {
|
|
102
|
+
pendingLogs--;
|
|
103
|
+
});
|
|
104
|
+
void logTail;
|
|
105
|
+
};
|
|
75
106
|
const { createAgentGatewayProcess, parseAgentGatewayProcessConfig } = await import("../src/process.js");
|
|
76
107
|
const listener = new URL(own.localBaseUrl);
|
|
77
108
|
return createAgentGatewayProcess({
|
|
@@ -83,6 +114,8 @@ async function compose(context) {
|
|
|
83
114
|
credentialFile,
|
|
84
115
|
downstreamCredentialFile: deps.downstreamCredentialFile,
|
|
85
116
|
}),
|
|
117
|
+
log,
|
|
118
|
+
operationLog: log,
|
|
86
119
|
});
|
|
87
120
|
}
|
|
88
121
|
const failed = (code, message) => ({
|
|
@@ -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.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: "agent-gateway",
|
|
5
5
|
packageName: "@tomflow/proflow-agent-gateway",
|
|
6
|
-
moduleVersion: "0.1.
|
|
6
|
+
moduleVersion: "0.1.19",
|
|
7
7
|
kind: "service",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
package/dist/src/index.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export type GatewayOptions = {
|
|
|
22
22
|
port?: number;
|
|
23
23
|
now?: () => number;
|
|
24
24
|
actionTimeoutMs?: number;
|
|
25
|
+
onIngressFailure?: (entry: {
|
|
26
|
+
status: "FAILED";
|
|
27
|
+
httpStatus: number;
|
|
28
|
+
sideEffectState: "NOT_APPLIED";
|
|
29
|
+
}) => void;
|
|
25
30
|
};
|
|
26
31
|
export declare class AgentGatewayError extends Error {
|
|
27
32
|
readonly code: string;
|
package/dist/src/index.js
CHANGED
|
@@ -225,6 +225,7 @@ export async function createAgentGateway(options) {
|
|
|
225
225
|
};
|
|
226
226
|
const handler = async (request, response) => {
|
|
227
227
|
inFlight += 1;
|
|
228
|
+
let ownerEntered = false;
|
|
228
229
|
try {
|
|
229
230
|
const url = new URL(request.url ?? "/", `http://${host}`);
|
|
230
231
|
if (request.method === "GET" && url.pathname === "/health") {
|
|
@@ -335,6 +336,7 @@ export async function createAgentGateway(options) {
|
|
|
335
336
|
const propagationReserveMs = Math.min(1_500, Math.max(100, Math.floor(actionTimeoutMs / 10)));
|
|
336
337
|
const deadlineAt = new Date(now() + Math.max(1, actionTimeoutMs - propagationReserveMs)).toISOString();
|
|
337
338
|
const actionSignal = AbortSignal.timeout(actionTimeoutMs);
|
|
339
|
+
ownerEntered = true;
|
|
338
340
|
const operation = action.uncertain && options.owners.lookupResult
|
|
339
341
|
? options.owners.lookupResult(action.operationId, authenticatedRoleRef, canonicalBody)
|
|
340
342
|
: options.owners.route(action.operationId, authenticatedRoleRef, canonicalBody, {
|
|
@@ -383,6 +385,16 @@ export async function createAgentGateway(options) {
|
|
|
383
385
|
}));
|
|
384
386
|
}
|
|
385
387
|
finally {
|
|
388
|
+
if (!ownerEntered && response.statusCode >= 400) {
|
|
389
|
+
try {
|
|
390
|
+
options.onIngressFailure?.({
|
|
391
|
+
status: "FAILED",
|
|
392
|
+
httpStatus: response.statusCode,
|
|
393
|
+
sideEffectState: "NOT_APPLIED",
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
catch { }
|
|
397
|
+
}
|
|
386
398
|
inFlight -= 1;
|
|
387
399
|
}
|
|
388
400
|
};
|
package/dist/src/process.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare function createAgentGatewayProcess(input: {
|
|
|
12
12
|
config: AgentGatewayProcessConfig;
|
|
13
13
|
fetch?: typeof globalThis.fetch;
|
|
14
14
|
log?: (entry: Record<string, unknown>) => void;
|
|
15
|
+
operationLog?: (entry: Record<string, unknown>) => void;
|
|
15
16
|
}): Promise<Readonly<{
|
|
16
17
|
readiness: () => Promise<{
|
|
17
18
|
status: "NOT_READY" | "READY";
|
package/dist/src/process.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash, timingSafeEqual } from "node:crypto";
|
|
1
|
+
import { createHash, timingSafeEqual, randomUUID } from "node:crypto";
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { AgentGatewayError, createAgentGateway } from "./index.js";
|
|
@@ -31,6 +31,7 @@ const safeDownstreamErrorCodes = new Set([
|
|
|
31
31
|
"LOCAL_TOOL_SCOPE_DENIED",
|
|
32
32
|
"LOCAL_TOOL_COMMAND_FAILED",
|
|
33
33
|
]);
|
|
34
|
+
const directToolOperationIds = new Set(["localDev", "repomix", "codeGraph"]);
|
|
34
35
|
async function boundedDownstreamErrorCode(response) {
|
|
35
36
|
if (!response.body)
|
|
36
37
|
return null;
|
|
@@ -82,6 +83,25 @@ function text(value, name) {
|
|
|
82
83
|
throw new TypeError(`${name} must be a non-empty string`);
|
|
83
84
|
return value;
|
|
84
85
|
}
|
|
86
|
+
function logErrorCode(error) {
|
|
87
|
+
const value = error instanceof AgentGatewayError
|
|
88
|
+
? error.code
|
|
89
|
+
: error &&
|
|
90
|
+
typeof error === "object" &&
|
|
91
|
+
typeof Reflect.get(error, "message") === "string"
|
|
92
|
+
? String(Reflect.get(error, "message"))
|
|
93
|
+
: "GATEWAY_FAILURE";
|
|
94
|
+
return /^[A-Z][A-Z0-9_.:-]{0,159}$/.test(value) ? value : "GATEWAY_FAILURE";
|
|
95
|
+
}
|
|
96
|
+
function optionalToolOperation(value) {
|
|
97
|
+
if (typeof value !== "object" ||
|
|
98
|
+
value === null ||
|
|
99
|
+
Array.isArray(value) ||
|
|
100
|
+
typeof Reflect.get(value, "operation") !== "string")
|
|
101
|
+
return undefined;
|
|
102
|
+
const operation = String(Reflect.get(value, "operation"));
|
|
103
|
+
return /^[A-Za-z0-9_.:-]{1,160}$/.test(operation) ? operation : undefined;
|
|
104
|
+
}
|
|
85
105
|
export function parseAgentGatewayProcessConfig(value) {
|
|
86
106
|
const input = record(value, "agent-gateway config");
|
|
87
107
|
const publicBaseUrl = new URL(text(input.publicBaseUrl, "publicBaseUrl"));
|
|
@@ -128,6 +148,9 @@ function parseCredentialStore(value) {
|
|
|
128
148
|
return credentials;
|
|
129
149
|
}
|
|
130
150
|
async function readCurrentCredentialStore(file) {
|
|
151
|
+
const info = await stat(file);
|
|
152
|
+
if (process.platform !== "win32" && (info.mode & 0o077) !== 0)
|
|
153
|
+
throw new Error("ROLE_CREDENTIAL_STORE_PERMISSIONS_INVALID");
|
|
131
154
|
return parseCredentialStore(JSON.parse(await readFile(file, "utf8")));
|
|
132
155
|
}
|
|
133
156
|
async function readDownstreamCredential(file) {
|
|
@@ -142,11 +165,6 @@ async function readDownstreamCredential(file) {
|
|
|
142
165
|
export async function createAgentGatewayProcess(input) {
|
|
143
166
|
const fetchImplementation = input.fetch ?? globalThis.fetch;
|
|
144
167
|
const credentialFile = input.config.credentialFile;
|
|
145
|
-
// Fail-fast at startup so a malformed configured credential store is rejected
|
|
146
|
-
// before the process advertises readiness. Authentication re-reads the current
|
|
147
|
-
// store on every attempt below, so a rotated key takes effect without a restart
|
|
148
|
-
// and a malformed/half-written store fails closed instead of serving a stale
|
|
149
|
-
// snapshot.
|
|
150
168
|
await readCurrentCredentialStore(credentialFile);
|
|
151
169
|
if (input.config.downstreamCredentialFile)
|
|
152
170
|
await readDownstreamCredential(input.config.downstreamCredentialFile);
|
|
@@ -158,7 +176,7 @@ export async function createAgentGatewayProcess(input) {
|
|
|
158
176
|
return false;
|
|
159
177
|
}
|
|
160
178
|
};
|
|
161
|
-
const downstream = async (path, body, signal) => {
|
|
179
|
+
const downstream = async (path, body, signal, operationRef) => {
|
|
162
180
|
const downstreamCredential = input.config.downstreamCredentialFile
|
|
163
181
|
? await readDownstreamCredential(input.config.downstreamCredentialFile)
|
|
164
182
|
: undefined;
|
|
@@ -167,6 +185,9 @@ export async function createAgentGatewayProcess(input) {
|
|
|
167
185
|
response = await fetchImplementation(`${input.config.downstreamBaseUrl}${path}`, {
|
|
168
186
|
method: body === undefined ? "GET" : "POST",
|
|
169
187
|
headers: {
|
|
188
|
+
...(operationRef
|
|
189
|
+
? { "x-proflow-operation-ref": operationRef }
|
|
190
|
+
: {}),
|
|
170
191
|
...(body === undefined
|
|
171
192
|
? {}
|
|
172
193
|
: { "content-type": "application/json" }),
|
|
@@ -185,21 +206,69 @@ export async function createAgentGatewayProcess(input) {
|
|
|
185
206
|
}
|
|
186
207
|
if (!response.ok) {
|
|
187
208
|
const downstreamCode = await boundedDownstreamErrorCode(response);
|
|
188
|
-
const code = response.status
|
|
209
|
+
const code = response.status === 401
|
|
189
210
|
? "OWNER_SERVICE_UNAVAILABLE"
|
|
190
211
|
: (downstreamCode ??
|
|
191
|
-
(response.status
|
|
192
|
-
? "
|
|
193
|
-
: response.status ===
|
|
194
|
-
? "
|
|
195
|
-
:
|
|
212
|
+
(response.status >= 500
|
|
213
|
+
? "OWNER_SERVICE_UNAVAILABLE"
|
|
214
|
+
: response.status === 400
|
|
215
|
+
? "INVALID_REQUEST"
|
|
216
|
+
: response.status === 403
|
|
217
|
+
? "ROLE_OPERATION_DENIED"
|
|
218
|
+
: "DOWNSTREAM_UNAVAILABLE"));
|
|
196
219
|
throw Object.assign(new AgentGatewayError(code), {
|
|
197
220
|
httpStatus: response.status,
|
|
198
221
|
});
|
|
199
222
|
}
|
|
200
223
|
return response.json();
|
|
201
224
|
};
|
|
225
|
+
const emitOperation = (inputEvent) => {
|
|
226
|
+
const toolOperation = directToolOperationIds.has(inputEvent.operationId)
|
|
227
|
+
? optionalToolOperation(inputEvent.value)
|
|
228
|
+
: undefined;
|
|
229
|
+
try {
|
|
230
|
+
void Promise.resolve(input.operationLog?.({
|
|
231
|
+
contract: "proflow.operation-boundary.v1",
|
|
232
|
+
eventId: `gateway-event:${randomUUID()}`,
|
|
233
|
+
operationRef: inputEvent.operationRef,
|
|
234
|
+
correlationKind: "EXACT",
|
|
235
|
+
timestamp: new Date().toISOString(),
|
|
236
|
+
source: "agent-gateway",
|
|
237
|
+
component: "agent-gateway-ingress",
|
|
238
|
+
event: inputEvent.mode === "LOOKUP"
|
|
239
|
+
? "GATEWAY_ACTION_LOOKUP"
|
|
240
|
+
: "GATEWAY_ACTION",
|
|
241
|
+
boundary: directToolOperationIds.has(inputEvent.operationId)
|
|
242
|
+
? "TOOL_INVOCATION"
|
|
243
|
+
: "ACTION",
|
|
244
|
+
status: inputEvent.status,
|
|
245
|
+
operationId: inputEvent.operationId,
|
|
246
|
+
roleRef: inputEvent.roleRef,
|
|
247
|
+
...(toolOperation ? { toolOperation } : {}),
|
|
248
|
+
...(inputEvent.errorCode ? { errorCode: inputEvent.errorCode } : {}),
|
|
249
|
+
durationMs: inputEvent.durationMs,
|
|
250
|
+
})).catch(() => undefined);
|
|
251
|
+
}
|
|
252
|
+
catch { }
|
|
253
|
+
};
|
|
202
254
|
const gateway = await createAgentGateway({
|
|
255
|
+
onIngressFailure(entry) {
|
|
256
|
+
try {
|
|
257
|
+
void Promise.resolve(input.operationLog?.({
|
|
258
|
+
contract: "proflow.operation-boundary.v1",
|
|
259
|
+
timestamp: new Date().toISOString(),
|
|
260
|
+
eventId: `gateway-event:${randomUUID()}`,
|
|
261
|
+
operationRef: `op:${randomUUID()}`,
|
|
262
|
+
correlationKind: "EXACT",
|
|
263
|
+
source: "agent-gateway",
|
|
264
|
+
component: "agent-gateway-ingress",
|
|
265
|
+
event: "GATEWAY_INGRESS_REJECTED",
|
|
266
|
+
...entry,
|
|
267
|
+
errorCode: "GATEWAY_INGRESS_REJECTED",
|
|
268
|
+
})).catch(() => undefined);
|
|
269
|
+
}
|
|
270
|
+
catch { }
|
|
271
|
+
},
|
|
203
272
|
host: input.config.host,
|
|
204
273
|
port: input.config.port,
|
|
205
274
|
relayBaseUrl: `${input.config.publicBaseUrl}/relay/`,
|
|
@@ -211,23 +280,74 @@ export async function createAgentGatewayProcess(input) {
|
|
|
211
280
|
return roleRef;
|
|
212
281
|
throw new Error("AUTHENTICATION_FAILED");
|
|
213
282
|
},
|
|
214
|
-
route(operationId, authenticatedRoleRef, value, context) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
283
|
+
async route(operationId, authenticatedRoleRef, value, context) {
|
|
284
|
+
const started = performance.now();
|
|
285
|
+
const operationRef = `op:${randomUUID()}`;
|
|
286
|
+
try {
|
|
287
|
+
const result = await downstream(`/actions/${encodeURIComponent(operationId)}`, {
|
|
288
|
+
authenticatedRoleRef,
|
|
289
|
+
input: value,
|
|
290
|
+
deadlineAt: context?.deadlineAt,
|
|
291
|
+
...(context?.fileMaterializationInputs === undefined
|
|
292
|
+
? {}
|
|
293
|
+
: {
|
|
294
|
+
fileMaterializationInputs: context.fileMaterializationInputs,
|
|
295
|
+
}),
|
|
296
|
+
}, context?.signal, operationRef);
|
|
297
|
+
emitOperation({
|
|
298
|
+
mode: "ROUTE",
|
|
299
|
+
operationRef,
|
|
300
|
+
operationId,
|
|
301
|
+
roleRef: authenticatedRoleRef,
|
|
302
|
+
value,
|
|
303
|
+
status: "SUCCEEDED",
|
|
304
|
+
durationMs: performance.now() - started,
|
|
305
|
+
});
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
emitOperation({
|
|
310
|
+
mode: "ROUTE",
|
|
311
|
+
operationRef,
|
|
312
|
+
operationId,
|
|
313
|
+
roleRef: authenticatedRoleRef,
|
|
314
|
+
value,
|
|
315
|
+
status: "FAILED",
|
|
316
|
+
errorCode: logErrorCode(error),
|
|
317
|
+
durationMs: performance.now() - started,
|
|
318
|
+
});
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
225
321
|
},
|
|
226
|
-
lookupResult(operationId, authenticatedRoleRef, value) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
322
|
+
async lookupResult(operationId, authenticatedRoleRef, value) {
|
|
323
|
+
const started = performance.now();
|
|
324
|
+
const operationRef = `op:${randomUUID()}`;
|
|
325
|
+
try {
|
|
326
|
+
const result = await downstream(`/actions/${encodeURIComponent(operationId)}/result`, { authenticatedRoleRef, input: value }, undefined, operationRef);
|
|
327
|
+
emitOperation({
|
|
328
|
+
mode: "LOOKUP",
|
|
329
|
+
operationRef,
|
|
330
|
+
operationId,
|
|
331
|
+
roleRef: authenticatedRoleRef,
|
|
332
|
+
value,
|
|
333
|
+
status: "SUCCEEDED",
|
|
334
|
+
durationMs: performance.now() - started,
|
|
335
|
+
});
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
emitOperation({
|
|
340
|
+
mode: "LOOKUP",
|
|
341
|
+
operationRef,
|
|
342
|
+
operationId,
|
|
343
|
+
roleRef: authenticatedRoleRef,
|
|
344
|
+
value,
|
|
345
|
+
status: "FAILED",
|
|
346
|
+
errorCode: logErrorCode(error),
|
|
347
|
+
durationMs: performance.now() - started,
|
|
348
|
+
});
|
|
349
|
+
throw error;
|
|
350
|
+
}
|
|
231
351
|
},
|
|
232
352
|
async readiness() {
|
|
233
353
|
try {
|
|
@@ -260,6 +380,7 @@ export async function createAgentGatewayProcess(input) {
|
|
|
260
380
|
timestamp: new Date().toISOString(),
|
|
261
381
|
component: "agent-gateway-process",
|
|
262
382
|
event: "SERVICE_STARTED",
|
|
383
|
+
status: "SUCCEEDED",
|
|
263
384
|
...address,
|
|
264
385
|
});
|
|
265
386
|
return address;
|
|
@@ -270,6 +391,7 @@ export async function createAgentGatewayProcess(input) {
|
|
|
270
391
|
timestamp: new Date().toISOString(),
|
|
271
392
|
component: "agent-gateway-process",
|
|
272
393
|
event: "SERVICE_STOPPED",
|
|
394
|
+
status: "SUCCEEDED",
|
|
273
395
|
});
|
|
274
396
|
};
|
|
275
397
|
return Object.freeze({
|
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.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
"@tomflow/proflow-module-contract": "^0.1.13"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@tomflow/proflow-
|
|
31
|
+
"@tomflow/proflow-task-migration-runner": "^0.1.11",
|
|
32
|
+
"@tomflow/proflow-execution-browser-extension": "^0.1.62",
|
|
32
33
|
"@tomflow/proflow-deployment-conformance": "^0.1.13",
|
|
34
|
+
"@tomflow/proflow-agent-runtime": "^0.1.17",
|
|
35
|
+
"@tomflow/proflow-task-store-sqlite": "^0.1.12",
|
|
33
36
|
"@tomflow/proflow-execution-runtime": "^0.1.19",
|
|
34
|
-
"@tomflow/proflow-
|
|
35
|
-
"@tomflow/proflow-
|
|
36
|
-
"@tomflow/proflow-task-orchestration": "^0.1.11",
|
|
37
|
-
"@tomflow/proflow-task-migration-runner": "^0.1.11",
|
|
38
|
-
"@tomflow/proflow-task-store-sqlite": "^0.1.12"
|
|
37
|
+
"@tomflow/proflow-platform-host": "^0.1.29",
|
|
38
|
+
"@tomflow/proflow-task-orchestration": "^0.1.11"
|
|
39
39
|
},
|
|
40
40
|
"description": "The sole Custom GPT Actions HTTP ingress and OpenAI transport anti-corruption layer.",
|
|
41
41
|
"keywords": [
|
package/proflow.module.json
CHANGED