@loomcycle/client 0.18.0 → 0.20.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.
@@ -418,6 +418,41 @@ class LoomcycleClient {
418
418
  async agentDef(input, opts) {
419
419
  return (0, fetch_helpers_js_1.postJSON)(this.ctx, "/v1/_agentdef", input, opts);
420
420
  }
421
+ /** Register (or refresh) a code-js agent idempotently from an INLINE JS body
422
+ * — the typed "ship a code agent with no host filesystem" convenience
423
+ * (RFC J), mirror of {@link LoomcycleClient.ensureMcpServer}.
424
+ *
425
+ * Runs `agentDef({op:"create", overlay:{provider:"code-js", code_body, …}})`,
426
+ * which is content-addressed-idempotent in loomcycle: a byte-identical
427
+ * re-registration is a no-op (`changed:false`), not a new version. This is
428
+ * what makes code agents work across container boundaries / pure-cloud —
429
+ * the JS no longer has to exist at `agent_code/<name>/index.js` on the
430
+ * sidecar's disk.
431
+ *
432
+ * Requires `LOOMCYCLE_CODE_AGENTS_ENABLED=1` on the sidecar — the same
433
+ * switch that registers the code-js provider. Without it the create is
434
+ * refused (raises {@link SubstrateToolRefusedError}). Keep `${run.*}` /
435
+ * `${LOOMCYCLE_*}` placeholders in the body LITERAL so the content stays
436
+ * stable and dedup engages on re-register. */
437
+ async ensureCodeAgent(opts, callOpts) {
438
+ const overlay = { provider: "code-js", code_body: opts.code };
439
+ if (opts.allowedTools)
440
+ overlay.allowed_tools = opts.allowedTools;
441
+ if (opts.tier)
442
+ overlay.tier = opts.tier;
443
+ if (opts.model)
444
+ overlay.model = opts.model;
445
+ const input = { op: "create", name: opts.name, overlay };
446
+ if (opts.description)
447
+ input.description = opts.description;
448
+ const row = (await this.agentDef(input, callOpts));
449
+ return {
450
+ name: opts.name,
451
+ defId: row.def_id,
452
+ version: row.version,
453
+ changed: row.deduplicated !== true,
454
+ };
455
+ }
421
456
  /** Invoke the SkillDef substrate tool over HTTP. Mirror of
422
457
  * {@link LoomcycleClient.agentDef} for skills (v0.8.22+). Same
423
458
  * input grammar, same error class on refusal. See the
@@ -466,15 +501,21 @@ class LoomcycleClient {
466
501
  * "register-if-changed" convenience for a consumer that re-registers its
467
502
  * own callback server on every startup.
468
503
  *
469
- * Runs `create` (which is content-addressed-idempotent in loomcycle
470
- * ≥ v0.18.0 — a byte-identical re-registration is a no-op, not a new
471
- * version) and, when {@link EnsureMcpServerOptions.rediscover} is set, a
472
- * `tools/list` rediscover (also idempotent on unchanged tools). The
473
- * returned {@link EnsureMcpServerResult.changed} is false when loomcycle
474
- * deduped both — so a stable-content re-register on every boot is a clean
475
- * no-op. Keep `${run.*}` / `${LOOMCYCLE_*}` header placeholders LITERAL
476
- * (don't resolve a per-restart token) or the content varies each boot and
477
- * dedup can't engage. */
504
+ * Runs `create`, which is content-addressed-idempotent (a byte-identical
505
+ * re-registration is a no-op, not a new version) AND auto-discovers the
506
+ * upstream's tools at ingestion — so {@link EnsureMcpServerResult.changed}
507
+ * is false on a stable-content re-register, and
508
+ * {@link EnsureMcpServerResult.discoveredToolCount} is populated straight
509
+ * from the `create` (no separate rediscover needed for the count). On a
510
+ * deduplicated re-register the count is absent (the tool surface was
511
+ * unchanged), so it reflects only the freshly-discovered case.
512
+ *
513
+ * Pass {@link EnsureMcpServerOptions.rediscover} only to FORCE a refresh
514
+ * when the upstream's tools changed but the registration content didn't.
515
+ *
516
+ * Keep `${run.*}` / `${LOOMCYCLE_*}` header placeholders LITERAL (don't
517
+ * resolve a per-restart token) or the content varies each boot and dedup
518
+ * can't engage. */
478
519
  async ensureMcpServer(opts, callOpts) {
479
520
  const overlay = {
480
521
  transport: opts.transport ?? "http",
@@ -488,13 +529,15 @@ class LoomcycleClient {
488
529
  const created = (await this.mcpServerDef(createInput, callOpts));
489
530
  let row = created;
490
531
  let changed = created.deduplicated !== true;
491
- let discoveredToolCount;
532
+ // create auto-discovers at ingestion → the count is on the create response.
533
+ let discoveredToolCount = created.discovered;
492
534
  if (opts.rediscover) {
493
535
  const red = (await this.mcpServerDef({ op: "rediscover", name: opts.name }, callOpts));
494
536
  row = red;
495
537
  if (red.deduplicated !== true)
496
538
  changed = true;
497
- discoveredToolCount = red.discovered;
539
+ if (red.discovered !== undefined)
540
+ discoveredToolCount = red.discovered;
498
541
  }
499
542
  const result = {
500
543
  name: opts.name,
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, EnsureMcpServerOptions, EnsureMcpServerResult, 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, MCPServerDefVerifyResult, MemoryEntriesResponse, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopesResponse, PauseResult, RegisterHookOptions, RegisterHookResponse, ResolveInterruptOptions, ResumeResult, ResolverMatrix, RunOptions, RunStateStreamItem, RuntimeStateResponse, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotRestoreResponse, StreamUserRunStatesOptions, SubstrateToolInput, SubstrateToolResponse, TranscriptResponse, WhoamiResponse } from "./types.js";
26
+ import type { Agent, AgentEvent, AgentStatus, CancelAgentResult, ClientOptions, ContinueOptions, CreateSnapshotOptions, EnsureCodeAgentOptions, EnsureCodeAgentResult, EnsureMcpServerOptions, EnsureMcpServerResult, 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, MCPServerDefVerifyResult, MemoryEntriesResponse, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopesResponse, PauseResult, RegisterHookOptions, RegisterHookResponse, ResolveInterruptOptions, ResumeResult, ResolverMatrix, RunOptions, RunStateStreamItem, RuntimeStateResponse, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotRestoreResponse, StreamUserRunStatesOptions, SubstrateToolInput, SubstrateToolResponse, TranscriptResponse, WhoamiResponse } from "./types.js";
27
27
  export declare class LoomcycleClient {
28
28
  private ctx;
29
29
  constructor(opts?: ClientOptions);
@@ -275,6 +275,25 @@ export declare class LoomcycleClient {
275
275
  agentDef(input: SubstrateToolInput, opts?: {
276
276
  signal?: AbortSignal;
277
277
  }): Promise<SubstrateToolResponse>;
278
+ /** Register (or refresh) a code-js agent idempotently from an INLINE JS body
279
+ * — the typed "ship a code agent with no host filesystem" convenience
280
+ * (RFC J), mirror of {@link LoomcycleClient.ensureMcpServer}.
281
+ *
282
+ * Runs `agentDef({op:"create", overlay:{provider:"code-js", code_body, …}})`,
283
+ * which is content-addressed-idempotent in loomcycle: a byte-identical
284
+ * re-registration is a no-op (`changed:false`), not a new version. This is
285
+ * what makes code agents work across container boundaries / pure-cloud —
286
+ * the JS no longer has to exist at `agent_code/<name>/index.js` on the
287
+ * sidecar's disk.
288
+ *
289
+ * Requires `LOOMCYCLE_CODE_AGENTS_ENABLED=1` on the sidecar — the same
290
+ * switch that registers the code-js provider. Without it the create is
291
+ * refused (raises {@link SubstrateToolRefusedError}). Keep `${run.*}` /
292
+ * `${LOOMCYCLE_*}` placeholders in the body LITERAL so the content stays
293
+ * stable and dedup engages on re-register. */
294
+ ensureCodeAgent(opts: EnsureCodeAgentOptions, callOpts?: {
295
+ signal?: AbortSignal;
296
+ }): Promise<EnsureCodeAgentResult>;
278
297
  /** Invoke the SkillDef substrate tool over HTTP. Mirror of
279
298
  * {@link LoomcycleClient.agentDef} for skills (v0.8.22+). Same
280
299
  * input grammar, same error class on refusal. See the
@@ -323,15 +342,21 @@ export declare class LoomcycleClient {
323
342
  * "register-if-changed" convenience for a consumer that re-registers its
324
343
  * own callback server on every startup.
325
344
  *
326
- * Runs `create` (which is content-addressed-idempotent in loomcycle
327
- * ≥ v0.18.0 — a byte-identical re-registration is a no-op, not a new
328
- * version) and, when {@link EnsureMcpServerOptions.rediscover} is set, a
329
- * `tools/list` rediscover (also idempotent on unchanged tools). The
330
- * returned {@link EnsureMcpServerResult.changed} is false when loomcycle
331
- * deduped both — so a stable-content re-register on every boot is a clean
332
- * no-op. Keep `${run.*}` / `${LOOMCYCLE_*}` header placeholders LITERAL
333
- * (don't resolve a per-restart token) or the content varies each boot and
334
- * dedup can't engage. */
345
+ * Runs `create`, which is content-addressed-idempotent (a byte-identical
346
+ * re-registration is a no-op, not a new version) AND auto-discovers the
347
+ * upstream's tools at ingestion — so {@link EnsureMcpServerResult.changed}
348
+ * is false on a stable-content re-register, and
349
+ * {@link EnsureMcpServerResult.discoveredToolCount} is populated straight
350
+ * from the `create` (no separate rediscover needed for the count). On a
351
+ * deduplicated re-register the count is absent (the tool surface was
352
+ * unchanged), so it reflects only the freshly-discovered case.
353
+ *
354
+ * Pass {@link EnsureMcpServerOptions.rediscover} only to FORCE a refresh
355
+ * when the upstream's tools changed but the registration content didn't.
356
+ *
357
+ * Keep `${run.*}` / `${LOOMCYCLE_*}` header placeholders LITERAL (don't
358
+ * resolve a per-restart token) or the content varies each boot and dedup
359
+ * can't engage. */
335
360
  ensureMcpServer(opts: EnsureMcpServerOptions, callOpts?: {
336
361
  signal?: AbortSignal;
337
362
  }): Promise<EnsureMcpServerResult>;
package/dist/client.js CHANGED
@@ -415,6 +415,41 @@ export class LoomcycleClient {
415
415
  async agentDef(input, opts) {
416
416
  return postJSON(this.ctx, "/v1/_agentdef", input, opts);
417
417
  }
418
+ /** Register (or refresh) a code-js agent idempotently from an INLINE JS body
419
+ * — the typed "ship a code agent with no host filesystem" convenience
420
+ * (RFC J), mirror of {@link LoomcycleClient.ensureMcpServer}.
421
+ *
422
+ * Runs `agentDef({op:"create", overlay:{provider:"code-js", code_body, …}})`,
423
+ * which is content-addressed-idempotent in loomcycle: a byte-identical
424
+ * re-registration is a no-op (`changed:false`), not a new version. This is
425
+ * what makes code agents work across container boundaries / pure-cloud —
426
+ * the JS no longer has to exist at `agent_code/<name>/index.js` on the
427
+ * sidecar's disk.
428
+ *
429
+ * Requires `LOOMCYCLE_CODE_AGENTS_ENABLED=1` on the sidecar — the same
430
+ * switch that registers the code-js provider. Without it the create is
431
+ * refused (raises {@link SubstrateToolRefusedError}). Keep `${run.*}` /
432
+ * `${LOOMCYCLE_*}` placeholders in the body LITERAL so the content stays
433
+ * stable and dedup engages on re-register. */
434
+ async ensureCodeAgent(opts, callOpts) {
435
+ const overlay = { provider: "code-js", code_body: opts.code };
436
+ if (opts.allowedTools)
437
+ overlay.allowed_tools = opts.allowedTools;
438
+ if (opts.tier)
439
+ overlay.tier = opts.tier;
440
+ if (opts.model)
441
+ overlay.model = opts.model;
442
+ const input = { op: "create", name: opts.name, overlay };
443
+ if (opts.description)
444
+ input.description = opts.description;
445
+ const row = (await this.agentDef(input, callOpts));
446
+ return {
447
+ name: opts.name,
448
+ defId: row.def_id,
449
+ version: row.version,
450
+ changed: row.deduplicated !== true,
451
+ };
452
+ }
418
453
  /** Invoke the SkillDef substrate tool over HTTP. Mirror of
419
454
  * {@link LoomcycleClient.agentDef} for skills (v0.8.22+). Same
420
455
  * input grammar, same error class on refusal. See the
@@ -463,15 +498,21 @@ export class LoomcycleClient {
463
498
  * "register-if-changed" convenience for a consumer that re-registers its
464
499
  * own callback server on every startup.
465
500
  *
466
- * Runs `create` (which is content-addressed-idempotent in loomcycle
467
- * ≥ v0.18.0 — a byte-identical re-registration is a no-op, not a new
468
- * version) and, when {@link EnsureMcpServerOptions.rediscover} is set, a
469
- * `tools/list` rediscover (also idempotent on unchanged tools). The
470
- * returned {@link EnsureMcpServerResult.changed} is false when loomcycle
471
- * deduped both — so a stable-content re-register on every boot is a clean
472
- * no-op. Keep `${run.*}` / `${LOOMCYCLE_*}` header placeholders LITERAL
473
- * (don't resolve a per-restart token) or the content varies each boot and
474
- * dedup can't engage. */
501
+ * Runs `create`, which is content-addressed-idempotent (a byte-identical
502
+ * re-registration is a no-op, not a new version) AND auto-discovers the
503
+ * upstream's tools at ingestion — so {@link EnsureMcpServerResult.changed}
504
+ * is false on a stable-content re-register, and
505
+ * {@link EnsureMcpServerResult.discoveredToolCount} is populated straight
506
+ * from the `create` (no separate rediscover needed for the count). On a
507
+ * deduplicated re-register the count is absent (the tool surface was
508
+ * unchanged), so it reflects only the freshly-discovered case.
509
+ *
510
+ * Pass {@link EnsureMcpServerOptions.rediscover} only to FORCE a refresh
511
+ * when the upstream's tools changed but the registration content didn't.
512
+ *
513
+ * Keep `${run.*}` / `${LOOMCYCLE_*}` header placeholders LITERAL (don't
514
+ * resolve a per-restart token) or the content varies each boot and dedup
515
+ * can't engage. */
475
516
  async ensureMcpServer(opts, callOpts) {
476
517
  const overlay = {
477
518
  transport: opts.transport ?? "http",
@@ -485,13 +526,15 @@ export class LoomcycleClient {
485
526
  const created = (await this.mcpServerDef(createInput, callOpts));
486
527
  let row = created;
487
528
  let changed = created.deduplicated !== true;
488
- let discoveredToolCount;
529
+ // create auto-discovers at ingestion → the count is on the create response.
530
+ let discoveredToolCount = created.discovered;
489
531
  if (opts.rediscover) {
490
532
  const red = (await this.mcpServerDef({ op: "rediscover", name: opts.name }, callOpts));
491
533
  row = red;
492
534
  if (red.deduplicated !== true)
493
535
  changed = true;
494
- discoveredToolCount = red.discovered;
536
+ if (red.discovered !== undefined)
537
+ discoveredToolCount = red.discovered;
495
538
  }
496
539
  const result = {
497
540
  name: opts.name,
package/dist/index.d.ts CHANGED
@@ -82,5 +82,5 @@
82
82
  * See `adapters/ts/README.md` for usage examples.
83
83
  */
84
84
  export { LoomcycleClient } from "./client.js";
85
- export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, ParentContext, PromptContent, PromptSegment, RetryInfo, RunOptions, ToolUse, Usage, Agent, AgentStatus, AgentUsage, CancelAgentResult, ListAgentsResponse, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, WhoamiResponse, PauseResult, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, ResolverMatrix, ResolverModelStatus, ResolverProviderAvailability, 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, EnsureMcpServerOptions, EnsureMcpServerResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, } from "./types.js";
85
+ export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, ParentContext, PromptContent, PromptSegment, RetryInfo, RunOptions, ToolUse, Usage, Agent, AgentStatus, AgentUsage, CancelAgentResult, ListAgentsResponse, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, WhoamiResponse, PauseResult, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, ResolverMatrix, ResolverModelStatus, ResolverProviderAvailability, 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, EnsureMcpServerOptions, EnsureMcpServerResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, AgentDefOverlay, EnsureCodeAgentOptions, EnsureCodeAgentResult, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, } from "./types.js";
86
86
  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/types.d.ts CHANGED
@@ -886,6 +886,10 @@ export interface AgentDefRowResponse {
886
886
  /** Only populated on `set` / `fork` responses (was the new row
887
887
  * auto-promoted to active?). Absent on get/list. */
888
888
  promoted?: boolean;
889
+ /** True when create was a content-addressed no-op: the active def already
890
+ * carried identical content, so no new version was minted. Absent on a
891
+ * real mint. Drives {@link LoomcycleClient.ensureCodeAgent}'s `changed`. */
892
+ deduplicated?: boolean;
889
893
  }
890
894
  /** Response shape for `AgentDef verify`. Answers "is the supplied
891
895
  * content_sha256 the active deployed version of this name?"
@@ -943,7 +947,11 @@ export interface MCPServerDefRowResponse {
943
947
  * content (create) or identical discovered_tools (rediscover), so no
944
948
  * new version was minted. Absent (undefined) on a real mint. */
945
949
  deduplicated?: boolean;
946
- /** Only on `rediscover` responses — the number of tools discovered. */
950
+ /** Number of tools discovered via the upstream's `tools/list`. Present on
951
+ * `rediscover` responses and — since loomcycle auto-discovers at ingestion
952
+ * — on a fresh `create`/`fork` that ran the handshake. Absent on a
953
+ * deduplicated create (the active tool surface was unchanged) and when
954
+ * `discover:false` was passed. */
947
955
  discovered?: number;
948
956
  }
949
957
  /** Options for {@link LoomcycleClient.ensureMcpServer}. */
@@ -960,7 +968,14 @@ export interface EnsureMcpServerOptions {
960
968
  * loomcycle's idempotent create dedup the re-registration. */
961
969
  headers?: Record<string, string>;
962
970
  description?: string;
963
- /** Run a `tools/list` rediscover after registering. Default false. */
971
+ /** Force a `tools/list` refresh after registering. Default false.
972
+ *
973
+ * You usually do NOT need this: registration auto-discovers the upstream's
974
+ * tools at ingestion, so {@link EnsureMcpServerResult.discoveredToolCount}
975
+ * is already populated from the `create`. Set this only to force a re-read
976
+ * when the upstream's tool surface changed but the registration content
977
+ * (url/headers) did not — a plain re-register would dedup and keep the
978
+ * cached tools, whereas a rediscover re-runs the handshake. */
964
979
  rediscover?: boolean;
965
980
  }
966
981
  /** Result of {@link LoomcycleClient.ensureMcpServer}. */
@@ -976,6 +991,65 @@ export interface EnsureMcpServerResult {
976
991
  /** Populated when `rediscover` ran: the number of tools discovered. */
977
992
  discoveredToolCount?: number;
978
993
  }
994
+ /** Typed `overlay` for an {@link LoomcycleClient.agentDef} create/fork —
995
+ * the mutable subset of an agent definition. All fields optional (a fork
996
+ * overlays only what changes). The `[extra]` tail keeps it forward-compatible
997
+ * with fields the in-process tool may accept that the adapter doesn't model
998
+ * yet — the tool owns the authoritative schema; the adapter doesn't re-validate.
999
+ *
1000
+ * `code_body` is the inline code-js orchestrator source (RFC J): set it (with
1001
+ * `provider: "code-js"`) to ingest a code agent through the substrate with NO
1002
+ * host filesystem bind — the symmetry that makes code agents work in
1003
+ * containers / pure-cloud. Requires `LOOMCYCLE_CODE_AGENTS_ENABLED=1` on the
1004
+ * sidecar; create/fork refuses a non-empty `code_body` otherwise. */
1005
+ export interface AgentDefOverlay {
1006
+ provider?: string;
1007
+ model?: string;
1008
+ /** Inline code-js source. Empty/absent ⇒ the provider falls back to
1009
+ * `agent_code/<name>/index.js`. Stored verbatim (whitespace is hash-
1010
+ * significant); participates in content_sha256. */
1011
+ code_body?: string;
1012
+ tier?: string;
1013
+ effort?: string;
1014
+ max_tokens?: number;
1015
+ max_iterations?: number;
1016
+ max_concurrent_children?: number;
1017
+ system_prompt?: string;
1018
+ allowed_tools?: string[];
1019
+ skills?: string[];
1020
+ memory_scopes?: string[];
1021
+ memory_quota_bytes?: number;
1022
+ memory_backend?: string;
1023
+ retry_attempts?: number;
1024
+ [extra: string]: unknown;
1025
+ }
1026
+ /** Options for {@link LoomcycleClient.ensureCodeAgent}. */
1027
+ export interface EnsureCodeAgentOptions {
1028
+ /** Agent name (substrate; must not collide with a static cfg.Agents name —
1029
+ * use a fork for those). */
1030
+ name: string;
1031
+ /** The inline code-js orchestrator source (the `function run(input){…}` body).
1032
+ * Keep any `${run.*}` / `${LOOMCYCLE_*}` placeholders LITERAL so the content
1033
+ * is stable across restarts — that's what lets loomcycle dedup the
1034
+ * re-registration. */
1035
+ code: string;
1036
+ /** The agent's allowed_tools ceiling (must be a subset of the caller's). */
1037
+ allowedTools?: string[];
1038
+ /** Per-user tier policy name (mutually exclusive with `model` in practice). */
1039
+ tier?: string;
1040
+ /** Pin a concrete model id (overrides tier resolution). */
1041
+ model?: string;
1042
+ description?: string;
1043
+ }
1044
+ /** Result of {@link LoomcycleClient.ensureCodeAgent}. */
1045
+ export interface EnsureCodeAgentResult {
1046
+ name: string;
1047
+ defId: string;
1048
+ version: number;
1049
+ /** True when this call minted a new version; false when loomcycle deduped
1050
+ * it (identical body + config already active). */
1051
+ changed: boolean;
1052
+ }
979
1053
  /** Response shape for `MCPServerDef verify`. Same semantics as
980
1054
  * AgentDefVerifyResult / SkillDefVerifyResult — answers "is the
981
1055
  * supplied content_sha256 the deployed active version of this name?" */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loomcycle/client",
3
- "version": "0.18.0",
4
- "description": "TypeScript client for the loomcycle sidecar (HTTP+SSE). 51 methods covering run streaming, agent metadata, pause/resume/state, resolver re-probe (resolveProbe — issue #88 operator escape hatch), operator-token admin (operatorTokenDef — RFC L OSS multi-tenant auth) + whoami (RFC L authoritative principal, v0.17.0) + tenant-scoped listUsers / listUserAgents, dynamic MCP registration (mcpServerDef + v0.18.0 typed mcpServerDefVerify + ensureMcpServer idempotent register-if-changed), 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).",
3
+ "version": "0.20.0",
4
+ "description": "TypeScript client for the loomcycle sidecar (HTTP+SSE). 51 methods covering run streaming, agent metadata, pause/resume/state, resolver re-probe (resolveProbe — issue #88 operator escape hatch), operator-token admin (operatorTokenDef — RFC L OSS multi-tenant auth) + whoami (RFC L authoritative principal, v0.17.0) + tenant-scoped listUsers / listUserAgents, dynamic MCP registration (mcpServerDef + v0.18.0 typed mcpServerDefVerify + ensureMcpServer idempotent register-if-changed), 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). v0.19.0 — typed inline code-js agent ingestion (AgentDefOverlay.code_body + ensureCodeAgent — register a deterministic code agent through the substrate with no host filesystem bind; RFC J). v0.20.0 — ensureMcpServer surfaces discoveredToolCount straight from create (loomcycle now auto-discovers MCP tools at ingestion); rediscover is now an explicit force-refresh.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "repository": {