@loomcycle/client 0.11.4 → 0.12.7

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.
@@ -89,6 +89,8 @@ class LoomcycleClient {
89
89
  body.user_tier = opts.userTier;
90
90
  if (opts.userBearer !== undefined)
91
91
  body.user_bearer = opts.userBearer;
92
+ if (opts.userCredentials !== undefined)
93
+ body.user_credentials = opts.userCredentials;
92
94
  yield* this.streamSSE("/v1/runs", body, opts.signal, opts.debug);
93
95
  }
94
96
  /**
@@ -125,6 +127,8 @@ class LoomcycleClient {
125
127
  body.user_tier = opts.userTier;
126
128
  if (opts.userBearer !== undefined)
127
129
  body.user_bearer = opts.userBearer;
130
+ if (opts.userCredentials !== undefined)
131
+ body.user_credentials = opts.userCredentials;
128
132
  yield* this.streamSSE(`/v1/sessions/${encodeURIComponent(opts.sessionId)}/messages`, body, opts.signal, opts.debug);
129
133
  }
130
134
  // ---- Agent metadata ----
@@ -422,6 +426,38 @@ class LoomcycleClient {
422
426
  async mcpServerDef(input, opts) {
423
427
  return (0, fetch_helpers_js_1.postJSON)(this.ctx, "/v1/_mcpserverdef", input, opts);
424
428
  }
429
+ /** Invoke the v1.x RFC E ScheduleDef substrate tool over HTTP.
430
+ * Author + fork + retire scheduled-run definitions at runtime.
431
+ * Mirror of {@link LoomcycleClient.agentDef} for schedules — the
432
+ * primary use case is JobEmber-style "fork a yaml template
433
+ * per-user with their bearer + tier cron" workflows.
434
+ *
435
+ * Operator-admin-only: this endpoint requires the bearer token.
436
+ *
437
+ * Op-discriminated input: `{op: "create" | "fork" | "get" |
438
+ * "list" | "retire", ...}`. Note that ScheduleDef has 5 ops
439
+ * (no separate `promote` — forks auto-promote by default per
440
+ * RFC E's worked example; no `verify` — no content_sha256 in
441
+ * v1.x).
442
+ *
443
+ * Sharp edges (substrate refuses these):
444
+ * - Name colliding with a static cfg.ScheduledRuns entry is
445
+ * refused on `create` (yaml is ground truth; use `fork` to
446
+ * derive a new version).
447
+ * - Fork against a template with `required_credentials` must
448
+ * supply all keys in `user_credentials` — loud-fail at fork
449
+ * time rather than silent ingestion-time failure when the
450
+ * sweeper fires.
451
+ * - Cron syntax is validated server-side; invalid expressions
452
+ * refuse with a parse error.
453
+ *
454
+ * Raises {@link SubstrateToolRefusedError} on tool-level refusals
455
+ * (static-name collision, missing required credential, invalid
456
+ * cron, etc.); {@link InvalidArgumentError} on 400 (malformed
457
+ * JSON); {@link AuthError} on 401. */
458
+ async scheduleDef(input, opts) {
459
+ return (0, fetch_helpers_js_1.postJSON)(this.ctx, "/v1/_scheduledef", input, opts);
460
+ }
425
461
  // ---- v0.10.3 Library v2 enumeration (read-only, merged yaml+substrate) ----
