@minicor/mcp-server 3.3.5 → 3.4.0
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/README.md +104 -4
- package/dist/__tests__/middleware-service-client.test.d.ts +2 -0
- package/dist/__tests__/middleware-service-client.test.d.ts.map +1 -0
- package/dist/__tests__/middleware-service-client.test.js +293 -0
- package/dist/__tests__/middleware-service-client.test.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware-service-client.d.ts +258 -0
- package/dist/middleware-service-client.d.ts.map +1 -0
- package/dist/middleware-service-client.js +264 -0
- package/dist/middleware-service-client.js.map +1 -0
- package/dist/prompts/build-rpa.d.ts.map +1 -1
- package/dist/prompts/build-rpa.js +17 -0
- package/dist/prompts/build-rpa.js.map +1 -1
- package/dist/prompts/nestjs-to-job.d.ts +11 -0
- package/dist/prompts/nestjs-to-job.d.ts.map +1 -0
- package/dist/prompts/nestjs-to-job.js +110 -0
- package/dist/prompts/nestjs-to-job.js.map +1 -0
- package/dist/tools/jobs.d.ts +21 -0
- package/dist/tools/jobs.d.ts.map +1 -0
- package/dist/tools/jobs.js +470 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/vm-rpa.d.ts.map +1 -1
- package/dist/tools/vm-rpa.js +109 -25
- package/dist/tools/vm-rpa.js.map +1 -1
- package/package.json +1 -1
- package/skills/general/nestjs-middleware-to-job.md +82 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the middleware-service management API (Jobs + Test Cases).
|
|
3
|
+
*
|
|
4
|
+
* AUTH / TRANSPORT
|
|
5
|
+
* ----------------
|
|
6
|
+
* The middleware-service management API authenticates a *user* Bearer token
|
|
7
|
+
* (validated via /auth/me) plus a workspace-access check — it does NOT accept
|
|
8
|
+
* the MCP's raw API key. The MCP, however, runs with a user bearer token
|
|
9
|
+
* (from ~/.laminar/tokens.json / LAMINAR_ACCESS_TOKEN, refreshed in index.ts).
|
|
10
|
+
*
|
|
11
|
+
* BASE-URL SELECTION (mirrors how the frontend's server/jobs.ts +
|
|
12
|
+
* lib/jobs/types.ts resolve the middleware-service host — region-aware):
|
|
13
|
+
*
|
|
14
|
+
* 1. PROXY mode — set `MIDDLEWARE_SERVICE_PROXY_BASE` (the deployed frontend
|
|
15
|
+
* origin, e.g. https://app.laminar.run; region-aware via
|
|
16
|
+
* `MIDDLEWARE_SERVICE_PROXY_BASE_US` / `_CA`). Requests go to
|
|
17
|
+
* `${proxyBase}${proxyPrefix}/<path>` where `proxyPrefix` defaults to
|
|
18
|
+
* `/api/middleware` (override with `MIDDLEWARE_SERVICE_PROXY_PREFIX`), and
|
|
19
|
+
* the leading `/api/` is stripped from the management path (so
|
|
20
|
+
* `/api/workspaces/...` becomes `/api/middleware/workspaces/...`). The
|
|
21
|
+
* frontend validates the user bearer and forwards to the (IAM-private)
|
|
22
|
+
* middleware-service. NOTE: the frontend currently reaches middleware-service
|
|
23
|
+
* through Next.js *server actions* (server/jobs.ts), not an HTTP proxy
|
|
24
|
+
* route — there is no `/api/middleware/[...path]` handler yet. Once one is
|
|
25
|
+
* deployed, setting MIDDLEWARE_SERVICE_PROXY_BASE flips the MCP onto it with
|
|
26
|
+
* no code change.
|
|
27
|
+
*
|
|
28
|
+
* 2. DIRECT override — set `MIDDLEWARE_SERVICE_URL` (all regions) or
|
|
29
|
+
* `MIDDLEWARE_SERVICE_URL_US` / `_CA` (per region) to hit a specific
|
|
30
|
+
* reachable instance (dev/local). Requests go to `${base}/api/workspaces/...`.
|
|
31
|
+
*
|
|
32
|
+
* 3. DEFAULT (deployed) — the public middleware-service Cloud Run URL for the
|
|
33
|
+
* region (us / ca), hit directly at `${base}/api/workspaces/...`. These are
|
|
34
|
+
* the same hosts the frontend's lib/jobs/types.ts targets.
|
|
35
|
+
*
|
|
36
|
+
* Precedence: PROXY (1) > DIRECT override (2) > DEFAULT Cloud Run (3).
|
|
37
|
+
*
|
|
38
|
+
* A "Job" is a middleware *route* whose behavior is a structured `definition`
|
|
39
|
+
* (step graph) rather than freeform `handlerCode` (see middlewares/JOBS-DESIGN.md).
|
|
40
|
+
*/
|
|
41
|
+
export type JobStepKind = "workflow" | "code";
|
|
42
|
+
export interface JobStep {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
kind: JobStepKind;
|
|
46
|
+
saveAs?: string;
|
|
47
|
+
when?: string;
|
|
48
|
+
forEach?: string;
|
|
49
|
+
onError?: "abort" | "skip" | "continue" | {
|
|
50
|
+
goto: string;
|
|
51
|
+
};
|
|
52
|
+
retry?: {
|
|
53
|
+
max: number;
|
|
54
|
+
backoffMs?: number;
|
|
55
|
+
};
|
|
56
|
+
cache?: {
|
|
57
|
+
key: string;
|
|
58
|
+
ttlMs: number;
|
|
59
|
+
};
|
|
60
|
+
workflowId?: number;
|
|
61
|
+
configStoreId?: string;
|
|
62
|
+
input?: Record<string, unknown> | string;
|
|
63
|
+
code?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface JobDefinition {
|
|
66
|
+
region: "us" | "ca";
|
|
67
|
+
resource?: {
|
|
68
|
+
configStoreId?: string;
|
|
69
|
+
lockKey?: string;
|
|
70
|
+
};
|
|
71
|
+
inputSchema: Record<string, unknown>;
|
|
72
|
+
outputSchema: Record<string, unknown>;
|
|
73
|
+
steps: JobStep[];
|
|
74
|
+
output?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface Assertion {
|
|
77
|
+
name: string;
|
|
78
|
+
/** TS boolean expression over `{ input, output, ctx, steps }`. */
|
|
79
|
+
expr: string;
|
|
80
|
+
}
|
|
81
|
+
export interface TestCase {
|
|
82
|
+
id: string;
|
|
83
|
+
routeId: string;
|
|
84
|
+
name: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
input: Record<string, unknown>;
|
|
87
|
+
assertions: Assertion[];
|
|
88
|
+
tags?: string[];
|
|
89
|
+
enabled?: boolean;
|
|
90
|
+
}
|
|
91
|
+
export interface Middleware {
|
|
92
|
+
id: string;
|
|
93
|
+
workspaceId: number;
|
|
94
|
+
name: string;
|
|
95
|
+
slug: string;
|
|
96
|
+
description?: string;
|
|
97
|
+
status?: string;
|
|
98
|
+
workspaceApiKey?: string;
|
|
99
|
+
}
|
|
100
|
+
export interface MiddlewareRoute {
|
|
101
|
+
id: string;
|
|
102
|
+
middlewareId: string;
|
|
103
|
+
method: string;
|
|
104
|
+
path: string;
|
|
105
|
+
definition?: JobDefinition;
|
|
106
|
+
description?: string;
|
|
107
|
+
}
|
|
108
|
+
export interface JobExecution {
|
|
109
|
+
id: string;
|
|
110
|
+
routeId: string;
|
|
111
|
+
status: "queued" | "running" | "succeeded" | "partial" | "failed";
|
|
112
|
+
input?: unknown;
|
|
113
|
+
output?: unknown;
|
|
114
|
+
context?: unknown;
|
|
115
|
+
steps?: unknown[];
|
|
116
|
+
error?: unknown;
|
|
117
|
+
startedAt?: string;
|
|
118
|
+
completedAt?: string;
|
|
119
|
+
durationMs?: number;
|
|
120
|
+
}
|
|
121
|
+
export interface TestRun {
|
|
122
|
+
id: string;
|
|
123
|
+
routeId: string;
|
|
124
|
+
status: "running" | "passed" | "failed";
|
|
125
|
+
totals?: {
|
|
126
|
+
total: number;
|
|
127
|
+
passed: number;
|
|
128
|
+
failed: number;
|
|
129
|
+
errored: number;
|
|
130
|
+
};
|
|
131
|
+
startedAt?: string;
|
|
132
|
+
completedAt?: string;
|
|
133
|
+
}
|
|
134
|
+
export interface TestResult {
|
|
135
|
+
id: string;
|
|
136
|
+
testRunId: string;
|
|
137
|
+
testCaseId: string;
|
|
138
|
+
jobExecutionId?: string;
|
|
139
|
+
passed: boolean;
|
|
140
|
+
failures?: unknown;
|
|
141
|
+
}
|
|
142
|
+
export interface Page<T> {
|
|
143
|
+
content: T[];
|
|
144
|
+
totalElements: number;
|
|
145
|
+
totalPages: number;
|
|
146
|
+
number: number;
|
|
147
|
+
size: number;
|
|
148
|
+
}
|
|
149
|
+
export declare class MiddlewareServiceClient {
|
|
150
|
+
private token;
|
|
151
|
+
private base;
|
|
152
|
+
private viaProxy;
|
|
153
|
+
/** Proxy path prefix (proxy mode only), e.g. `/api/middleware`. */
|
|
154
|
+
private proxyPrefix;
|
|
155
|
+
constructor(apiBase: string, token: string);
|
|
156
|
+
/**
|
|
157
|
+
* Proxy mode: `${proxyBase}${proxyPrefix}/<path>` with the leading `/api/`
|
|
158
|
+
* stripped (so `/api/workspaces/...` -> `/api/middleware/workspaces/...`),
|
|
159
|
+
* matching the agent/skills proxy convention.
|
|
160
|
+
* Direct mode: `${base}/api/workspaces/...`.
|
|
161
|
+
*/
|
|
162
|
+
private request;
|
|
163
|
+
private routesBase;
|
|
164
|
+
private middlewaresBase;
|
|
165
|
+
/** List the routers (middlewares) in a workspace. */
|
|
166
|
+
listMiddlewares(workspaceId: number): Promise<Middleware[]>;
|
|
167
|
+
/** Create a router (middleware) that jobs/routes attach to. */
|
|
168
|
+
createMiddleware(workspaceId: number, body: {
|
|
169
|
+
name: string;
|
|
170
|
+
slug: string;
|
|
171
|
+
description?: string;
|
|
172
|
+
workspaceApiKey?: string;
|
|
173
|
+
}): Promise<Middleware>;
|
|
174
|
+
/** Auto-configure the router's workspace API key from the workspace's keys. */
|
|
175
|
+
autoConfigureMiddleware(workspaceId: number, middlewareId: string): Promise<unknown>;
|
|
176
|
+
/** Fetch a single router (middleware) by id (list + filter; no single GET). */
|
|
177
|
+
getMiddleware(workspaceId: number, middlewareId: string): Promise<Middleware | undefined>;
|
|
178
|
+
/** Update a router (middleware) — e.g. to set its `workspaceApiKey`. */
|
|
179
|
+
updateMiddleware(workspaceId: number, middlewareId: string, body: {
|
|
180
|
+
workspaceApiKey?: string;
|
|
181
|
+
name?: string;
|
|
182
|
+
slug?: string;
|
|
183
|
+
description?: string;
|
|
184
|
+
}): Promise<Middleware>;
|
|
185
|
+
/**
|
|
186
|
+
* Set the router's `workspaceApiKey`, then RE-READ the middleware and return
|
|
187
|
+
* it so callers can confirm the key actually stuck (non-null/non-empty).
|
|
188
|
+
*/
|
|
189
|
+
setWorkspaceApiKey(workspaceId: number, middlewareId: string, workspaceApiKey: string): Promise<Middleware | undefined>;
|
|
190
|
+
/**
|
|
191
|
+
* Create a job-backed route. The management API exposes route creation under
|
|
192
|
+
* the middleware; passing a `definition` makes the route job-backed.
|
|
193
|
+
*/
|
|
194
|
+
createJob(workspaceId: number, middlewareId: string, body: {
|
|
195
|
+
method?: string;
|
|
196
|
+
path: string;
|
|
197
|
+
description?: string;
|
|
198
|
+
definition: JobDefinition;
|
|
199
|
+
}): Promise<MiddlewareRoute>;
|
|
200
|
+
updateJob(workspaceId: number, middlewareId: string, routeId: string, body: {
|
|
201
|
+
method?: string;
|
|
202
|
+
path?: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
definition?: JobDefinition;
|
|
205
|
+
}): Promise<MiddlewareRoute>;
|
|
206
|
+
/**
|
|
207
|
+
* The contract notes there is currently NO `GET /routes/:routeId` (single).
|
|
208
|
+
* List all routes and filter client-side.
|
|
209
|
+
*/
|
|
210
|
+
listRoutes(workspaceId: number, middlewareId: string): Promise<MiddlewareRoute[]>;
|
|
211
|
+
getJob(workspaceId: number, middlewareId: string, routeId: string): Promise<MiddlewareRoute | undefined>;
|
|
212
|
+
runJob(workspaceId: number, middlewareId: string, routeId: string, input: Record<string, unknown>, trigger?: "mcp" | "api" | "test"): Promise<{
|
|
213
|
+
jobExecutionId: string;
|
|
214
|
+
}>;
|
|
215
|
+
getExecution(workspaceId: number, middlewareId: string, routeId: string, executionId: string): Promise<JobExecution>;
|
|
216
|
+
listExecutions(workspaceId: number, middlewareId: string, routeId: string, opts?: {
|
|
217
|
+
page?: number;
|
|
218
|
+
size?: number;
|
|
219
|
+
status?: string;
|
|
220
|
+
search?: string;
|
|
221
|
+
}): Promise<Page<JobExecution>>;
|
|
222
|
+
listTestCases(workspaceId: number, middlewareId: string, routeId: string): Promise<TestCase[]>;
|
|
223
|
+
addTestCase(workspaceId: number, middlewareId: string, routeId: string, body: {
|
|
224
|
+
name: string;
|
|
225
|
+
description?: string;
|
|
226
|
+
input: Record<string, unknown>;
|
|
227
|
+
assertions: Assertion[];
|
|
228
|
+
tags?: string[];
|
|
229
|
+
enabled?: boolean;
|
|
230
|
+
}): Promise<TestCase>;
|
|
231
|
+
updateTestCase(workspaceId: number, middlewareId: string, routeId: string, testCaseId: string, body: Partial<{
|
|
232
|
+
name: string;
|
|
233
|
+
description: string;
|
|
234
|
+
input: Record<string, unknown>;
|
|
235
|
+
assertions: Assertion[];
|
|
236
|
+
tags: string[];
|
|
237
|
+
enabled: boolean;
|
|
238
|
+
}>): Promise<TestCase>;
|
|
239
|
+
startTestRun(workspaceId: number, middlewareId: string, routeId: string, testCaseIds?: string[]): Promise<{
|
|
240
|
+
testRunId: string;
|
|
241
|
+
}>;
|
|
242
|
+
getTestRun(workspaceId: number, middlewareId: string, routeId: string, testRunId: string): Promise<{
|
|
243
|
+
testRun: TestRun;
|
|
244
|
+
results: TestResult[];
|
|
245
|
+
}>;
|
|
246
|
+
pollExecution(workspaceId: number, middlewareId: string, routeId: string, executionId: string, opts?: {
|
|
247
|
+
intervalMs?: number;
|
|
248
|
+
timeoutMs?: number;
|
|
249
|
+
}): Promise<JobExecution>;
|
|
250
|
+
pollTestRun(workspaceId: number, middlewareId: string, routeId: string, testRunId: string, opts?: {
|
|
251
|
+
intervalMs?: number;
|
|
252
|
+
timeoutMs?: number;
|
|
253
|
+
}): Promise<{
|
|
254
|
+
testRun: TestRun;
|
|
255
|
+
results: TestResult[];
|
|
256
|
+
}>;
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=middleware-service-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware-service-client.d.ts","sourceRoot":"","sources":["../src/middleware-service-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the middleware-service management API (Jobs + Test Cases).
|
|
3
|
+
*
|
|
4
|
+
* AUTH / TRANSPORT
|
|
5
|
+
* ----------------
|
|
6
|
+
* The middleware-service management API authenticates a *user* Bearer token
|
|
7
|
+
* (validated via /auth/me) plus a workspace-access check — it does NOT accept
|
|
8
|
+
* the MCP's raw API key. The MCP, however, runs with a user bearer token
|
|
9
|
+
* (from ~/.laminar/tokens.json / LAMINAR_ACCESS_TOKEN, refreshed in index.ts).
|
|
10
|
+
*
|
|
11
|
+
* BASE-URL SELECTION (mirrors how the frontend's server/jobs.ts +
|
|
12
|
+
* lib/jobs/types.ts resolve the middleware-service host — region-aware):
|
|
13
|
+
*
|
|
14
|
+
* 1. PROXY mode — set `MIDDLEWARE_SERVICE_PROXY_BASE` (the deployed frontend
|
|
15
|
+
* origin, e.g. https://app.laminar.run; region-aware via
|
|
16
|
+
* `MIDDLEWARE_SERVICE_PROXY_BASE_US` / `_CA`). Requests go to
|
|
17
|
+
* `${proxyBase}${proxyPrefix}/<path>` where `proxyPrefix` defaults to
|
|
18
|
+
* `/api/middleware` (override with `MIDDLEWARE_SERVICE_PROXY_PREFIX`), and
|
|
19
|
+
* the leading `/api/` is stripped from the management path (so
|
|
20
|
+
* `/api/workspaces/...` becomes `/api/middleware/workspaces/...`). The
|
|
21
|
+
* frontend validates the user bearer and forwards to the (IAM-private)
|
|
22
|
+
* middleware-service. NOTE: the frontend currently reaches middleware-service
|
|
23
|
+
* through Next.js *server actions* (server/jobs.ts), not an HTTP proxy
|
|
24
|
+
* route — there is no `/api/middleware/[...path]` handler yet. Once one is
|
|
25
|
+
* deployed, setting MIDDLEWARE_SERVICE_PROXY_BASE flips the MCP onto it with
|
|
26
|
+
* no code change.
|
|
27
|
+
*
|
|
28
|
+
* 2. DIRECT override — set `MIDDLEWARE_SERVICE_URL` (all regions) or
|
|
29
|
+
* `MIDDLEWARE_SERVICE_URL_US` / `_CA` (per region) to hit a specific
|
|
30
|
+
* reachable instance (dev/local). Requests go to `${base}/api/workspaces/...`.
|
|
31
|
+
*
|
|
32
|
+
* 3. DEFAULT (deployed) — the public middleware-service Cloud Run URL for the
|
|
33
|
+
* region (us / ca), hit directly at `${base}/api/workspaces/...`. These are
|
|
34
|
+
* the same hosts the frontend's lib/jobs/types.ts targets.
|
|
35
|
+
*
|
|
36
|
+
* Precedence: PROXY (1) > DIRECT override (2) > DEFAULT Cloud Run (3).
|
|
37
|
+
*
|
|
38
|
+
* A "Job" is a middleware *route* whose behavior is a structured `definition`
|
|
39
|
+
* (step graph) rather than freeform `handlerCode` (see middlewares/JOBS-DESIGN.md).
|
|
40
|
+
*/
|
|
41
|
+
// ─── Client ───────────────────────────────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Public middleware-service Cloud Run URLs (the deployed default), per region.
|
|
44
|
+
* These mirror the frontend's lib/jobs/types.ts `middlewareRuntimeHost` and the
|
|
45
|
+
* earlier MCP `SERVICE_BASE` map. Used when neither the proxy nor a direct
|
|
46
|
+
* override is configured.
|
|
47
|
+
*/
|
|
48
|
+
const DEFAULT_DIRECT_BASE = {
|
|
49
|
+
us: "https://middleware-service-489511347341.northamerica-northeast1.run.app",
|
|
50
|
+
ca: "https://middleware-service-ca-ernfuwetfa-nn.a.run.app",
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The frontend origin that fronts a middleware proxy, if one is deployed.
|
|
54
|
+
* Region-aware to match the platform's split frontends (e.g. app.laminar.run vs
|
|
55
|
+
* ca.app.laminar.run): `MIDDLEWARE_SERVICE_PROXY_BASE` applies to all regions,
|
|
56
|
+
* `MIDDLEWARE_SERVICE_PROXY_BASE_US` / `_CA` override it per region.
|
|
57
|
+
*/
|
|
58
|
+
function proxyBaseOverride(isCa) {
|
|
59
|
+
const generic = process.env.MIDDLEWARE_SERVICE_PROXY_BASE;
|
|
60
|
+
const regional = isCa
|
|
61
|
+
? process.env.MIDDLEWARE_SERVICE_PROXY_BASE_CA
|
|
62
|
+
: process.env.MIDDLEWARE_SERVICE_PROXY_BASE_US;
|
|
63
|
+
const base = regional ?? generic;
|
|
64
|
+
return base && base.trim() !== "" ? base : undefined;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* DIRECT base override (dev/local, or a specific reachable instance).
|
|
68
|
+
* `MIDDLEWARE_SERVICE_URL` applies to all regions; `MIDDLEWARE_SERVICE_URL_US` /
|
|
69
|
+
* `_CA` override it per region.
|
|
70
|
+
*/
|
|
71
|
+
function directBaseOverride(isCa) {
|
|
72
|
+
const generic = process.env.MIDDLEWARE_SERVICE_URL;
|
|
73
|
+
return isCa
|
|
74
|
+
? process.env.MIDDLEWARE_SERVICE_URL_CA ?? generic
|
|
75
|
+
: process.env.MIDDLEWARE_SERVICE_URL_US ?? generic;
|
|
76
|
+
}
|
|
77
|
+
export class MiddlewareServiceClient {
|
|
78
|
+
token;
|
|
79
|
+
base;
|
|
80
|
+
viaProxy;
|
|
81
|
+
/** Proxy path prefix (proxy mode only), e.g. `/api/middleware`. */
|
|
82
|
+
proxyPrefix;
|
|
83
|
+
constructor(apiBase, token) {
|
|
84
|
+
this.token = token;
|
|
85
|
+
const isCa = /\bca\./.test(apiBase);
|
|
86
|
+
const proxyBase = proxyBaseOverride(isCa);
|
|
87
|
+
const directOverride = directBaseOverride(isCa);
|
|
88
|
+
if (proxyBase) {
|
|
89
|
+
// (1) PROXY mode — route through the deployed frontend proxy.
|
|
90
|
+
this.base = proxyBase.replace(/\/+$/, "");
|
|
91
|
+
this.viaProxy = true;
|
|
92
|
+
this.proxyPrefix =
|
|
93
|
+
"/" +
|
|
94
|
+
(process.env.MIDDLEWARE_SERVICE_PROXY_PREFIX ?? "/api/middleware")
|
|
95
|
+
.replace(/^\/+/, "")
|
|
96
|
+
.replace(/\/+$/, "");
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// (2) DIRECT override, else (3) the region's public Cloud Run default —
|
|
100
|
+
// both call `${base}/api/workspaces/...` directly with the user bearer.
|
|
101
|
+
this.base = (directOverride ?? (isCa ? DEFAULT_DIRECT_BASE.ca : DEFAULT_DIRECT_BASE.us)).replace(/\/+$/, "");
|
|
102
|
+
this.viaProxy = false;
|
|
103
|
+
this.proxyPrefix = "";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Proxy mode: `${proxyBase}${proxyPrefix}/<path>` with the leading `/api/`
|
|
108
|
+
* stripped (so `/api/workspaces/...` -> `/api/middleware/workspaces/...`),
|
|
109
|
+
* matching the agent/skills proxy convention.
|
|
110
|
+
* Direct mode: `${base}/api/workspaces/...`.
|
|
111
|
+
*/
|
|
112
|
+
async request(method, apiPath, body) {
|
|
113
|
+
const path = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
|
|
114
|
+
const url = this.viaProxy
|
|
115
|
+
? `${this.base}${this.proxyPrefix}/${path.replace(/^\/api\//, "").replace(/^\/+/, "")}`
|
|
116
|
+
: `${this.base}${path}`;
|
|
117
|
+
const res = await fetch(url, {
|
|
118
|
+
method,
|
|
119
|
+
headers: {
|
|
120
|
+
"Content-Type": "application/json",
|
|
121
|
+
Authorization: `Bearer ${this.token}`,
|
|
122
|
+
},
|
|
123
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
124
|
+
});
|
|
125
|
+
if (!res.ok) {
|
|
126
|
+
const errText = await res.text().catch(() => "");
|
|
127
|
+
throw new Error(`Middleware service ${method} ${apiPath} failed (${res.status}): ${errText}`);
|
|
128
|
+
}
|
|
129
|
+
if (res.status === 204)
|
|
130
|
+
return undefined;
|
|
131
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
132
|
+
if (contentType.includes("application/json"))
|
|
133
|
+
return res.json();
|
|
134
|
+
return res.text();
|
|
135
|
+
}
|
|
136
|
+
routesBase(workspaceId, middlewareId) {
|
|
137
|
+
return `/api/workspaces/${workspaceId}/middlewares/${middlewareId}/routes`;
|
|
138
|
+
}
|
|
139
|
+
middlewaresBase(workspaceId) {
|
|
140
|
+
return `/api/workspaces/${workspaceId}/middlewares`;
|
|
141
|
+
}
|
|
142
|
+
// ── Middlewares (routers) ──────────────────────────────────
|
|
143
|
+
/** List the routers (middlewares) in a workspace. */
|
|
144
|
+
async listMiddlewares(workspaceId) {
|
|
145
|
+
return this.request("GET", this.middlewaresBase(workspaceId));
|
|
146
|
+
}
|
|
147
|
+
/** Create a router (middleware) that jobs/routes attach to. */
|
|
148
|
+
async createMiddleware(workspaceId, body) {
|
|
149
|
+
return this.request("POST", this.middlewaresBase(workspaceId), body);
|
|
150
|
+
}
|
|
151
|
+
/** Auto-configure the router's workspace API key from the workspace's keys. */
|
|
152
|
+
async autoConfigureMiddleware(workspaceId, middlewareId) {
|
|
153
|
+
return this.request("POST", `${this.middlewaresBase(workspaceId)}/${middlewareId}/auto-configure`);
|
|
154
|
+
}
|
|
155
|
+
/** Fetch a single router (middleware) by id (list + filter; no single GET). */
|
|
156
|
+
async getMiddleware(workspaceId, middlewareId) {
|
|
157
|
+
const middlewares = await this.listMiddlewares(workspaceId);
|
|
158
|
+
return middlewares.find((m) => m.id === middlewareId);
|
|
159
|
+
}
|
|
160
|
+
/** Update a router (middleware) — e.g. to set its `workspaceApiKey`. */
|
|
161
|
+
async updateMiddleware(workspaceId, middlewareId, body) {
|
|
162
|
+
return this.request("PUT", `${this.middlewaresBase(workspaceId)}/${middlewareId}`, body);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Set the router's `workspaceApiKey`, then RE-READ the middleware and return
|
|
166
|
+
* it so callers can confirm the key actually stuck (non-null/non-empty).
|
|
167
|
+
*/
|
|
168
|
+
async setWorkspaceApiKey(workspaceId, middlewareId, workspaceApiKey) {
|
|
169
|
+
await this.updateMiddleware(workspaceId, middlewareId, { workspaceApiKey });
|
|
170
|
+
return this.getMiddleware(workspaceId, middlewareId);
|
|
171
|
+
}
|
|
172
|
+
// ── Jobs (routes) ──────────────────────────────────────────
|
|
173
|
+
/**
|
|
174
|
+
* Create a job-backed route. The management API exposes route creation under
|
|
175
|
+
* the middleware; passing a `definition` makes the route job-backed.
|
|
176
|
+
*/
|
|
177
|
+
async createJob(workspaceId, middlewareId, body) {
|
|
178
|
+
return this.request("POST", this.routesBase(workspaceId, middlewareId),
|
|
179
|
+
// Spread first, then apply the default so `method` is `body.method ?? "POST"`
|
|
180
|
+
// even when the caller passes `method: undefined`.
|
|
181
|
+
{ ...body, method: body.method ?? "POST" });
|
|
182
|
+
}
|
|
183
|
+
async updateJob(workspaceId, middlewareId, routeId, body) {
|
|
184
|
+
return this.request("PUT", `${this.routesBase(workspaceId, middlewareId)}/${routeId}`, body);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The contract notes there is currently NO `GET /routes/:routeId` (single).
|
|
188
|
+
* List all routes and filter client-side.
|
|
189
|
+
*/
|
|
190
|
+
async listRoutes(workspaceId, middlewareId) {
|
|
191
|
+
const data = await this.request("GET", this.routesBase(workspaceId, middlewareId));
|
|
192
|
+
if (Array.isArray(data))
|
|
193
|
+
return data;
|
|
194
|
+
return data?.routes ?? [];
|
|
195
|
+
}
|
|
196
|
+
async getJob(workspaceId, middlewareId, routeId) {
|
|
197
|
+
const routes = await this.listRoutes(workspaceId, middlewareId);
|
|
198
|
+
return routes.find((r) => r.id === routeId);
|
|
199
|
+
}
|
|
200
|
+
async runJob(workspaceId, middlewareId, routeId, input, trigger = "mcp") {
|
|
201
|
+
return this.request("POST", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/run`, { input, trigger });
|
|
202
|
+
}
|
|
203
|
+
async getExecution(workspaceId, middlewareId, routeId, executionId) {
|
|
204
|
+
return this.request("GET", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/executions/${executionId}`);
|
|
205
|
+
}
|
|
206
|
+
async listExecutions(workspaceId, middlewareId, routeId, opts) {
|
|
207
|
+
const params = new URLSearchParams();
|
|
208
|
+
if (opts?.page != null)
|
|
209
|
+
params.set("page", String(opts.page));
|
|
210
|
+
if (opts?.size != null)
|
|
211
|
+
params.set("size", String(opts.size));
|
|
212
|
+
if (opts?.status)
|
|
213
|
+
params.set("status", opts.status);
|
|
214
|
+
if (opts?.search)
|
|
215
|
+
params.set("search", opts.search);
|
|
216
|
+
const qs = params.toString();
|
|
217
|
+
return this.request("GET", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/executions${qs ? `?${qs}` : ""}`);
|
|
218
|
+
}
|
|
219
|
+
// ── Test cases ─────────────────────────────────────────────
|
|
220
|
+
async listTestCases(workspaceId, middlewareId, routeId) {
|
|
221
|
+
return this.request("GET", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/test-cases`);
|
|
222
|
+
}
|
|
223
|
+
async addTestCase(workspaceId, middlewareId, routeId, body) {
|
|
224
|
+
return this.request("POST", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/test-cases`, body);
|
|
225
|
+
}
|
|
226
|
+
async updateTestCase(workspaceId, middlewareId, routeId, testCaseId, body) {
|
|
227
|
+
return this.request("PUT", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/test-cases/${testCaseId}`, body);
|
|
228
|
+
}
|
|
229
|
+
// ── Test runs ──────────────────────────────────────────────
|
|
230
|
+
async startTestRun(workspaceId, middlewareId, routeId, testCaseIds) {
|
|
231
|
+
return this.request("POST", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/test-runs`, testCaseIds ? { testCaseIds } : {});
|
|
232
|
+
}
|
|
233
|
+
async getTestRun(workspaceId, middlewareId, routeId, testRunId) {
|
|
234
|
+
return this.request("GET", `${this.routesBase(workspaceId, middlewareId)}/${routeId}/test-runs/${testRunId}`);
|
|
235
|
+
}
|
|
236
|
+
// ── Polling helpers ────────────────────────────────────────
|
|
237
|
+
async pollExecution(workspaceId, middlewareId, routeId, executionId, opts) {
|
|
238
|
+
const interval = opts?.intervalMs ?? 3000;
|
|
239
|
+
const timeout = opts?.timeoutMs ?? 5 * 60 * 1000;
|
|
240
|
+
const deadline = Date.now() + timeout;
|
|
241
|
+
let last;
|
|
242
|
+
while (Date.now() < deadline) {
|
|
243
|
+
last = await this.getExecution(workspaceId, middlewareId, routeId, executionId);
|
|
244
|
+
if (last.status !== "running" && last.status !== "queued")
|
|
245
|
+
return last;
|
|
246
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
247
|
+
}
|
|
248
|
+
throw new Error(`Timed out polling job execution ${executionId} after ${timeout}ms (last status: ${last?.status ?? "unknown"})`);
|
|
249
|
+
}
|
|
250
|
+
async pollTestRun(workspaceId, middlewareId, routeId, testRunId, opts) {
|
|
251
|
+
const interval = opts?.intervalMs ?? 3000;
|
|
252
|
+
const timeout = opts?.timeoutMs ?? 10 * 60 * 1000;
|
|
253
|
+
const deadline = Date.now() + timeout;
|
|
254
|
+
let last;
|
|
255
|
+
while (Date.now() < deadline) {
|
|
256
|
+
last = await this.getTestRun(workspaceId, middlewareId, routeId, testRunId);
|
|
257
|
+
if (last.testRun.status !== "running")
|
|
258
|
+
return last;
|
|
259
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
260
|
+
}
|
|
261
|
+
throw new Error(`Timed out polling test run ${testRunId} after ${timeout}ms (last status: ${last?.testRun.status ?? "unknown"})`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=middleware-service-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware-service-client.js","sourceRoot":"","sources":["../src/middleware-service-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-rpa.d.ts","sourceRoot":"","sources":["../../src/prompts/build-rpa.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"build-rpa.d.ts","sourceRoot":"","sources":["../../src/prompts/build-rpa.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,QA+K5C"}
|
|
@@ -40,6 +40,20 @@ ${appName}
|
|
|
40
40
|
ID: ${workspaceId}${workflowId ? `\nExisting workflow ID: ${workflowId} (add steps to this workflow)` : "\nCreate a new workflow for this automation."}
|
|
41
41
|
${modeSection}
|
|
42
42
|
|
|
43
|
+
## WORK BACKWARDS — Define the Test Case FIRST
|
|
44
|
+
|
|
45
|
+
Before building anything, write down what "done" means as a concrete, runnable test:
|
|
46
|
+
|
|
47
|
+
1. **State the contract.** What input does this automation take, and what output proves it worked? Write the input JSON and the expected output shape.
|
|
48
|
+
2. **Author the green-gate.** A workflow's behavior is locked in by a **Job** with **test cases**. As the very first build artifact:
|
|
49
|
+
- Register a thin Job for this automation: \`register_job\` with a \`definition\` whose single \`workflow\` step calls this workflow (use a placeholder \`workflowId\` you'll fill in, or the existing one). The job is the testable wrapper above the workflow.
|
|
50
|
+
- Add the test case NOW: \`add_test_case\` with the input from step 1 and assertions \`[{ name, expr }]\` describing the expected output (e.g. \`output.patientId != null\`, \`output.status === "ok"\`). \`expr\` is a TS boolean over \`{ input, output, ctx, steps }\`.
|
|
51
|
+
3. **The test is RED.** It will fail until the workflow exists and is correct. That red test is your target.
|
|
52
|
+
4. **Build the workflow** (the loop below) to turn the test GREEN.
|
|
53
|
+
5. **Green-gate:** the build is NOT done until \`run_tests\` reports \`green: true\`. Re-run \`run_tests\` after every meaningful change.
|
|
54
|
+
|
|
55
|
+
Use test patients only — never real patient data. Pick inputs/slots far in the future so tests don't collide with real schedules.
|
|
56
|
+
|
|
43
57
|
## MANDATORY FIRST STEP — Load Testing Skill
|
|
44
58
|
|
|
45
59
|
Before doing ANYTHING else, run: \`get_skill("rpa-testing-workflow")\`
|
|
@@ -121,6 +135,9 @@ b. Poll \`get_execution_status\` every 5-10s, \`vm_screenshot\` at intervals to
|
|
|
121
135
|
c. On failure → \`diagnose_execution\` + \`vm_screenshot\`, fix with \`update_flow\`, re-run FULL workflow
|
|
122
136
|
d. Iterate until full workflow passes. **Do NOT declare done until it passes.**${isProduction ? "\ne. Run the workflow a SECOND time to verify idempotency." : ""}
|
|
123
137
|
|
|
138
|
+
### 6b. GREEN-GATE — run_tests
|
|
139
|
+
The workflow passing once is not enough. Point the Job's workflow step at the finished \`workflowId\` (\`update_job\` if needed), then run \`run_tests\` for the job. **The build is done ONLY when \`run_tests\` returns \`green: true\`** and every test case passes. On a red result, drill into the failing case's job execution → step → Minicor run, fix, and re-run \`run_tests\`. Add more \`add_test_case\` entries for edge cases (empty results, not-found, second-run idempotency) and keep them green.
|
|
140
|
+
|
|
124
141
|
### 7. Iterate with the User
|
|
125
142
|
${isProduction ? `
|
|
126
143
|
### 8. Production Hardening
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-rpa.js","sourceRoot":"","sources":["../../src/prompts/build-rpa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAY;IAC3C,MAAM,CAAC,MAAM,CACX,oBAAoB,EACpB,wSAAwS,EACxS;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,CACP,iHAAiH,CAClH;QACH,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,CACP,uFAAuF,CACxF;QACH,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sEAAsE,CACvE;QACH,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;aAC3B,QAAQ,EAAE;aACV,QAAQ,CACP,4HAA4H,CAC7H;KACJ,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE;QACzD,MAAM,YAAY,GAAG,IAAI,KAAK,YAAY,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC;QAC7B,MAAM,WAAW,GAAG,IAAI;YACtB,CAAC,CAAC,aAAa,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,iFAAiF,EAAE;YAC9K,CAAC,CAAC,yIAAyI,CAAC;QAE9I,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAe;oBACrB,OAAO,EAAE;wBACP,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE;;;EAGlB,IAAI;;;EAGJ,OAAO;;;MAGH,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,2BAA2B,UAAU,+BAA+B,CAAC,CAAC,CAAC,8CAA8C;EACpJ,WAAW
|
|
1
|
+
{"version":3,"file":"build-rpa.js","sourceRoot":"","sources":["../../src/prompts/build-rpa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAY;IAC3C,MAAM,CAAC,MAAM,CACX,oBAAoB,EACpB,wSAAwS,EACxS;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,CACP,iHAAiH,CAClH;QACH,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,CACP,uFAAuF,CACxF;QACH,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sEAAsE,CACvE;QACH,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;aAC3B,QAAQ,EAAE;aACV,QAAQ,CACP,4HAA4H,CAC7H;KACJ,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE;QACzD,MAAM,YAAY,GAAG,IAAI,KAAK,YAAY,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC;QAC7B,MAAM,WAAW,GAAG,IAAI;YACtB,CAAC,CAAC,aAAa,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,iFAAiF,EAAE;YAC9K,CAAC,CAAC,yIAAyI,CAAC;QAE9I,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAe;oBACrB,OAAO,EAAE;wBACP,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE;;;EAGlB,IAAI;;;EAGJ,OAAO;;;MAGH,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,2BAA2B,UAAU,+BAA+B,CAAC,CAAC,CAAC,8CAA8C;EACpJ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0EAqC6D,YAAY,CAAC,CAAC,CAAC,sGAAsG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oGAAoG;;;;;;;;;;;;;;;;;;;;;;;;;YAyBvS,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iFAiC8D,YAAY,CAAC,CAAC,CAAC,4DAA4D,CAAC,CAAC,CAAC,EAAE;;;;;;EAM/J,YAAY,CAAC,CAAC,CAAC;;;;;;CAMhB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;;;CAIhB;;;qFAGoF,YAAY,CAAC,CAAC,CAAC,8EAA8E,CAAC,CAAC,CAAC,EAAE;;sIAEjD;qBACzH;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolDeps } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prompt: turn an existing NestJS customer middleware into a Job.
|
|
4
|
+
*
|
|
5
|
+
* Given a Nest.js controller that orchestrates Laminar workflows (login →
|
|
6
|
+
* lookup → create, with header munging and error mapping), this prompt walks
|
|
7
|
+
* the agent through mapping that endpoint into a structured JobDefinition step
|
|
8
|
+
* graph and registering it with register_job.
|
|
9
|
+
*/
|
|
10
|
+
export declare function register({ server }: ToolDeps): void;
|
|
11
|
+
//# sourceMappingURL=nestjs-to-job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nestjs-to-job.d.ts","sourceRoot":"","sources":["../../src/prompts/nestjs-to-job.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,QAwG5C"}
|