@mcpmesh/sdk 2.1.0 → 2.2.4
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/dist/__tests__/jobs.spec.d.ts +2 -0
- package/dist/__tests__/jobs.spec.d.ts.map +1 -0
- package/dist/__tests__/jobs.spec.js +445 -0
- package/dist/__tests__/jobs.spec.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +221 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +363 -0
- package/dist/jobs.js.map +1 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/jobs.d.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public `mesh.jobs` namespace — convenience helpers for the MeshJob
|
|
3
|
+
* event-injection primitive (Phase 1, MeshJob substrate; event-channel
|
|
4
|
+
* extension landed in v2.2).
|
|
5
|
+
*
|
|
6
|
+
* The primary surfaces are:
|
|
7
|
+
*
|
|
8
|
+
* - {@link postEvent} — fire-and-forget helper to push an event into a
|
|
9
|
+
* running job by id, without holding a `JobProxy` reference. Intended
|
|
10
|
+
* for MCP tool bodies that receive a `jobId` in their request payload
|
|
11
|
+
* (e.g. a "submit_user_input" tool exposed by an orchestrator agent).
|
|
12
|
+
*
|
|
13
|
+
* - {@link JobNotFoundError} / {@link JobTerminalError} — typed `Error`
|
|
14
|
+
* subclasses translated from the Rust core's `JobError` variants. The
|
|
15
|
+
* napi binding surfaces all `JobError` variants as a plain `Error`
|
|
16
|
+
* today (see `src/runtime/core/src/jobs_napi.rs::job_error_to_napi`),
|
|
17
|
+
* so we re-classify on the TypeScript side via stable
|
|
18
|
+
* error-message substrings ("job is terminal" / "job not found").
|
|
19
|
+
*
|
|
20
|
+
* The `JobController` / `JobProxy` napi-rs classes from `@mcpmesh/core`
|
|
21
|
+
* already expose `recvEvent` / `sendEvent` methods directly — application
|
|
22
|
+
* code calls them via the `MeshJob`-typed parameter the framework
|
|
23
|
+
* injects. This module just adds the helper + error classes around that
|
|
24
|
+
* surface, mirroring Python's `mesh.jobs.post_event` API one-for-one.
|
|
25
|
+
*/
|
|
26
|
+
import { JobProxy } from "@mcpmesh/core";
|
|
27
|
+
/**
|
|
28
|
+
* Event posted into a running job's event log. Matches the OpenAPI
|
|
29
|
+
* `JobEvent` schema field-for-field (and the Rust `JobEvent` /
|
|
30
|
+
* Python `job_event_to_pydict` shape). Returned by `JobController.recvEvent`.
|
|
31
|
+
*/
|
|
32
|
+
export interface JobEvent {
|
|
33
|
+
/** Server-assigned job UUID this event belongs to. */
|
|
34
|
+
job_id: string;
|
|
35
|
+
/** Per-job monotonic sequence number assigned by the registry. */
|
|
36
|
+
seq: number;
|
|
37
|
+
/** User-supplied event type tag (e.g. "signal", "user_input"). */
|
|
38
|
+
type: string;
|
|
39
|
+
/** Arbitrary JSON-shaped payload carried with the event (or `null`). */
|
|
40
|
+
payload: unknown;
|
|
41
|
+
/** W3C trace context propagated by the poster (or `null`). */
|
|
42
|
+
trace_context: unknown;
|
|
43
|
+
/** Identifier of the agent that posted the event (or `null`). */
|
|
44
|
+
posted_by: string | null;
|
|
45
|
+
/** Unix epoch seconds at which the registry created the row. */
|
|
46
|
+
created_at: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Receipt returned by `JobProxy.sendEvent` / `postEvent`. Matches the
|
|
50
|
+
* OpenAPI `JobEventPostResponse` schema field-for-field.
|
|
51
|
+
*/
|
|
52
|
+
export interface JobEventReceipt {
|
|
53
|
+
/** Server-assigned job UUID the event was posted into. */
|
|
54
|
+
job_id: string;
|
|
55
|
+
/** Per-job monotonic sequence number assigned by the registry. */
|
|
56
|
+
seq: number;
|
|
57
|
+
/** Unix epoch seconds at which the registry created the row. */
|
|
58
|
+
created_at: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The targeted job does not exist (or has been swept) in the registry.
|
|
62
|
+
*
|
|
63
|
+
* Translated from the Rust `JobError::Other(BackendError::NotFound)`
|
|
64
|
+
* path (`GET/POST /jobs/{id}/events` → HTTP 404).
|
|
65
|
+
*/
|
|
66
|
+
export declare class JobNotFoundError extends Error {
|
|
67
|
+
readonly name = "JobNotFoundError";
|
|
68
|
+
constructor(message: string);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The targeted job is in a terminal state (completed / failed /
|
|
72
|
+
* cancelled) and no longer accepts events.
|
|
73
|
+
*
|
|
74
|
+
* Translated from the Rust `JobError::JobTerminal` variant — the
|
|
75
|
+
* registry returns HTTP 409 once the job row is terminal and the Rust
|
|
76
|
+
* layer maps that to `JobTerminal`.
|
|
77
|
+
*/
|
|
78
|
+
export declare class JobTerminalError extends Error {
|
|
79
|
+
readonly name = "JobTerminalError";
|
|
80
|
+
constructor(message: string);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Re-classify a generic `Error` raised by the napi layer into one of the
|
|
84
|
+
* typed subclasses, if the message matches. Returns the original error
|
|
85
|
+
* (or a typed clone) — callers should `throw` the returned value.
|
|
86
|
+
*
|
|
87
|
+
* Exported so tests can exercise the substring contract without a real
|
|
88
|
+
* napi failure path.
|
|
89
|
+
*/
|
|
90
|
+
export declare function translateJobError(err: unknown): unknown;
|
|
91
|
+
/**
|
|
92
|
+
* Return a process-cached `JobProxy` for the given
|
|
93
|
+
* `(registryUrl, jobId)` pair, constructing one on first miss.
|
|
94
|
+
*
|
|
95
|
+
* Cache is a bounded LRU: hits bump the entry to the most-recent end of
|
|
96
|
+
* the insertion-order map, misses on a full cache evict the
|
|
97
|
+
* least-recent entry before inserting. Exported only for tests; not
|
|
98
|
+
* part of the public API.
|
|
99
|
+
*/
|
|
100
|
+
export declare function _getOrCreateProxy(registryUrl: string, jobId: string): JobProxy;
|
|
101
|
+
/**
|
|
102
|
+
* Clear the JobProxy cache. Exposed for tests — not part of the public
|
|
103
|
+
* API. Equivalent to dropping all entries; the underlying napi handles
|
|
104
|
+
* are released when JS GC runs.
|
|
105
|
+
*/
|
|
106
|
+
export declare function _clearProxyCache(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Post an event to a running job by ID.
|
|
109
|
+
*
|
|
110
|
+
* Convenience helper for tool bodies that hold a `jobId` (e.g. from a
|
|
111
|
+
* request body, a token lookup, or a stashed reference) but do NOT
|
|
112
|
+
* have a `JobProxy` reference in scope. Constructs (or reuses, via the
|
|
113
|
+
* LRU cache) a `JobProxy` bound to the current agent's registry URL
|
|
114
|
+
* and forwards the call.
|
|
115
|
+
*
|
|
116
|
+
* Mirrors Python's `mesh.jobs.post_event` API one-for-one.
|
|
117
|
+
*
|
|
118
|
+
* @param jobId - Target job's server-assigned id.
|
|
119
|
+
* @param eventType - Event type tag (e.g. `"extend_deadline"`,
|
|
120
|
+
* `"user_input"`, or any user-defined string). The running handler
|
|
121
|
+
* can filter via `await job.recvEvent(["..."])`.
|
|
122
|
+
* @param payload - Optional JSON-serializable payload carried with the
|
|
123
|
+
* event. `undefined`/`null` is normalized to an empty object before
|
|
124
|
+
* forwarding — the Rust layer accepts either.
|
|
125
|
+
* @returns Receipt `{ job_id, seq, created_at }`. `seq` is the
|
|
126
|
+
* server-assigned sequence number useful for stitching follow-up
|
|
127
|
+
* `recvEvent` calls.
|
|
128
|
+
*
|
|
129
|
+
* @throws {@link JobNotFoundError} If the registry doesn't know the
|
|
130
|
+
* job (sweep already removed it, or wrong id).
|
|
131
|
+
* @throws {@link JobTerminalError} If the job has already reached a
|
|
132
|
+
* terminal state — no more events accepted.
|
|
133
|
+
* @throws Error For transport errors (registry unreachable, 5xx after
|
|
134
|
+
* retries, malformed payload, etc.) — the underlying error message
|
|
135
|
+
* is preserved.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* Inside an MCP tool body that holds a job id:
|
|
139
|
+
* ```ts
|
|
140
|
+
* agent.addTool({
|
|
141
|
+
* name: "submit_user_input",
|
|
142
|
+
* capability: "submit_user_input",
|
|
143
|
+
* parameters: z.object({ jobId: z.string(), text: z.string() }),
|
|
144
|
+
* execute: async ({ jobId, text }) => {
|
|
145
|
+
* const receipt = await mesh.jobs.postEvent(
|
|
146
|
+
* jobId,
|
|
147
|
+
* "user_input",
|
|
148
|
+
* { text },
|
|
149
|
+
* );
|
|
150
|
+
* return { posted_seq: receipt.seq };
|
|
151
|
+
* },
|
|
152
|
+
* });
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export declare function postEvent(jobId: string, eventType: string, payload?: unknown): Promise<JobEventReceipt>;
|
|
156
|
+
/**
|
|
157
|
+
* Options for {@link subscribeEvents}. All fields are optional —
|
|
158
|
+
* defaults match Python's `mesh.jobs.subscribe_events` keyword args.
|
|
159
|
+
*/
|
|
160
|
+
export interface SubscribeEventsOptions {
|
|
161
|
+
/**
|
|
162
|
+
* Optional event-type filter applied server-side. Only events whose
|
|
163
|
+
* `type` matches one of these is yielded. Omit for all types.
|
|
164
|
+
*/
|
|
165
|
+
types?: string[];
|
|
166
|
+
/**
|
|
167
|
+
* Initial cursor (default `0` ≡ from the beginning of the event log).
|
|
168
|
+
* Pass a higher value to skip historical events. Accepts both
|
|
169
|
+
* `number` and `bigint` for callers stitching from an `i64`-sourced
|
|
170
|
+
* cursor.
|
|
171
|
+
*/
|
|
172
|
+
after?: number | bigint;
|
|
173
|
+
/**
|
|
174
|
+
* Long-poll wait budget per registry call (in seconds). Default `30`.
|
|
175
|
+
* Capped at `60` by the registry. Pass `null` to skip the long-poll
|
|
176
|
+
* entirely (single immediate read; rarely needed — tight-poll callers
|
|
177
|
+
* should pass `0` instead).
|
|
178
|
+
*/
|
|
179
|
+
longPollSecs?: number | null;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Subscribe to events posted to a running job by ID.
|
|
183
|
+
*
|
|
184
|
+
* Long-lived async iterator. Each call manages its own cursor —
|
|
185
|
+
* multiple subscribers can observe the same job's events independently
|
|
186
|
+
* without affecting the producer's `recvEvent` consumption (the
|
|
187
|
+
* producer's cursor is per-controller; this observer's cursor is
|
|
188
|
+
* per-call).
|
|
189
|
+
*
|
|
190
|
+
* The iterator runs indefinitely until the caller breaks out of the
|
|
191
|
+
* `for await` loop or the underlying registry returns
|
|
192
|
+
* {@link JobNotFoundError}. There is no automatic terminal-state
|
|
193
|
+
* detection — use a synthetic event type (e.g. `{ type: "ended" }`)
|
|
194
|
+
* posted by your application to signal iteration end.
|
|
195
|
+
*
|
|
196
|
+
* Mirrors Python's `mesh.jobs.subscribe_events` one-for-one.
|
|
197
|
+
*
|
|
198
|
+
* @param jobId - Target job's server-assigned id.
|
|
199
|
+
* @param options - Optional filter / cursor / long-poll knobs.
|
|
200
|
+
* @yields Event objects: `{ seq, type, payload, trace_context,
|
|
201
|
+
* posted_by, created_at, job_id }`.
|
|
202
|
+
*
|
|
203
|
+
* @throws {@link JobNotFoundError} If the job has been reaped from the
|
|
204
|
+
* registry (404 on the `GET /jobs/{id}/events` endpoint).
|
|
205
|
+
* @throws Error For transport errors (registry unreachable, 5xx after
|
|
206
|
+
* retries, malformed payload, etc.) — the underlying error message
|
|
207
|
+
* is preserved.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* Mirror events from a running job into a downstream system:
|
|
211
|
+
* ```ts
|
|
212
|
+
* for await (const event of mesh.jobs.subscribeEvents(jobId, {
|
|
213
|
+
* types: ["progress", "result"],
|
|
214
|
+
* })) {
|
|
215
|
+
* await downstream.publish(event);
|
|
216
|
+
* if (event.type === "result") break; // caller-defined termination
|
|
217
|
+
* }
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
export declare function subscribeEvents(jobId: string, options?: SubscribeEventsOptions): AsyncGenerator<JobEvent, void, unknown>;
|
|
221
|
+
//# sourceMappingURL=jobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,aAAa,EAAE,OAAO,CAAC;IACvB,iEAAiE;IACjE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;CACpB;AAoBD;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,sBAAsB;gBACvB,OAAO,EAAE,MAAM;CAG5B;AAED;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,sBAAsB;gBACvB,OAAO,EAAE,MAAM;CAG5B;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAwBvD;AAmCD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAuB9E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,eAAe,CAAC,CAc1B;AAMD;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAuB,eAAe,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,sBAA2B,GACnC,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAmEzC"}
|
package/dist/jobs.js
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public `mesh.jobs` namespace — convenience helpers for the MeshJob
|
|
3
|
+
* event-injection primitive (Phase 1, MeshJob substrate; event-channel
|
|
4
|
+
* extension landed in v2.2).
|
|
5
|
+
*
|
|
6
|
+
* The primary surfaces are:
|
|
7
|
+
*
|
|
8
|
+
* - {@link postEvent} — fire-and-forget helper to push an event into a
|
|
9
|
+
* running job by id, without holding a `JobProxy` reference. Intended
|
|
10
|
+
* for MCP tool bodies that receive a `jobId` in their request payload
|
|
11
|
+
* (e.g. a "submit_user_input" tool exposed by an orchestrator agent).
|
|
12
|
+
*
|
|
13
|
+
* - {@link JobNotFoundError} / {@link JobTerminalError} — typed `Error`
|
|
14
|
+
* subclasses translated from the Rust core's `JobError` variants. The
|
|
15
|
+
* napi binding surfaces all `JobError` variants as a plain `Error`
|
|
16
|
+
* today (see `src/runtime/core/src/jobs_napi.rs::job_error_to_napi`),
|
|
17
|
+
* so we re-classify on the TypeScript side via stable
|
|
18
|
+
* error-message substrings ("job is terminal" / "job not found").
|
|
19
|
+
*
|
|
20
|
+
* The `JobController` / `JobProxy` napi-rs classes from `@mcpmesh/core`
|
|
21
|
+
* already expose `recvEvent` / `sendEvent` methods directly — application
|
|
22
|
+
* code calls them via the `MeshJob`-typed parameter the framework
|
|
23
|
+
* injects. This module just adds the helper + error classes around that
|
|
24
|
+
* surface, mirroring Python's `mesh.jobs.post_event` API one-for-one.
|
|
25
|
+
*/
|
|
26
|
+
import { JobProxy } from "@mcpmesh/core";
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Typed error classes
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
//
|
|
31
|
+
// The Rust core's `JobError::Other(BackendError::NotFound)` and
|
|
32
|
+
// `JobError::JobTerminal` variants currently surface as plain `Error` from
|
|
33
|
+
// the napi layer (see `src/runtime/core/src/jobs_napi.rs::job_error_to_napi`).
|
|
34
|
+
// Until the napi binding switches to a custom exception type, we
|
|
35
|
+
// re-classify on the TypeScript side via stable substrings emitted by the
|
|
36
|
+
// NAPI wrapper's explicit error remap in
|
|
37
|
+
// `src/runtime/core/src/jobs_napi.rs` (`job_error_to_napi` at lines
|
|
38
|
+
// 85-102, specifically the `JobTerminal` arm at 97-99). The wrapper
|
|
39
|
+
// deliberately remaps `JobError::Display` to a stable SDK-facing format
|
|
40
|
+
// — do NOT collapse this remap thinking it just passes core's Display
|
|
41
|
+
// through; the substring contract here depends on it. Both classes
|
|
42
|
+
// derive from `Error` so existing `catch (Error)` handlers continue to
|
|
43
|
+
// catch them.
|
|
44
|
+
/**
|
|
45
|
+
* The targeted job does not exist (or has been swept) in the registry.
|
|
46
|
+
*
|
|
47
|
+
* Translated from the Rust `JobError::Other(BackendError::NotFound)`
|
|
48
|
+
* path (`GET/POST /jobs/{id}/events` → HTTP 404).
|
|
49
|
+
*/
|
|
50
|
+
export class JobNotFoundError extends Error {
|
|
51
|
+
name = "JobNotFoundError";
|
|
52
|
+
constructor(message) {
|
|
53
|
+
super(message);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The targeted job is in a terminal state (completed / failed /
|
|
58
|
+
* cancelled) and no longer accepts events.
|
|
59
|
+
*
|
|
60
|
+
* Translated from the Rust `JobError::JobTerminal` variant — the
|
|
61
|
+
* registry returns HTTP 409 once the job row is terminal and the Rust
|
|
62
|
+
* layer maps that to `JobTerminal`.
|
|
63
|
+
*/
|
|
64
|
+
export class JobTerminalError extends Error {
|
|
65
|
+
name = "JobTerminalError";
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Re-classify a generic `Error` raised by the napi layer into one of the
|
|
72
|
+
* typed subclasses, if the message matches. Returns the original error
|
|
73
|
+
* (or a typed clone) — callers should `throw` the returned value.
|
|
74
|
+
*
|
|
75
|
+
* Exported so tests can exercise the substring contract without a real
|
|
76
|
+
* napi failure path.
|
|
77
|
+
*/
|
|
78
|
+
export function translateJobError(err) {
|
|
79
|
+
if (!(err instanceof Error) ||
|
|
80
|
+
err instanceof JobNotFoundError ||
|
|
81
|
+
err instanceof JobTerminalError) {
|
|
82
|
+
return err;
|
|
83
|
+
}
|
|
84
|
+
const msg = err.message ?? "";
|
|
85
|
+
const msgLower = msg.toLowerCase();
|
|
86
|
+
// Order matters: "job is terminal" is the JobTerminal variant's Display
|
|
87
|
+
// prefix (see jobs_napi.rs::job_error_to_napi); "job not found" is
|
|
88
|
+
// BackendError::NotFound's Display prefix.
|
|
89
|
+
if (msgLower.includes("job is terminal")) {
|
|
90
|
+
const typed = new JobTerminalError(msg);
|
|
91
|
+
typed.cause = err;
|
|
92
|
+
return typed;
|
|
93
|
+
}
|
|
94
|
+
if (msgLower.includes("job not found")) {
|
|
95
|
+
const typed = new JobNotFoundError(msg);
|
|
96
|
+
typed.cause = err;
|
|
97
|
+
return typed;
|
|
98
|
+
}
|
|
99
|
+
return err;
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// JobProxy cache (mirror of Python's `_get_or_create_proxy`)
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
//
|
|
105
|
+
// `postEvent` used to construct a fresh `JobProxy` on every call. Each
|
|
106
|
+
// proxy wraps a Rust `reqwest::Client` with its own connection pool, so a
|
|
107
|
+
// steady-state sender that fires off `postEvent` in a hot loop would
|
|
108
|
+
// force a fresh TCP/TLS handshake against the registry on every call.
|
|
109
|
+
// Cache by `(registryUrl, jobId)` for the process lifetime; the cache
|
|
110
|
+
// key is invalidated naturally when a different registry URL or job id is
|
|
111
|
+
// used.
|
|
112
|
+
//
|
|
113
|
+
// Bounded LRU eviction: long-lived senders that post events to many
|
|
114
|
+
// distinct jobs (e.g. a router fanning out across thousands of jobs) would
|
|
115
|
+
// otherwise grow the cache without bound. `Map` preserves insertion
|
|
116
|
+
// order; deleting + re-inserting on hit and shifting off the first key on
|
|
117
|
+
// overflow gives us O(1) LRU semantics. The Rust `JobProxy` does not
|
|
118
|
+
// expose an explicit `close()` over napi — eviction just drops the Map
|
|
119
|
+
// entry and lets JS GC release the wrapped `reqwest::Client` connection
|
|
120
|
+
// pool when no JS references remain.
|
|
121
|
+
const _PROXY_CACHE_DEFAULT_MAX = 256;
|
|
122
|
+
function proxyCacheMax() {
|
|
123
|
+
const raw = process.env.MCP_MESH_JOBPROXY_CACHE_MAX;
|
|
124
|
+
if (!raw)
|
|
125
|
+
return _PROXY_CACHE_DEFAULT_MAX;
|
|
126
|
+
const value = parseInt(raw, 10);
|
|
127
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
128
|
+
return _PROXY_CACHE_DEFAULT_MAX;
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
const _proxyCache = new Map();
|
|
132
|
+
/**
|
|
133
|
+
* Return a process-cached `JobProxy` for the given
|
|
134
|
+
* `(registryUrl, jobId)` pair, constructing one on first miss.
|
|
135
|
+
*
|
|
136
|
+
* Cache is a bounded LRU: hits bump the entry to the most-recent end of
|
|
137
|
+
* the insertion-order map, misses on a full cache evict the
|
|
138
|
+
* least-recent entry before inserting. Exported only for tests; not
|
|
139
|
+
* part of the public API.
|
|
140
|
+
*/
|
|
141
|
+
export function _getOrCreateProxy(registryUrl, jobId) {
|
|
142
|
+
const key = `${registryUrl} ${jobId}`;
|
|
143
|
+
const existing = _proxyCache.get(key);
|
|
144
|
+
if (existing !== undefined) {
|
|
145
|
+
// Bump to most-recent end of insertion order: delete + re-set.
|
|
146
|
+
_proxyCache.delete(key);
|
|
147
|
+
_proxyCache.set(key, existing);
|
|
148
|
+
return existing;
|
|
149
|
+
}
|
|
150
|
+
const proxy = new JobProxy(jobId, registryUrl);
|
|
151
|
+
const maxSize = proxyCacheMax();
|
|
152
|
+
while (_proxyCache.size >= maxSize) {
|
|
153
|
+
// Evict LRU = first entry in insertion order. The Map iterator yields
|
|
154
|
+
// keys in insertion order; pull the oldest and delete it. Dropping
|
|
155
|
+
// the entry releases our reference to the JobProxy; JS GC reclaims
|
|
156
|
+
// the wrapped reqwest client (and its connection pool) when no other
|
|
157
|
+
// refs exist.
|
|
158
|
+
const oldest = _proxyCache.keys().next().value;
|
|
159
|
+
if (oldest === undefined)
|
|
160
|
+
break;
|
|
161
|
+
_proxyCache.delete(oldest);
|
|
162
|
+
}
|
|
163
|
+
_proxyCache.set(key, proxy);
|
|
164
|
+
return proxy;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Clear the JobProxy cache. Exposed for tests — not part of the public
|
|
168
|
+
* API. Equivalent to dropping all entries; the underlying napi handles
|
|
169
|
+
* are released when JS GC runs.
|
|
170
|
+
*/
|
|
171
|
+
export function _clearProxyCache() {
|
|
172
|
+
_proxyCache.clear();
|
|
173
|
+
}
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// postEvent convenience helper
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
/**
|
|
178
|
+
* Discover the registry base URL the running agent is bound to.
|
|
179
|
+
*
|
|
180
|
+
* Mirrors Python's `mesh.jobs._resolve_registry_url`: the canonical
|
|
181
|
+
* source is the `MCP_MESH_REGISTRY_URL` environment variable. The
|
|
182
|
+
* configuration pipeline writes this on agent startup and every
|
|
183
|
+
* job-substrate code path reads it.
|
|
184
|
+
*
|
|
185
|
+
* @throws Error if the variable isn't set — the caller can't post an
|
|
186
|
+
* event without knowing which registry to target.
|
|
187
|
+
*/
|
|
188
|
+
function resolveRegistryUrl() {
|
|
189
|
+
const url = process.env.MCP_MESH_REGISTRY_URL;
|
|
190
|
+
if (!url) {
|
|
191
|
+
throw new Error("mesh.jobs.postEvent: MCP_MESH_REGISTRY_URL is not set; " +
|
|
192
|
+
"cannot resolve registry base URL. Ensure the calling " +
|
|
193
|
+
"process is running inside a mesh agent.");
|
|
194
|
+
}
|
|
195
|
+
return url;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Post an event to a running job by ID.
|
|
199
|
+
*
|
|
200
|
+
* Convenience helper for tool bodies that hold a `jobId` (e.g. from a
|
|
201
|
+
* request body, a token lookup, or a stashed reference) but do NOT
|
|
202
|
+
* have a `JobProxy` reference in scope. Constructs (or reuses, via the
|
|
203
|
+
* LRU cache) a `JobProxy` bound to the current agent's registry URL
|
|
204
|
+
* and forwards the call.
|
|
205
|
+
*
|
|
206
|
+
* Mirrors Python's `mesh.jobs.post_event` API one-for-one.
|
|
207
|
+
*
|
|
208
|
+
* @param jobId - Target job's server-assigned id.
|
|
209
|
+
* @param eventType - Event type tag (e.g. `"extend_deadline"`,
|
|
210
|
+
* `"user_input"`, or any user-defined string). The running handler
|
|
211
|
+
* can filter via `await job.recvEvent(["..."])`.
|
|
212
|
+
* @param payload - Optional JSON-serializable payload carried with the
|
|
213
|
+
* event. `undefined`/`null` is normalized to an empty object before
|
|
214
|
+
* forwarding — the Rust layer accepts either.
|
|
215
|
+
* @returns Receipt `{ job_id, seq, created_at }`. `seq` is the
|
|
216
|
+
* server-assigned sequence number useful for stitching follow-up
|
|
217
|
+
* `recvEvent` calls.
|
|
218
|
+
*
|
|
219
|
+
* @throws {@link JobNotFoundError} If the registry doesn't know the
|
|
220
|
+
* job (sweep already removed it, or wrong id).
|
|
221
|
+
* @throws {@link JobTerminalError} If the job has already reached a
|
|
222
|
+
* terminal state — no more events accepted.
|
|
223
|
+
* @throws Error For transport errors (registry unreachable, 5xx after
|
|
224
|
+
* retries, malformed payload, etc.) — the underlying error message
|
|
225
|
+
* is preserved.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* Inside an MCP tool body that holds a job id:
|
|
229
|
+
* ```ts
|
|
230
|
+
* agent.addTool({
|
|
231
|
+
* name: "submit_user_input",
|
|
232
|
+
* capability: "submit_user_input",
|
|
233
|
+
* parameters: z.object({ jobId: z.string(), text: z.string() }),
|
|
234
|
+
* execute: async ({ jobId, text }) => {
|
|
235
|
+
* const receipt = await mesh.jobs.postEvent(
|
|
236
|
+
* jobId,
|
|
237
|
+
* "user_input",
|
|
238
|
+
* { text },
|
|
239
|
+
* );
|
|
240
|
+
* return { posted_seq: receipt.seq };
|
|
241
|
+
* },
|
|
242
|
+
* });
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
export async function postEvent(jobId, eventType, payload) {
|
|
246
|
+
const registryUrl = resolveRegistryUrl();
|
|
247
|
+
const proxy = _getOrCreateProxy(registryUrl, jobId);
|
|
248
|
+
const safePayload = payload !== undefined && payload !== null ? payload : {};
|
|
249
|
+
try {
|
|
250
|
+
const receipt = (await proxy.sendEvent(eventType, safePayload));
|
|
251
|
+
return receipt;
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
const translated = translateJobError(err);
|
|
255
|
+
if (translated !== err) {
|
|
256
|
+
throw translated;
|
|
257
|
+
}
|
|
258
|
+
throw err;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Subscribe to events posted to a running job by ID.
|
|
263
|
+
*
|
|
264
|
+
* Long-lived async iterator. Each call manages its own cursor —
|
|
265
|
+
* multiple subscribers can observe the same job's events independently
|
|
266
|
+
* without affecting the producer's `recvEvent` consumption (the
|
|
267
|
+
* producer's cursor is per-controller; this observer's cursor is
|
|
268
|
+
* per-call).
|
|
269
|
+
*
|
|
270
|
+
* The iterator runs indefinitely until the caller breaks out of the
|
|
271
|
+
* `for await` loop or the underlying registry returns
|
|
272
|
+
* {@link JobNotFoundError}. There is no automatic terminal-state
|
|
273
|
+
* detection — use a synthetic event type (e.g. `{ type: "ended" }`)
|
|
274
|
+
* posted by your application to signal iteration end.
|
|
275
|
+
*
|
|
276
|
+
* Mirrors Python's `mesh.jobs.subscribe_events` one-for-one.
|
|
277
|
+
*
|
|
278
|
+
* @param jobId - Target job's server-assigned id.
|
|
279
|
+
* @param options - Optional filter / cursor / long-poll knobs.
|
|
280
|
+
* @yields Event objects: `{ seq, type, payload, trace_context,
|
|
281
|
+
* posted_by, created_at, job_id }`.
|
|
282
|
+
*
|
|
283
|
+
* @throws {@link JobNotFoundError} If the job has been reaped from the
|
|
284
|
+
* registry (404 on the `GET /jobs/{id}/events` endpoint).
|
|
285
|
+
* @throws Error For transport errors (registry unreachable, 5xx after
|
|
286
|
+
* retries, malformed payload, etc.) — the underlying error message
|
|
287
|
+
* is preserved.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* Mirror events from a running job into a downstream system:
|
|
291
|
+
* ```ts
|
|
292
|
+
* for await (const event of mesh.jobs.subscribeEvents(jobId, {
|
|
293
|
+
* types: ["progress", "result"],
|
|
294
|
+
* })) {
|
|
295
|
+
* await downstream.publish(event);
|
|
296
|
+
* if (event.type === "result") break; // caller-defined termination
|
|
297
|
+
* }
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
export async function* subscribeEvents(jobId, options = {}) {
|
|
301
|
+
const { types, after = 0, longPollSecs = 30 } = options;
|
|
302
|
+
const registryUrl = resolveRegistryUrl();
|
|
303
|
+
const proxy = _getOrCreateProxy(registryUrl, jobId);
|
|
304
|
+
// Cursor as `number` because the napi binding types `after` as
|
|
305
|
+
// `number` (i64 → JS Number). Accept `bigint` in the input options
|
|
306
|
+
// for callers stitching from another i64 source, but coerce down to
|
|
307
|
+
// `number` for the binding boundary — guarding the overflow case so
|
|
308
|
+
// an out-of-range i64 cursor surfaces as an explicit RangeError
|
|
309
|
+
// rather than silently truncating.
|
|
310
|
+
let cursor;
|
|
311
|
+
if (typeof after === "bigint") {
|
|
312
|
+
if (after > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
313
|
+
throw new RangeError(`subscribeEvents: 'after' cursor exceeds Number.MAX_SAFE_INTEGER (${Number.MAX_SAFE_INTEGER}); per-job seq overflowed JS Number range. Got: ${after}`);
|
|
314
|
+
}
|
|
315
|
+
cursor = Number(after);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
cursor = after ?? 0;
|
|
319
|
+
}
|
|
320
|
+
// The binding type signature is `number | null | undefined`; the
|
|
321
|
+
// Python sibling accepts `None` for "single immediate read", and we
|
|
322
|
+
// forward that through verbatim.
|
|
323
|
+
const wait = longPollSecs;
|
|
324
|
+
// eslint-disable-next-line no-constant-condition
|
|
325
|
+
while (true) {
|
|
326
|
+
let result;
|
|
327
|
+
try {
|
|
328
|
+
result = (await proxy.listEvents(cursor, types, wait));
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
const translated = translateJobError(err);
|
|
332
|
+
if (translated !== err) {
|
|
333
|
+
throw translated;
|
|
334
|
+
}
|
|
335
|
+
throw err;
|
|
336
|
+
}
|
|
337
|
+
const { events, nextAfter } = result;
|
|
338
|
+
for (const event of events) {
|
|
339
|
+
const seq = event.seq;
|
|
340
|
+
// Reject booleans explicitly: `typeof true === "boolean"` but
|
|
341
|
+
// JS often widens bool↔number; the registry contract is integer
|
|
342
|
+
// seqs, so a bool here is a wire-level malformed payload.
|
|
343
|
+
if (typeof seq === "boolean") {
|
|
344
|
+
throw new Error(`subscribeEvents: registry returned event with boolean 'seq': ${JSON.stringify(event)}`);
|
|
345
|
+
}
|
|
346
|
+
if (typeof seq !== "number" && typeof seq !== "bigint") {
|
|
347
|
+
throw new Error(`subscribeEvents: registry returned event without integer 'seq': ${JSON.stringify(event)}`);
|
|
348
|
+
}
|
|
349
|
+
const seqNum = typeof seq === "bigint" ? Number(seq) : seq;
|
|
350
|
+
if (seqNum > cursor)
|
|
351
|
+
cursor = seqNum;
|
|
352
|
+
// listEvents returns ascending-seq; cursor advance before yield
|
|
353
|
+
// ensures correctness across consumer cancellation.
|
|
354
|
+
yield event;
|
|
355
|
+
}
|
|
356
|
+
// Empty pages (or pages filtered by `types` server-side) still
|
|
357
|
+
// advance the cursor via the registry-supplied watermark, so
|
|
358
|
+
// subsequent polls don't re-scan the same filtered range.
|
|
359
|
+
if (nextAfter > cursor)
|
|
360
|
+
cursor = nextAfter;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=jobs.js.map
|
package/dist/jobs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -97,6 +97,18 @@ export interface MeshJob {
|
|
|
97
97
|
updateProgress?(progress: number, message?: string): Promise<void>;
|
|
98
98
|
complete?(result: unknown): Promise<void>;
|
|
99
99
|
fail?(error: string): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Wait for the next event posted into this job's event log.
|
|
102
|
+
*
|
|
103
|
+
* Returns the event object on arrival, `null` on timeout. Cursor is
|
|
104
|
+
* per-controller-instance (shared across `clone`s); a fresh
|
|
105
|
+
* controller for the same `jobId` replays from seq=0.
|
|
106
|
+
*
|
|
107
|
+
* Mirrors Python's `MeshJob.recv_event` (event-channel extension that
|
|
108
|
+
* shipped with v2.2 via PR #1041). Throws on `JobNotFound` /
|
|
109
|
+
* transport-layer failures; `timeoutSecs` rejects NaN/Infinity/negative.
|
|
110
|
+
*/
|
|
111
|
+
recvEvent?(types?: string[], timeoutSecs?: number): Promise<import("./jobs.js").JobEvent | null>;
|
|
100
112
|
submit?(payload?: Record<string, unknown>, options?: {
|
|
101
113
|
maxDuration?: number;
|
|
102
114
|
maxRetries?: number;
|
|
@@ -106,6 +118,15 @@ export interface MeshJob {
|
|
|
106
118
|
wait?(timeoutSecs?: number): Promise<unknown>;
|
|
107
119
|
status?(): Promise<Record<string, unknown>>;
|
|
108
120
|
cancel?(reason?: string): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Post an event into this job's event log. The running handler
|
|
123
|
+
* (inside the `task: true` job) will see it on its next `recvEvent`
|
|
124
|
+
* call — or wake immediately if it's currently long-polling.
|
|
125
|
+
*
|
|
126
|
+
* Mirrors Python's `MeshJob.send_event`. Throws `JobNotFoundError` /
|
|
127
|
+
* `JobTerminalError` for the corresponding registry error codes.
|
|
128
|
+
*/
|
|
129
|
+
sendEvent?(eventType: string, payload?: unknown): Promise<import("./jobs.js").JobEventReceipt>;
|
|
109
130
|
}
|
|
110
131
|
/**
|
|
111
132
|
* Dependency specification for mesh tool DI.
|