426
462
  /** List every agent the runtime knows about — yaml-static + dynamic
427
463
  * AgentDefs merged into one envelope per name. Each entry carries
@@ -707,6 +743,78 @@ class LoomcycleClient {
707
743
  const path = channelOpPath(channel, opts.scope, opts.userId, "ack");
708
744
  return (0, fetch_helpers_js_1.postJSON)(this.ctx, path, { cursor: opts.cursor }, { signal: opts.signal });
709
745
  }
746
+ // ---- v0.11.5 Channel admin CRUD ----
747
+ //
748
+ // Three bearer-authed ops that mutate the runtime-substrate
749
+ // channel registry. yaml-declared channels are immutable from
750
+ // this surface — the server refuses with HTTP 409 + wire `code`
751
+ // `channel_yaml_immutable`. The TS adapter surfaces that as a
752
+ // {@link LoomcycleError} with status 409.
753
+ /** Create a new runtime-substrate channel. Refuses with HTTP 409
754
+ * when the name matches a yaml-declared channel (code
755
+ * `channel_yaml_immutable`) or an existing runtime channel
756
+ * (code `channel_name_in_use`). */
757
+ async createChannel(opts) {
758
+ const body = { name: opts.name };
759
+ if (opts.description !== undefined)
760
+ body.description = opts.description;
761
+ if (opts.scope !== undefined)
762
+ body.scope = opts.scope;
763
+ if (opts.semantic !== undefined)
764
+ body.semantic = opts.semantic;
765
+ if (opts.default_ttl !== undefined)
766
+ body.default_ttl = opts.default_ttl;
767
+ if (opts.max_messages !== undefined)
768
+ body.max_messages = opts.max_messages;
769
+ if (opts.publisher !== undefined)
770
+ body.publisher = opts.publisher;
771
+ if (opts.period !== undefined)
772
+ body.period = opts.period;
773
+ return (0, fetch_helpers_js_1.postJSON)(this.ctx, "/v1/_channels", body, {
774
+ signal: opts.signal,
775
+ });
776
+ }
777
+ /** Partially update a runtime-substrate channel. Nil-valued fields
778
+ * in `opts` leave the corresponding attribute unchanged. Refuses
779
+ * yaml-declared channels with HTTP 409. */
780
+ async updateChannel(name, opts) {
781
+ const body = {};
782
+ if (opts.description !== undefined)
783
+ body.description = opts.description;
784
+ if (opts.default_ttl !== undefined)
785
+ body.default_ttl = opts.default_ttl;
786
+ if (opts.max_messages !== undefined)
787
+ body.max_messages = opts.max_messages;
788
+ if (opts.semantic !== undefined)
789
+ body.semantic = opts.semantic;
790
+ return (0, fetch_helpers_js_1.patchJSON)(this.ctx, `/v1/_channels/${encodeURIComponent(name)}`, body, { signal: opts.signal });
791
+ }
792
+ /** Delete a runtime-substrate channel + cascade its persisted
793
+ * messages + cursors. yaml-declared channels refuse with HTTP 409.
794
+ * Idempotent: deleting a non-existent runtime channel returns a
795
+ * {@link NotFoundError} so the caller can distinguish that case. */
796
+ async deleteChannel(name, opts) {
797
+ return (0, fetch_helpers_js_1.deleteRequest)(this.ctx, `/v1/_channels/${encodeURIComponent(name)}`, opts);
798
+ }
799
+ // ---- v0.11.5 Memory entry admin CRUD ----
800
+ /** Idempotently upsert one memory entry by full (scope, scope_id,
801
+ * key) identifier. PUT semantics — re-writes overwrite the value.
802
+ * Optional embed flag triggers a synchronous embed via the
803
+ * operator-configured embedder. */
804
+ async setMemoryEntry(scope, scopeID, key, opts) {
805
+ const body = { value: opts.value };
806
+ if (opts.embed !== undefined)
807
+ body.embed = opts.embed;
808
+ if (opts.ttl_seconds !== undefined)
809
+ body.ttl_seconds = opts.ttl_seconds;
810
+ return (0, fetch_helpers_js_1.putJSON)(this.ctx, `/v1/_memory/scopes/${encodeURIComponent(scope)}/${encodeURIComponent(scopeID)}/keys/${encodeURIComponent(key)}`, body, { signal: opts.signal });
811
+ }
812
+ /** Delete one memory entry by (scope, scope_id, key). Idempotent:
813
+ * deleting a missing row is a non-error per the in-band Memory
814
+ * tool's semantics — both surfaces return 204. */
815
+ async deleteMemoryEntry(scope, scopeID, key, opts) {
816
+ return (0, fetch_helpers_js_1.deleteRequest)(this.ctx, `/v1/_memory/scopes/${encodeURIComponent(scope)}/${encodeURIComponent(scopeID)}/keys/${encodeURIComponent(key)}`, opts);
817
+ }
710
818
  /** Subscribe to run state transitions for one user_id via SSE.
711
819
  * Yields one `{ kind: "open", ... }` item first (confirms the
712
820
  * connection is live), then one `{ kind: "event", ... }` per
@@ -14,6 +14,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.authHeaders = authHeaders;
15
15
  exports.jsonFetch = jsonFetch;
16
16
  exports.postJSON = postJSON;
17
+ exports.putJSON = putJSON;
18
+ exports.patchJSON = patchJSON;
17
19
  exports.deleteRequest = deleteRequest;
18
20
  exports.raiseFromResponse = raiseFromResponse;
19
21
  const errors_js_1 = require("./errors.js");
@@ -65,6 +67,51 @@ async function postJSON(ctx, path, body, opts) {
65
67
  return null;
66
68
  return (await resp.json());
67
69
  }
70
+ /** putJSON sends a JSON-encoded body via PUT and unwraps the
71
+ * response. Idempotent — REST-canonical verb for "create or
72
+ * overwrite by full identifier." */
73
+ async function putJSON(ctx, path, body, opts) {
74
+ const headers = authHeaders(ctx);
75
+ let bodyStr;
76
+ if (body !== undefined) {
77
+ headers["Content-Type"] = "application/json";
78
+ bodyStr = JSON.stringify(body);
79
+ }
80
+ const resp = await ctx.fetchImpl(ctx.baseUrl + path, {
81
+ method: "PUT",
82
+ headers,
83
+ body: bodyStr,
84
+ signal: opts?.signal,
85
+ });
86
+ if (!resp.ok) {
87
+ await raiseFromResponse(resp);
88
+ }
89
+ if (resp.status === 204)
90
+ return null;
91
+ return (await resp.json());
92
+ }
93
+ /** patchJSON sends a JSON-encoded body via PATCH and unwraps the
94
+ * response. For partial-update endpoints. */
95
+ async function patchJSON(ctx, path, body, opts) {
96
+ const headers = authHeaders(ctx);
97
+ let bodyStr;
98
+ if (body !== undefined) {
99
+ headers["Content-Type"] = "application/json";
100
+ bodyStr = JSON.stringify(body);
101
+ }
102
+ const resp = await ctx.fetchImpl(ctx.baseUrl + path, {
103
+ method: "PATCH",
104
+ headers,
105
+ body: bodyStr,
106
+ signal: opts?.signal,
107
+ });
108
+ if (!resp.ok) {
109
+ await raiseFromResponse(resp);
110
+ }
111
+ if (resp.status === 204)
112
+ return null;
113
+ return (await resp.json());
114
+ }
68
115
  /** deleteRequest sends a DELETE and tolerates 204/200/404-with-
69
116
  * idempotent-semantics per the loomcycle wire contract. */
70
117
  async function deleteRequest(ctx, path, opts) {
package/dist/cjs/index.js CHANGED
@@ -43,9 +43,11 @@
43
43
  * listRunInterrupts(runId, opts?): Promise<InterruptListResponse>
44
44
  * resolveInterrupt(runId, interruptId, opts): Promise<unknown>
45
45
  *
46
- * // Substrate admin (v0.8.22)
46
+ * // Substrate admin (v0.8.22; mcpServerDef v0.9.x; scheduleDef v1.x)
47
47
  * agentDef(input): Promise<SubstrateToolResponse>
48
48
  * skillDef(input): Promise<SubstrateToolResponse>
49
+ * mcpServerDef(input): Promise<SubstrateToolResponse>
50
+ * scheduleDef(input): Promise<SubstrateToolResponse>
49
51
  *
50
52
  * // Library v2 enumeration (v0.10.3 — yaml+substrate merged)
51
53
  * listLibraryAgents(): Promise<LibraryListResponse<LibraryAgentDefinition>>
package/dist/client.d.ts CHANGED
@@ -23,7 +23,7 @@
23
23
  * via fetch-helpers.ts:raiseFromResponse — see README.md for the
24
24
  * full mapping table.
25
25
  */
26
- import type { Agent, AgentEvent, AgentStatus, CancelAgentResult, ClientOptions, ContinueOptions, CreateSnapshotOptions, HealthResponse, Hook, InterruptListResponse, InterruptStatus, AckChannelOptions, ChannelAckResult, ChannelPeekResult, ChannelPublishResult, ChannelSubscribeResult, ListChannelsResponse, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, LibraryAgentDefinition, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, ListUsersResponse, LLMChatOptions, LLMChatResponse, LLMChatStreamItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, MemoryEntriesResponse, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopesResponse, PauseResult, RegisterHookOptions, RegisterHookResponse, ResolveInterruptOptions, ResumeResult, RunOptions, RunStateStreamItem, RuntimeStateResponse, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotRestoreResponse, StreamUserRunStatesOptions, SubstrateToolInput, SubstrateToolResponse, TranscriptResponse } from "./types.js";
26
+ import type { Agent, AgentEvent, AgentStatus, CancelAgentResult, ClientOptions, ContinueOptions, CreateSnapshotOptions, HealthResponse, Hook, InterruptListResponse, InterruptStatus, AckChannelOptions, ChannelAckResult, ChannelDescriptor, ChannelPeekResult, ChannelPublishResult, ChannelSubscribeResult, CreateChannelOptions, ListChannelsResponse, PeekChannelOptions, PublishChannelOptions, SetMemoryEntryOptions, SetMemoryEntryResponse, SubscribeChannelOptions, UpdateChannelOptions, LibraryAgentDefinition, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, ListUsersResponse, LLMChatOptions, LLMChatResponse, LLMChatStreamItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, MemoryEntriesResponse, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopesResponse, PauseResult, RegisterHookOptions, RegisterHookResponse, ResolveInterruptOptions, ResumeResult, RunOptions, RunStateStreamItem, RuntimeStateResponse, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotRestoreResponse, StreamUserRunStatesOptions, SubstrateToolInput, SubstrateToolResponse, TranscriptResponse } from "./types.js";
27
27
  export declare class LoomcycleClient {
28
28
  private ctx;
29
29
  constructor(opts?: ClientOptions);
@@ -289,6 +289,38 @@ export declare class LoomcycleClient {
289
289
  mcpServerDef(input: SubstrateToolInput, opts?: {
290
290
  signal?: AbortSignal;
291
291
  }): Promise<SubstrateToolResponse>;
292
+ /** Invoke the v1.x RFC E ScheduleDef substrate tool over HTTP.
293
+ * Author + fork + retire scheduled-run definitions at runtime.
294
+ * Mirror of {@link LoomcycleClient.agentDef} for schedules — the
295
+ * primary use case is JobEmber-style "fork a yaml template
296
+ * per-user with their bearer + tier cron" workflows.
297
+ *
298
+ * Operator-admin-only: this endpoint requires the bearer token.
299
+ *
300
+ * Op-discriminated input: `{op: "create" | "fork" | "get" |
301
+ * "list" | "retire", ...}`. Note that ScheduleDef has 5 ops
302
+ * (no separate `promote` — forks auto-promote by default per
303
+ * RFC E's worked example; no `verify` — no content_sha256 in
304
+ * v1.x).
305
+ *
306
+ * Sharp edges (substrate refuses these):
307
+ * - Name colliding with a static cfg.ScheduledRuns entry is
308
+ * refused on `create` (yaml is ground truth; use `fork` to
309
+ * derive a new version).
310
+ * - Fork against a template with `required_credentials` must
311
+ * supply all keys in `user_credentials` — loud-fail at fork
312
+ * time rather than silent ingestion-time failure when the
313
+ * sweeper fires.
314
+ * - Cron syntax is validated server-side; invalid expressions
315
+ * refuse with a parse error.
316
+ *
317
+ * Raises {@link SubstrateToolRefusedError} on tool-level refusals
318
+ * (static-name collision, missing required credential, invalid
319
+ * cron, etc.); {@link InvalidArgumentError} on 400 (malformed
320
+ * JSON); {@link AuthError} on 401. */
321
+ scheduleDef(input: SubstrateToolInput, opts?: {
322
+ signal?: AbortSignal;
323
+ }): Promise<SubstrateToolResponse>;
292
324
  /** List every agent the runtime knows about — yaml-static + dynamic
293
325
  * AgentDefs merged into one envelope per name. Each entry carries
294
326
  * `source: "static-only" | "dynamic-only" | "both"` so callers can
@@ -425,6 +457,33 @@ export declare class LoomcycleClient {
425
457
  * raise a {@link ConflictError} (HTTP 409, code
426
458
  * `channel_cursor_regression`). */
427
459
  ackChannel(channel: string, opts: AckChannelOptions): Promise<ChannelAckResult>;
460
+ /** Create a new runtime-substrate channel. Refuses with HTTP 409
461
+ * when the name matches a yaml-declared channel (code
462
+ * `channel_yaml_immutable`) or an existing runtime channel
463
+ * (code `channel_name_in_use`). */
464
+ createChannel(opts: CreateChannelOptions): Promise<ChannelDescriptor>;
465
+ /** Partially update a runtime-substrate channel. Nil-valued fields
466
+ * in `opts` leave the corresponding attribute unchanged. Refuses
467
+ * yaml-declared channels with HTTP 409. */
468
+ updateChannel(name: string, opts: UpdateChannelOptions): Promise<ChannelDescriptor>;
469
+ /** Delete a runtime-substrate channel + cascade its persisted
470
+ * messages + cursors. yaml-declared channels refuse with HTTP 409.
471
+ * Idempotent: deleting a non-existent runtime channel returns a
472
+ * {@link NotFoundError} so the caller can distinguish that case. */
473
+ deleteChannel(name: string, opts?: {
474
+ signal?: AbortSignal;
475
+ }): Promise<void>;
476
+ /** Idempotently upsert one memory entry by full (scope, scope_id,
477
+ * key) identifier. PUT semantics — re-writes overwrite the value.
478
+ * Optional embed flag triggers a synchronous embed via the
479
+ * operator-configured embedder. */
480
+ setMemoryEntry(scope: string, scopeID: string, key: string, opts: SetMemoryEntryOptions): Promise<SetMemoryEntryResponse>;
481
+ /** Delete one memory entry by (scope, scope_id, key). Idempotent:
482
+ * deleting a missing row is a non-error per the in-band Memory
483
+ * tool's semantics — both surfaces return 204. */
484
+ deleteMemoryEntry(scope: string, scopeID: string, key: string, opts?: {
485
+ signal?: AbortSignal;
486
+ }): Promise<void>;
428
487
  /** Subscribe to run state transitions for one user_id via SSE.
429
488
  * Yields one `{ kind: "open", ... }` item first (confirms the
430
489
  * connection is live), then one `{ kind: "event", ... }` per
package/dist/client.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * via fetch-helpers.ts:raiseFromResponse — see README.md for the
24
24
  * full mapping table.
25
25
  */
26
- import { authHeaders, deleteRequest, jsonFetch, postJSON, raiseFromResponse, } from "./fetch-helpers.js";
26
+ import { authHeaders, deleteRequest, jsonFetch, patchJSON, postJSON, putJSON, raiseFromResponse, } from "./fetch-helpers.js";
27
27
  import { parseSSE } from "./stream.js";
28
28
  export class LoomcycleClient {
29
29
  ctx;
@@ -86,6 +86,8 @@ export class LoomcycleClient {
86
86
  body.user_tier = opts.userTier;
87
87
  if (opts.userBearer !== undefined)
88
88
  body.user_bearer = opts.userBearer;
89
+ if (opts.userCredentials !== undefined)
90
+ body.user_credentials = opts.userCredentials;
89
91
  yield* this.streamSSE("/v1/runs", body, opts.signal, opts.debug);
90
92
  }
91
93
  /**
@@ -122,6 +124,8 @@ export class LoomcycleClient {
122
124
  body.user_tier = opts.userTier;
123
125
  if (opts.userBearer !== undefined)
124
126
  body.user_bearer = opts.userBearer;
127
+ if (opts.userCredentials !== undefined)
128
+ body.user_credentials = opts.userCredentials;
125
129
  yield* this.streamSSE(`/v1/sessions/${encodeURIComponent(opts.sessionId)}/messages`, body, opts.signal, opts.debug);
126
130
  }
127
131
  // ---- Agent metadata ----
@@ -419,6 +423,38 @@ export class LoomcycleClient {
419
423
  async mcpServerDef(input, opts) {
420
424
  return postJSON(this.ctx, "/v1/_mcpserverdef", input, opts);
421
425
  }
426
+ /** Invoke the v1.x RFC E ScheduleDef substrate tool over HTTP.
427
+ * Author + fork + retire scheduled-run definitions at runtime.
428
+ * Mirror of {@link LoomcycleClient.agentDef} for schedules — the
429
+ * primary use case is JobEmber-style "fork a yaml template
430
+ * per-user with their bearer + tier cron" workflows.
431
+ *
432
+ * Operator-admin-only: this endpoint requires the bearer token.
433
+ *
434
+ * Op-discriminated input: `{op: "create" | "fork" | "get" |
435
+ * "list" | "retire", ...}`. Note that ScheduleDef has 5 ops
436
+ * (no separate `promote` — forks auto-promote by default per
437
+ * RFC E's worked example; no `verify` — no content_sha256 in
438
+ * v1.x).
439
+ *
440
+ * Sharp edges (substrate refuses these):
441
+ * - Name colliding with a static cfg.ScheduledRuns entry is
442
+ * refused on `create` (yaml is ground truth; use `fork` to
443
+ * derive a new version).
444
+ * - Fork against a template with `required_credentials` must
445
+ * supply all keys in `user_credentials` — loud-fail at fork
446
+ * time rather than silent ingestion-time failure when the
447
+ * sweeper fires.
448
+ * - Cron syntax is validated server-side; invalid expressions
449
+ * refuse with a parse error.
450
+ *
451
+ * Raises {@link SubstrateToolRefusedError} on tool-level refusals
452
+ * (static-name collision, missing required credential, invalid
453
+ * cron, etc.); {@link InvalidArgumentError} on 400 (malformed
454
+ * JSON); {@link AuthError} on 401. */
455
+ async scheduleDef(input, opts) {
456
+ return postJSON(this.ctx, "/v1/_scheduledef", input, opts);
457
+ }
422
458
  // ---- v0.10.3 Library v2 enumeration (read-only, merged yaml+substrate) ----
423
459
  /** List every agent the runtime knows about — yaml-static + dynamic
424
460
  * AgentDefs merged into one envelope per name. Each entry carries
@@ -704,6 +740,78 @@ export class LoomcycleClient {
704
740
  const path = channelOpPath(channel, opts.scope, opts.userId, "ack");
705
741
  return postJSON(this.ctx, path, { cursor: opts.cursor }, { signal: opts.signal });
706
742
  }
743
+ // ---- v0.11.5 Channel admin CRUD ----
744
+ //
745
+ // Three bearer-authed ops that mutate the runtime-substrate
746
+ // channel registry. yaml-declared channels are immutable from
747
+ // this surface — the server refuses with HTTP 409 + wire `code`
748
+ // `channel_yaml_immutable`. The TS adapter surfaces that as a
749
+ // {@link LoomcycleError} with status 409.
750
+ /** Create a new runtime-substrate channel. Refuses with HTTP 409
751
+ * when the name matches a yaml-declared channel (code
752
+ * `channel_yaml_immutable`) or an existing runtime channel
753
+ * (code `channel_name_in_use`). */
754
+ async createChannel(opts) {
755
+ const body = { name: opts.name };
756
+ if (opts.description !== undefined)
757
+ body.description = opts.description;
758
+ if (opts.scope !== undefined)
759
+ body.scope = opts.scope;
760
+ if (opts.semantic !== undefined)
761
+ body.semantic = opts.semantic;
762
+ if (opts.default_ttl !== undefined)
763
+ body.default_ttl = opts.default_ttl;
764
+ if (opts.max_messages !== undefined)
765
+ body.max_messages = opts.max_messages;
766
+ if (opts.publisher !== undefined)
767
+ body.publisher = opts.publisher;
768
+ if (opts.period !== undefined)
769
+ body.period = opts.period;
770
+ return postJSON(this.ctx, "/v1/_channels", body, {
771
+ signal: opts.signal,
772
+ });
773
+ }
774
+ /** Partially update a runtime-substrate channel. Nil-valued fields
775
+ * in `opts` leave the corresponding attribute unchanged. Refuses
776
+ * yaml-declared channels with HTTP 409. */
777
+ async updateChannel(name, opts) {
778
+ const body = {};
779
+ if (opts.description !== undefined)
780
+ body.description = opts.description;
781
+ if (opts.default_ttl !== undefined)
782
+ body.default_ttl = opts.default_ttl;
783
+ if (opts.max_messages !== undefined)
784
+ body.max_messages = opts.max_messages;
785
+ if (opts.semantic !== undefined)
786
+ body.semantic = opts.semantic;
787
+ return patchJSON(this.ctx, `/v1/_channels/${encodeURIComponent(name)}`, body, { signal: opts.signal });
788
+ }
789
+ /** Delete a runtime-substrate channel + cascade its persisted
790
+ * messages + cursors. yaml-declared channels refuse with HTTP 409.
791
+ * Idempotent: deleting a non-existent runtime channel returns a
792
+ * {@link NotFoundError} so the caller can distinguish that case. */
793
+ async deleteChannel(name, opts) {
794
+ return deleteRequest(this.ctx, `/v1/_channels/${encodeURIComponent(name)}`, opts);
795
+ }
796
+ // ---- v0.11.5 Memory entry admin CRUD ----
797
+ /** Idempotently upsert one memory entry by full (scope, scope_id,
798
+ * key) identifier. PUT semantics — re-writes overwrite the value.
799
+ * Optional embed flag triggers a synchronous embed via the
800
+ * operator-configured embedder. */
801
+ async setMemoryEntry(scope, scopeID, key, opts) {
802
+ const body = { value: opts.value };
803
+ if (opts.embed !== undefined)
804
+ body.embed = opts.embed;
805
+ if (opts.ttl_seconds !== undefined)
806
+ body.ttl_seconds = opts.ttl_seconds;
807
+ return putJSON(this.ctx, `/v1/_memory/scopes/${encodeURIComponent(scope)}/${encodeURIComponent(scopeID)}/keys/${encodeURIComponent(key)}`, body, { signal: opts.signal });
808
+ }
809
+ /** Delete one memory entry by (scope, scope_id, key). Idempotent:
810
+ * deleting a missing row is a non-error per the in-band Memory
811
+ * tool's semantics — both surfaces return 204. */
812
+ async deleteMemoryEntry(scope, scopeID, key, opts) {
813
+ return deleteRequest(this.ctx, `/v1/_memory/scopes/${encodeURIComponent(scope)}/${encodeURIComponent(scopeID)}/keys/${encodeURIComponent(key)}`, opts);
814
+ }
707
815
  /** Subscribe to run state transitions for one user_id via SSE.
708
816
  * Yields one `{ kind: "open", ... }` item first (confirms the
709
817
  * connection is live), then one `{ kind: "event", ... }` per
@@ -43,6 +43,17 @@ export declare function jsonFetch<T>(ctx: _FetchContext, path: string, opts?: {
43
43
  export declare function postJSON<T>(ctx: _FetchContext, path: string, body?: unknown, opts?: {
44
44
  signal?: AbortSignal;
45
45
  }): Promise<T>;
46
+ /** putJSON sends a JSON-encoded body via PUT and unwraps the
47
+ * response. Idempotent — REST-canonical verb for "create or
48
+ * overwrite by full identifier." */
49
+ export declare function putJSON<T>(ctx: _FetchContext, path: string, body?: unknown, opts?: {
50
+ signal?: AbortSignal;
51
+ }): Promise<T>;
52
+ /** patchJSON sends a JSON-encoded body via PATCH and unwraps the
53
+ * response. For partial-update endpoints. */
54
+ export declare function patchJSON<T>(ctx: _FetchContext, path: string, body?: unknown, opts?: {
55
+ signal?: AbortSignal;
56
+ }): Promise<T>;
46
57
  /** deleteRequest sends a DELETE and tolerates 204/200/404-with-
47
58
  * idempotent-semantics per the loomcycle wire contract. */
48
59
  export declare function deleteRequest(ctx: _FetchContext, path: string, opts?: {
@@ -58,6 +58,51 @@ export async function postJSON(ctx, path, body, opts) {
58
58
  return null;
59
59
  return (await resp.json());
60
60
  }
61
+ /** putJSON sends a JSON-encoded body via PUT and unwraps the
62
+ * response. Idempotent — REST-canonical verb for "create or
63
+ * overwrite by full identifier." */
64
+ export async function putJSON(ctx, path, body, opts) {
65
+ const headers = authHeaders(ctx);
66
+ let bodyStr;
67
+ if (body !== undefined) {
68
+ headers["Content-Type"] = "application/json";
69
+ bodyStr = JSON.stringify(body);
70
+ }
71
+ const resp = await ctx.fetchImpl(ctx.baseUrl + path, {
72
+ method: "PUT",
73
+ headers,
74
+ body: bodyStr,
75
+ signal: opts?.signal,
76
+ });
77
+ if (!resp.ok) {
78
+ await raiseFromResponse(resp);
79
+ }
80
+ if (resp.status === 204)
81
+ return null;
82
+ return (await resp.json());
83
+ }
84
+ /** patchJSON sends a JSON-encoded body via PATCH and unwraps the
85
+ * response. For partial-update endpoints. */
86
+ export async function patchJSON(ctx, path, body, opts) {
87
+ const headers = authHeaders(ctx);
88
+ let bodyStr;
89
+ if (body !== undefined) {
90
+ headers["Content-Type"] = "application/json";
91
+ bodyStr = JSON.stringify(body);
92
+ }
93
+ const resp = await ctx.fetchImpl(ctx.baseUrl + path, {
94
+ method: "PATCH",
95
+ headers,
96
+ body: bodyStr,
97
+ signal: opts?.signal,
98
+ });
99
+ if (!resp.ok) {
100
+ await raiseFromResponse(resp);
101
+ }
102
+ if (resp.status === 204)
103
+ return null;
104
+ return (await resp.json());
105
+ }
61
106
  /** deleteRequest sends a DELETE and tolerates 204/200/404-with-
62
107
  * idempotent-semantics per the loomcycle wire contract. */
63
108
  export async function deleteRequest(ctx, path, opts) {
package/dist/index.d.ts CHANGED
@@ -42,9 +42,11 @@
42
42
  * listRunInterrupts(runId, opts?): Promise<InterruptListResponse>
43
43
  * resolveInterrupt(runId, interruptId, opts): Promise<unknown>
44
44
  *
45
- * // Substrate admin (v0.8.22)
45
+ * // Substrate admin (v0.8.22; mcpServerDef v0.9.x; scheduleDef v1.x)
46
46
  * agentDef(input): Promise<SubstrateToolResponse>
47
47
  * skillDef(input): Promise<SubstrateToolResponse>
48
+ * mcpServerDef(input): Promise<SubstrateToolResponse>
49
+ * scheduleDef(input): Promise<SubstrateToolResponse>
48
50
  *
49
51
  * // Library v2 enumeration (v0.10.3 — yaml+substrate merged)
50
52
  * listLibraryAgents(): Promise<LibraryListResponse<LibraryAgentDefinition>>
@@ -76,5 +78,5 @@
76
78
  * See `adapters/ts/README.md` for usage examples.
77
79
  */
78
80
  export { LoomcycleClient } from "./client.js";
79
- export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, PromptContent, PromptSegment, RetryInfo, RunOptions, ToolUse, Usage, Agent, AgentStatus, AgentUsage, CancelAgentResult, ListAgentsResponse, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, PauseResult, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, CreateSnapshotOptions, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotListResponse, SnapshotRestoreResponse, MemoryEntriesResponse, MemoryEntry, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopeIDSummary, MemoryScopeKind, MemoryScopesResponse, InterruptListResponse, InterruptRow, InterruptStatus, ResolveInterruptOptions, Hook, HookFailMode, HookPhase, HookToolCall, HookToolResult, ListHooksResponse, PostHookCall, PostHookResult, PreHookCall, PreHookResult, RegisterHookOptions, RegisterHookResponse, SubstrateToolInput, SubstrateToolResponse, SystemPromptPayload, UserInputPayload, ChannelDescriptor, ListChannelsResponse, RunStateEvent, RunStateStreamClose, RunStateStreamItem, RunStateStreamOpen, StreamUserRunStatesOptions, AckChannelOptions, ChannelAckResult, ChannelMessageItem, ChannelPeekResult, ChannelPublishResult, ChannelScope, ChannelSubscribeResult, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, AgentDefRowResponse, AgentDefVerifyResult, SkillDefVerifyResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, } from "./types.js";
81
+ export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, PromptContent, PromptSegment, RetryInfo, RunOptions, ToolUse, Usage, Agent, AgentStatus, AgentUsage, CancelAgentResult, ListAgentsResponse, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, PauseResult, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, CreateSnapshotOptions, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotListResponse, SnapshotRestoreResponse, MemoryEntriesResponse, MemoryEntry, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopeIDSummary, MemoryScopeKind, MemoryScopesResponse, InterruptListResponse, InterruptRow, InterruptStatus, ResolveInterruptOptions, Hook, HookFailMode, HookPhase, HookToolCall, HookToolResult, ListHooksResponse, PostHookCall, PostHookResult, PreHookCall, PreHookResult, RegisterHookOptions, RegisterHookResponse, SubstrateToolInput, SubstrateToolResponse, SystemPromptPayload, UserInputPayload, ChannelDescriptor, ListChannelsResponse, RunStateEvent, RunStateStreamClose, RunStateStreamItem, RunStateStreamOpen, StreamUserRunStatesOptions, AckChannelOptions, ChannelAckResult, ChannelMessageItem, ChannelPeekResult, ChannelPublishResult, ChannelScope, ChannelSubscribeResult, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, CreateChannelOptions, UpdateChannelOptions, SetMemoryEntryOptions, SetMemoryEntryResponse, AgentDefRowResponse, AgentDefVerifyResult, SkillDefVerifyResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, } from "./types.js";
80
82
  export { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, HookNotFoundError, NotFoundError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, UnavailableError, } from "./errors.js";
package/dist/index.js CHANGED
@@ -42,9 +42,11 @@
42
42
  * listRunInterrupts(runId, opts?): Promise<InterruptListResponse>
43
43
  * resolveInterrupt(runId, interruptId, opts): Promise<unknown>
44
44
  *
45
- * // Substrate admin (v0.8.22)
45
+ * // Substrate admin (v0.8.22; mcpServerDef v0.9.x; scheduleDef v1.x)
46
46
  * agentDef(input): Promise<SubstrateToolResponse>
47
47
  * skillDef(input): Promise<SubstrateToolResponse>
48
+ * mcpServerDef(input): Promise<SubstrateToolResponse>
49
+ * scheduleDef(input): Promise<SubstrateToolResponse>
48
50
  *
49
51
  * // Library v2 enumeration (v0.10.3 — yaml+substrate merged)
50
52
  * listLibraryAgents(): Promise<LibraryListResponse<LibraryAgentDefinition>>
package/dist/types.d.ts CHANGED
@@ -130,6 +130,15 @@ export interface RunOptions {
130
130
  * (static-bearer setups unaffected). Sub-agents inherit identically.
131
131
  * Never persisted; never logged in full. */
132
132
  userBearer?: string;
133
+ /** Per-tool named credentials map (v1.x RFC F). Per-MCP-server bearers
134
+ * keyed by operator-chosen name (convention: the `mcp_servers.<name>`
135
+ * yaml key). Substituted into MCP HTTP header values containing
136
+ * `${run.credentials.<name>}` at outbound request-build time. Keys
137
+ * match `[a-zA-Z0-9_-]{1,64}`; values arbitrary strings. Sub-agents
138
+ * inherit the whole map. Coexists with `userBearer` — the legacy
139
+ * field auto-promotes to `userCredentials.default` for back-compat
140
+ * with v0.8.x flows. Never persisted; never logged. */
141
+ userCredentials?: Record<string, string>;
133
142
  /** Opt-in observability: when true, the iterator emits client-
134
143
  * synthesized `{ type: "_meta", meta_subtype: "stream_open" | "stream_close" }`
135
144
  * events around the real event stream. `meta_reason` carries the
@@ -166,6 +175,10 @@ export interface ContinueOptions {
166
175
  * so different continuations in the same session may carry
167
176
  * different end-user tokens. */
168
177
  userBearer?: string;
178
+ /** Per-tool named credentials map (v1.x RFC F). See
179
+ * {@link RunOptions.userCredentials} for the full shape — same
180
+ * semantics, supplied per-continuation rather than per-fresh-run. */
181
+ userCredentials?: Record<string, string>;
169
182
  /** Opt-in observability: see {@link RunOptions.debug}. Same shape. */
170
183
  debug?: boolean;
171
184
  signal?: AbortSignal;
@@ -192,6 +205,7 @@ export interface AgentUsage {
192
205
  cache_creation_tokens?: number;
193
206
  cache_read_tokens?: number;
194
207
  model?: string;
208
+ provider?: string;
195
209
  }
196
210
  export interface Agent {
197
211
  agent_id: string;
@@ -555,6 +569,7 @@ export interface PostHookResult {
555
569
  * {@link LoomcycleClient.listChannels}. */
556
570
  export interface ChannelDescriptor {
557
571
  name: string;
572
+ description?: string;
558
573
  scope?: string;
559
574
  semantic?: string;
560
575
  publisher?: string;
@@ -565,6 +580,10 @@ export interface ChannelDescriptor {
565
580
  /** RFC3339 — empty when count == 0. */
566
581
  oldest_visible_at?: string;
567
582
  newest_visible_at?: string;
583
+ /** v0.11.5: "yaml" (operator yaml — immutable from this surface),
584
+ * "runtime" (substrate — CRUD-mutable), "orphan" (no declaration,
585
+ * only orphan messages). */
586
+ source?: "yaml" | "runtime" | "orphan" | string;
568
587
  }
569
588
  /** Response shape for {@link LoomcycleClient.listChannels}. */
570
589
  export interface ListChannelsResponse {
@@ -656,6 +675,63 @@ export interface AckChannelOptions {
656
675
  export interface ChannelAckResult {
657
676
  ok: boolean;
658
677
  }
678
+ /** Options for {@link LoomcycleClient.createChannel}. Operator-yaml
679
+ * channels are immutable from this surface; the server returns
680
+ * HTTP 409 `channel_yaml_immutable` when `name` matches a yaml-
681
+ * declared channel. */
682
+ export interface CreateChannelOptions {
683
+ name: string;
684
+ description?: string;
685
+ /** "global" | "agent" | "user". Defaults to "global" if omitted. */
686
+ scope?: string;
687
+ /** "queue" | "topic". Defaults to "queue" if omitted. */
688
+ semantic?: string;
689
+ /** Seconds; 0 = no TTL. */
690
+ default_ttl?: number;
691
+ /** 0 = unbounded. */
692
+ max_messages?: number;
693
+ /** Free-form attribution; not enforced by the substrate. */
694
+ publisher?: string;
695
+ /** Free-form retention hint; not enforced by the substrate. */
696
+ period?: string;
697
+ signal?: AbortSignal;
698
+ }
699
+ /** Options for {@link LoomcycleClient.updateChannel}. Nil fields
700
+ * leave the corresponding channel attribute unchanged. */
701
+ export interface UpdateChannelOptions {
702
+ description?: string;
703
+ default_ttl?: number;
704
+ max_messages?: number;
705
+ /** "queue" | "topic" */
706
+ semantic?: string;
707
+ signal?: AbortSignal;
708
+ }
709
+ /** Options for {@link LoomcycleClient.setMemoryEntry}. `value` is
710
+ * opaque JSON. Setting `embed: true` triggers a synchronous embed
711
+ * via the operator-configured embedder; the returned `embedded`
712
+ * flag + optional `embed_warning` report whether the embedding
713
+ * landed. */
714
+ export interface SetMemoryEntryOptions {
715
+ value: unknown;
716
+ /** When true, also compute + store the embedding (requires
717
+ * memory.embedder yaml + a vector-capable store backend). */
718
+ embed?: boolean;
719
+ /** Optional TTL in seconds; <= 0 means "no expiry". */
720
+ ttl_seconds?: number;
721
+ signal?: AbortSignal;
722
+ }
723
+ /** Response shape for {@link LoomcycleClient.setMemoryEntry}. */
724
+ export interface SetMemoryEntryResponse {
725
+ scope: string;
726
+ scope_id: string;
727
+ key: string;
728
+ /** true when the embedding was computed AND stored. */
729
+ embedded: boolean;
730
+ /** Non-empty when embed was requested but failed (transient
731
+ * error, embedder unconfigured, vector backend not available).
732
+ * The k/v row still landed. */
733
+ embed_warning?: string;
734
+ }
659
735
  /** One run state transition emitted by
660
736
  * {@link LoomcycleClient.streamUserRunStates}. The TS field is RFC3339. */
661
737
  export interface RunStateEvent {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loomcycle/client",
3
- "version": "0.11.4",
4
- "description": "TypeScript client for the loomcycle sidecar (HTTP+SSE). 41 methods covering run streaming, agent metadata, pause/resume/state, snapshot lifecycle, memory admin (incl. v0.9.0 Vector Memory embed_stats + reembed), interruption resolve, hook management, v0.8.22 substrate admin (agentDef + skillDef), v0.9.x n8n Phase 0 (listChannels + streamUserRunStates), v0.9.x Channel CRUD (publishChannel + subscribeChannel + peekChannel + ackChannel), v0.9.x content_sha256 verify, v0.9.1 transcript first-cycle, v0.9.x dynamic MCP server registration (mcpServerDef + MCPServerDefVerifyResult), v0.10.3 Library v2 enumeration (listLibraryAgents + listLibrarySkills + listLibraryMcpServers), and v0.11.0 LLM Gateway (llmChat + llmStream — direct provider routing without agent overhead; primary target is n8n's LoomCycleChatModel AI Agent sub-node and any LangChain-compatible consumer). v0.10.1 — dual ESM + CommonJS distribution (additive — ESM consumers unchanged; CJS consumers like n8n's community-node loader now work).",
3
+ "version": "0.12.7",
4
+ "description": "TypeScript client for the loomcycle sidecar (HTTP+SSE). 46 methods covering run streaming, agent metadata, pause/resume/state, snapshot lifecycle, memory admin (incl. v0.9.0 Vector Memory embed_stats + reembed AND v0.11.5 setMemoryEntry + deleteMemoryEntry), interruption resolve, hook management, v0.8.22 substrate admin (agentDef + skillDef), v0.9.x n8n Phase 0 (listChannels + streamUserRunStates), v0.9.x Channel CRUD (publishChannel + subscribeChannel + peekChannel + ackChannel), v0.11.5 Channel admin CRUD (createChannel + updateChannel + deleteChannel — runtime substrate; yaml channels refuse mutation with HTTP 409), v0.9.x content_sha256 verify, v0.9.1 transcript first-cycle, v0.9.x dynamic MCP server registration (mcpServerDef + MCPServerDefVerifyResult), v0.10.3 Library v2 enumeration (listLibraryAgents + listLibrarySkills + listLibraryMcpServers), and v0.11.0 LLM Gateway (llmChat + llmStream — direct provider routing without agent overhead; primary target is n8n's LoomCycleChatModel AI Agent sub-node and any LangChain-compatible consumer). v0.10.1 — dual ESM + CommonJS distribution (additive — ESM consumers unchanged; CJS consumers like n8n's community-node loader now work).",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "repository": {