@loomcycle/client 0.10.4 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client.js +127 -0
- package/dist/cjs/index.js +4 -0
- package/dist/client.d.ts +33 -1
- package/dist/client.js +128 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -0
- package/dist/types.d.ts +148 -0
- package/package.json +2 -2
package/dist/cjs/client.js
CHANGED
|
@@ -463,6 +463,64 @@ class LoomcycleClient {
|
|
|
463
463
|
async listLibraryMcpServers(opts) {
|
|
464
464
|
return (0, fetch_helpers_js_1.jsonFetch)(this.ctx, "/v1/_library/mcp-servers", opts);
|
|
465
465
|
}
|
|
466
|
+
// ---- v0.11.0 LLM Gateway ----
|
|
467
|
+
/** Non-streaming LLM chat completion via the gateway endpoint.
|
|
468
|
+
* Wraps `POST /v1/_llm/chat` with `stream: false`. The gateway
|
|
469
|
+
* resolves a provider per the routing precedence
|
|
470
|
+
* (explicit-pin > explicit-provider > explicit-model > resolver
|
|
471
|
+
* default), invokes it directly (no agent loop), and returns the
|
|
472
|
+
* aggregated response with usage counters + the chosen
|
|
473
|
+
* provider/model echoed back.
|
|
474
|
+
*
|
|
475
|
+
* Use this when you want loomcycle's routing benefits (one
|
|
476
|
+
* credential, one quota, one observability surface across
|
|
477
|
+
* providers) without paying for the agent runtime overhead.
|
|
478
|
+
* Tool-calling works: pass `tools[]` and read `tool_use` content
|
|
479
|
+
* blocks back; the per-provider schema translation is handled by
|
|
480
|
+
* the substrate's existing driver layer.
|
|
481
|
+
*
|
|
482
|
+
* Raises {@link AuthError} on 401; {@link UnavailableError} on 503
|
|
483
|
+
* (resolver not configured, store unwired);
|
|
484
|
+
* {@link InvalidArgumentError} on 400 (bad request shape). */
|
|
485
|
+
async llmChat(opts) {
|
|
486
|
+
const body = serializeLLMOptions(opts, false);
|
|
487
|
+
return (0, fetch_helpers_js_1.postJSON)(this.ctx, "/v1/_llm/chat", body, {
|
|
488
|
+
signal: opts.signal,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
/** Streaming LLM chat completion. Wraps `POST /v1/_llm/chat` with
|
|
492
|
+
* `stream: true`. Yields one {@link LLMChatStreamItem} per SSE
|
|
493
|
+
* frame in Anthropic-style: provider_chosen first, then
|
|
494
|
+
* content_block_start / content_block_delta / content_block_stop
|
|
495
|
+
* pairs, then message_delta + done.
|
|
496
|
+
*
|
|
497
|
+
* Iteration terminates when the gateway closes the stream. On a
|
|
498
|
+
* terminal error the gateway emits an `error` frame; the iterator
|
|
499
|
+
* yields it and the caller decides whether to throw.
|
|
500
|
+
*
|
|
501
|
+
* Use this for live token streaming into LangChain BaseChatModel
|
|
502
|
+
* `_stream` callbacks. */
|
|
503
|
+
async *llmStream(opts) {
|
|
504
|
+
const body = serializeLLMOptions(opts, true);
|
|
505
|
+
const resp = await this.ctx.fetchImpl(this.ctx.baseUrl + "/v1/_llm/chat", {
|
|
506
|
+
method: "POST",
|
|
507
|
+
headers: {
|
|
508
|
+
...(0, fetch_helpers_js_1.authHeaders)(this.ctx),
|
|
509
|
+
"Content-Type": "application/json",
|
|
510
|
+
Accept: "text/event-stream",
|
|
511
|
+
},
|
|
512
|
+
body: JSON.stringify(body),
|
|
513
|
+
signal: opts.signal,
|
|
514
|
+
});
|
|
515
|
+
if (!resp.ok) {
|
|
516
|
+
await (0, fetch_helpers_js_1.raiseFromResponse)(resp);
|
|
517
|
+
}
|
|
518
|
+
if (!resp.body) {
|
|
519
|
+
throw new Error("llmStream: response has no body");
|
|
520
|
+
}
|
|
521
|
+
const reader = resp.body.getReader();
|
|
522
|
+
yield* parseLLMStreamFrames(reader);
|
|
523
|
+
}
|
|
466
524
|
// ---- Internal helpers ----
|
|
467
525
|
/** Shared SSE POST → stream-of-AgentEvent path. Used by
|
|
468
526
|
* runStreaming + continueSession.
|
|
@@ -773,3 +831,72 @@ function channelOpPath(channel, scope, userId, op) {
|
|
|
773
831
|
}
|
|
774
832
|
return `/v1/_channels/${enc}/${op}`;
|
|
775
833
|
}
|
|
834
|
+
// ---- v0.11.0 LLM Gateway helpers ----
|
|
835
|
+
/** serializeLLMOptions strips the AbortSignal (transport concern) and
|
|
836
|
+
* forces the stream flag to match the call mode. */
|
|
837
|
+
function serializeLLMOptions(opts, stream) {
|
|
838
|
+
const { signal: _signal, ...rest } = opts;
|
|
839
|
+
return { ...rest, stream };
|
|
840
|
+
}
|
|
841
|
+
/** parseLLMStreamFrames drains an SSE stream from /v1/_llm/chat and
|
|
842
|
+
* yields one LLMChatStreamItem per frame. Unlike parseSSE in
|
|
843
|
+
* stream.ts, the gateway's frames discriminate purely by the SSE
|
|
844
|
+
* event name — there's no `type` field on the data payload. */
|
|
845
|
+
async function* parseLLMStreamFrames(reader) {
|
|
846
|
+
const decoder = new TextDecoder("utf-8");
|
|
847
|
+
let buf = "";
|
|
848
|
+
let event = "";
|
|
849
|
+
let data = "";
|
|
850
|
+
const flush = () => {
|
|
851
|
+
if (!event || !data) {
|
|
852
|
+
event = "";
|
|
853
|
+
data = "";
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
try {
|
|
857
|
+
const payload = JSON.parse(data);
|
|
858
|
+
const item = { kind: event, payload };
|
|
859
|
+
event = "";
|
|
860
|
+
data = "";
|
|
861
|
+
return item;
|
|
862
|
+
}
|
|
863
|
+
catch {
|
|
864
|
+
event = "";
|
|
865
|
+
data = "";
|
|
866
|
+
return null;
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
while (true) {
|
|
870
|
+
const { value, done } = await reader.read();
|
|
871
|
+
if (done)
|
|
872
|
+
break;
|
|
873
|
+
buf += decoder.decode(value, { stream: true });
|
|
874
|
+
let idx;
|
|
875
|
+
while ((idx = buf.indexOf("\n")) !== -1) {
|
|
876
|
+
const line = buf.slice(0, idx).replace(/\r$/, "");
|
|
877
|
+
buf = buf.slice(idx + 1);
|
|
878
|
+
if (line === "") {
|
|
879
|
+
const item = flush();
|
|
880
|
+
if (item)
|
|
881
|
+
yield item;
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
if (line.startsWith("event:"))
|
|
885
|
+
event = line.slice("event:".length).trim();
|
|
886
|
+
else if (line.startsWith("data:"))
|
|
887
|
+
data = line.slice("data:".length).trim();
|
|
888
|
+
// Keepalive comment lines (`:keepalive`) are silently dropped.
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
// Drain a final un-newlined frame on connection close.
|
|
892
|
+
if (buf.length > 0) {
|
|
893
|
+
const line = buf.replace(/\r$/, "");
|
|
894
|
+
if (line.startsWith("event:"))
|
|
895
|
+
event = line.slice("event:".length).trim();
|
|
896
|
+
else if (line.startsWith("data:"))
|
|
897
|
+
data = line.slice("data:".length).trim();
|
|
898
|
+
}
|
|
899
|
+
const item = flush();
|
|
900
|
+
if (item)
|
|
901
|
+
yield item;
|
|
902
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -52,6 +52,10 @@
|
|
|
52
52
|
* listLibrarySkills(): Promise<LibraryListResponse<LibrarySkillDefinition>>
|
|
53
53
|
* listLibraryMcpServers(): Promise<LibraryListResponse<LibraryMcpServerDefinition>>
|
|
54
54
|
*
|
|
55
|
+
* // LLM Gateway (v0.11.0 — direct provider routing, no agent loop)
|
|
56
|
+
* llmChat(opts: LLMChatOptions): Promise<LLMChatResponse>
|
|
57
|
+
* llmStream(opts: LLMChatOptions): AsyncIterable<LLMChatStreamItem>
|
|
58
|
+
*
|
|
55
59
|
* Errors (typed subclasses of LoomcycleError; see README for the
|
|
56
60
|
* full HTTP-status → typed-error mapping table):
|
|
57
61
|
* LoomcycleError, AgentNotFoundError, SessionNotFoundError,
|
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, 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, ChannelPeekResult, ChannelPublishResult, ChannelSubscribeResult, ListChannelsResponse, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, LibraryAgentDefinition, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, ListUsersResponse, LLMChatOptions, LLMChatResponse, LLMChatStreamItem, 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);
|
|
@@ -329,6 +329,38 @@ export declare class LoomcycleClient {
|
|
|
329
329
|
listLibraryMcpServers(opts?: {
|
|
330
330
|
signal?: AbortSignal;
|
|
331
331
|
}): Promise<LibraryListResponse<LibraryMcpServerDefinition>>;
|
|
332
|
+
/** Non-streaming LLM chat completion via the gateway endpoint.
|
|
333
|
+
* Wraps `POST /v1/_llm/chat` with `stream: false`. The gateway
|
|
334
|
+
* resolves a provider per the routing precedence
|
|
335
|
+
* (explicit-pin > explicit-provider > explicit-model > resolver
|
|
336
|
+
* default), invokes it directly (no agent loop), and returns the
|
|
337
|
+
* aggregated response with usage counters + the chosen
|
|
338
|
+
* provider/model echoed back.
|
|
339
|
+
*
|
|
340
|
+
* Use this when you want loomcycle's routing benefits (one
|
|
341
|
+
* credential, one quota, one observability surface across
|
|
342
|
+
* providers) without paying for the agent runtime overhead.
|
|
343
|
+
* Tool-calling works: pass `tools[]` and read `tool_use` content
|
|
344
|
+
* blocks back; the per-provider schema translation is handled by
|
|
345
|
+
* the substrate's existing driver layer.
|
|
346
|
+
*
|
|
347
|
+
* Raises {@link AuthError} on 401; {@link UnavailableError} on 503
|
|
348
|
+
* (resolver not configured, store unwired);
|
|
349
|
+
* {@link InvalidArgumentError} on 400 (bad request shape). */
|
|
350
|
+
llmChat(opts: LLMChatOptions): Promise<LLMChatResponse>;
|
|
351
|
+
/** Streaming LLM chat completion. Wraps `POST /v1/_llm/chat` with
|
|
352
|
+
* `stream: true`. Yields one {@link LLMChatStreamItem} per SSE
|
|
353
|
+
* frame in Anthropic-style: provider_chosen first, then
|
|
354
|
+
* content_block_start / content_block_delta / content_block_stop
|
|
355
|
+
* pairs, then message_delta + done.
|
|
356
|
+
*
|
|
357
|
+
* Iteration terminates when the gateway closes the stream. On a
|
|
358
|
+
* terminal error the gateway emits an `error` frame; the iterator
|
|
359
|
+
* yields it and the caller decides whether to throw.
|
|
360
|
+
*
|
|
361
|
+
* Use this for live token streaming into LangChain BaseChatModel
|
|
362
|
+
* `_stream` callbacks. */
|
|
363
|
+
llmStream(opts: LLMChatOptions): AsyncIterable<LLMChatStreamItem>;
|
|
332
364
|
/** Shared SSE POST → stream-of-AgentEvent path. Used by
|
|
333
365
|
* runStreaming + continueSession.
|
|
334
366
|
*
|
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 { deleteRequest, jsonFetch, postJSON, raiseFromResponse, } from "./fetch-helpers.js";
|
|
26
|
+
import { authHeaders, deleteRequest, jsonFetch, postJSON, raiseFromResponse, } from "./fetch-helpers.js";
|
|
27
27
|
import { parseSSE } from "./stream.js";
|
|
28
28
|
export class LoomcycleClient {
|
|
29
29
|
ctx;
|
|
@@ -460,6 +460,64 @@ export class LoomcycleClient {
|
|
|
460
460
|
async listLibraryMcpServers(opts) {
|
|
461
461
|
return jsonFetch(this.ctx, "/v1/_library/mcp-servers", opts);
|
|
462
462
|
}
|
|
463
|
+
// ---- v0.11.0 LLM Gateway ----
|
|
464
|
+
/** Non-streaming LLM chat completion via the gateway endpoint.
|
|
465
|
+
* Wraps `POST /v1/_llm/chat` with `stream: false`. The gateway
|
|
466
|
+
* resolves a provider per the routing precedence
|
|
467
|
+
* (explicit-pin > explicit-provider > explicit-model > resolver
|
|
468
|
+
* default), invokes it directly (no agent loop), and returns the
|
|
469
|
+
* aggregated response with usage counters + the chosen
|
|
470
|
+
* provider/model echoed back.
|
|
471
|
+
*
|
|
472
|
+
* Use this when you want loomcycle's routing benefits (one
|
|
473
|
+
* credential, one quota, one observability surface across
|
|
474
|
+
* providers) without paying for the agent runtime overhead.
|
|
475
|
+
* Tool-calling works: pass `tools[]` and read `tool_use` content
|
|
476
|
+
* blocks back; the per-provider schema translation is handled by
|
|
477
|
+
* the substrate's existing driver layer.
|
|
478
|
+
*
|
|
479
|
+
* Raises {@link AuthError} on 401; {@link UnavailableError} on 503
|
|
480
|
+
* (resolver not configured, store unwired);
|
|
481
|
+
* {@link InvalidArgumentError} on 400 (bad request shape). */
|
|
482
|
+
async llmChat(opts) {
|
|
483
|
+
const body = serializeLLMOptions(opts, false);
|
|
484
|
+
return postJSON(this.ctx, "/v1/_llm/chat", body, {
|
|
485
|
+
signal: opts.signal,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
/** Streaming LLM chat completion. Wraps `POST /v1/_llm/chat` with
|
|
489
|
+
* `stream: true`. Yields one {@link LLMChatStreamItem} per SSE
|
|
490
|
+
* frame in Anthropic-style: provider_chosen first, then
|
|
491
|
+
* content_block_start / content_block_delta / content_block_stop
|
|
492
|
+
* pairs, then message_delta + done.
|
|
493
|
+
*
|
|
494
|
+
* Iteration terminates when the gateway closes the stream. On a
|
|
495
|
+
* terminal error the gateway emits an `error` frame; the iterator
|
|
496
|
+
* yields it and the caller decides whether to throw.
|
|
497
|
+
*
|
|
498
|
+
* Use this for live token streaming into LangChain BaseChatModel
|
|
499
|
+
* `_stream` callbacks. */
|
|
500
|
+
async *llmStream(opts) {
|
|
501
|
+
const body = serializeLLMOptions(opts, true);
|
|
502
|
+
const resp = await this.ctx.fetchImpl(this.ctx.baseUrl + "/v1/_llm/chat", {
|
|
503
|
+
method: "POST",
|
|
504
|
+
headers: {
|
|
505
|
+
...authHeaders(this.ctx),
|
|
506
|
+
"Content-Type": "application/json",
|
|
507
|
+
Accept: "text/event-stream",
|
|
508
|
+
},
|
|
509
|
+
body: JSON.stringify(body),
|
|
510
|
+
signal: opts.signal,
|
|
511
|
+
});
|
|
512
|
+
if (!resp.ok) {
|
|
513
|
+
await raiseFromResponse(resp);
|
|
514
|
+
}
|
|
515
|
+
if (!resp.body) {
|
|
516
|
+
throw new Error("llmStream: response has no body");
|
|
517
|
+
}
|
|
518
|
+
const reader = resp.body.getReader();
|
|
519
|
+
yield* parseLLMStreamFrames(reader);
|
|
520
|
+
}
|
|
463
521
|
// ---- Internal helpers ----
|
|
464
522
|
/** Shared SSE POST → stream-of-AgentEvent path. Used by
|
|
465
523
|
* runStreaming + continueSession.
|
|
@@ -769,3 +827,72 @@ function channelOpPath(channel, scope, userId, op) {
|
|
|
769
827
|
}
|
|
770
828
|
return `/v1/_channels/${enc}/${op}`;
|
|
771
829
|
}
|
|
830
|
+
// ---- v0.11.0 LLM Gateway helpers ----
|
|
831
|
+
/** serializeLLMOptions strips the AbortSignal (transport concern) and
|
|
832
|
+
* forces the stream flag to match the call mode. */
|
|
833
|
+
function serializeLLMOptions(opts, stream) {
|
|
834
|
+
const { signal: _signal, ...rest } = opts;
|
|
835
|
+
return { ...rest, stream };
|
|
836
|
+
}
|
|
837
|
+
/** parseLLMStreamFrames drains an SSE stream from /v1/_llm/chat and
|
|
838
|
+
* yields one LLMChatStreamItem per frame. Unlike parseSSE in
|
|
839
|
+
* stream.ts, the gateway's frames discriminate purely by the SSE
|
|
840
|
+
* event name — there's no `type` field on the data payload. */
|
|
841
|
+
async function* parseLLMStreamFrames(reader) {
|
|
842
|
+
const decoder = new TextDecoder("utf-8");
|
|
843
|
+
let buf = "";
|
|
844
|
+
let event = "";
|
|
845
|
+
let data = "";
|
|
846
|
+
const flush = () => {
|
|
847
|
+
if (!event || !data) {
|
|
848
|
+
event = "";
|
|
849
|
+
data = "";
|
|
850
|
+
return null;
|
|
851
|
+
}
|
|
852
|
+
try {
|
|
853
|
+
const payload = JSON.parse(data);
|
|
854
|
+
const item = { kind: event, payload };
|
|
855
|
+
event = "";
|
|
856
|
+
data = "";
|
|
857
|
+
return item;
|
|
858
|
+
}
|
|
859
|
+
catch {
|
|
860
|
+
event = "";
|
|
861
|
+
data = "";
|
|
862
|
+
return null;
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
while (true) {
|
|
866
|
+
const { value, done } = await reader.read();
|
|
867
|
+
if (done)
|
|
868
|
+
break;
|
|
869
|
+
buf += decoder.decode(value, { stream: true });
|
|
870
|
+
let idx;
|
|
871
|
+
while ((idx = buf.indexOf("\n")) !== -1) {
|
|
872
|
+
const line = buf.slice(0, idx).replace(/\r$/, "");
|
|
873
|
+
buf = buf.slice(idx + 1);
|
|
874
|
+
if (line === "") {
|
|
875
|
+
const item = flush();
|
|
876
|
+
if (item)
|
|
877
|
+
yield item;
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
if (line.startsWith("event:"))
|
|
881
|
+
event = line.slice("event:".length).trim();
|
|
882
|
+
else if (line.startsWith("data:"))
|
|
883
|
+
data = line.slice("data:".length).trim();
|
|
884
|
+
// Keepalive comment lines (`:keepalive`) are silently dropped.
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
// Drain a final un-newlined frame on connection close.
|
|
888
|
+
if (buf.length > 0) {
|
|
889
|
+
const line = buf.replace(/\r$/, "");
|
|
890
|
+
if (line.startsWith("event:"))
|
|
891
|
+
event = line.slice("event:".length).trim();
|
|
892
|
+
else if (line.startsWith("data:"))
|
|
893
|
+
data = line.slice("data:".length).trim();
|
|
894
|
+
}
|
|
895
|
+
const item = flush();
|
|
896
|
+
if (item)
|
|
897
|
+
yield item;
|
|
898
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,10 @@
|
|
|
51
51
|
* listLibrarySkills(): Promise<LibraryListResponse<LibrarySkillDefinition>>
|
|
52
52
|
* listLibraryMcpServers(): Promise<LibraryListResponse<LibraryMcpServerDefinition>>
|
|
53
53
|
*
|
|
54
|
+
* // LLM Gateway (v0.11.0 — direct provider routing, no agent loop)
|
|
55
|
+
* llmChat(opts: LLMChatOptions): Promise<LLMChatResponse>
|
|
56
|
+
* llmStream(opts: LLMChatOptions): AsyncIterable<LLMChatStreamItem>
|
|
57
|
+
*
|
|
54
58
|
* Errors (typed subclasses of LoomcycleError; see README for the
|
|
55
59
|
* full HTTP-status → typed-error mapping table):
|
|
56
60
|
* LoomcycleError, AgentNotFoundError, SessionNotFoundError,
|
|
@@ -69,5 +73,5 @@
|
|
|
69
73
|
* See `adapters/ts/README.md` for usage examples.
|
|
70
74
|
*/
|
|
71
75
|
export { LoomcycleClient } from "./client.js";
|
|
72
|
-
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, } from "./types.js";
|
|
76
|
+
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, } from "./types.js";
|
|
73
77
|
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
|
@@ -51,6 +51,10 @@
|
|
|
51
51
|
* listLibrarySkills(): Promise<LibraryListResponse<LibrarySkillDefinition>>
|
|
52
52
|
* listLibraryMcpServers(): Promise<LibraryListResponse<LibraryMcpServerDefinition>>
|
|
53
53
|
*
|
|
54
|
+
* // LLM Gateway (v0.11.0 — direct provider routing, no agent loop)
|
|
55
|
+
* llmChat(opts: LLMChatOptions): Promise<LLMChatResponse>
|
|
56
|
+
* llmStream(opts: LLMChatOptions): AsyncIterable<LLMChatStreamItem>
|
|
57
|
+
*
|
|
54
58
|
* Errors (typed subclasses of LoomcycleError; see README for the
|
|
55
59
|
* full HTTP-status → typed-error mapping table):
|
|
56
60
|
* LoomcycleError, AgentNotFoundError, SessionNotFoundError,
|
package/dist/types.d.ts
CHANGED
|
@@ -879,3 +879,151 @@ export interface LibraryEntry<T = unknown> {
|
|
|
879
879
|
export interface LibraryListResponse<T = unknown> {
|
|
880
880
|
entries: LibraryEntry<T>[];
|
|
881
881
|
}
|
|
882
|
+
/** One message in the gateway conversation. Mirrors LangChain's
|
|
883
|
+
* BaseMessage shape so consumers map without re-shaping. */
|
|
884
|
+
export interface LLMChatMessage {
|
|
885
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
886
|
+
/** Flat string content. For "assistant" turns with tool_calls,
|
|
887
|
+
* the content may be empty. For "tool" turns, this is the tool
|
|
888
|
+
* result text. */
|
|
889
|
+
content?: string;
|
|
890
|
+
/** Set on "assistant" turns that requested tool invocations. */
|
|
891
|
+
tool_calls?: LLMChatToolCall[];
|
|
892
|
+
/** Set on "tool" turns; correlates back to the assistant's
|
|
893
|
+
* tool_calls[].id. */
|
|
894
|
+
tool_call_id?: string;
|
|
895
|
+
}
|
|
896
|
+
/** One assistant-requested tool invocation. */
|
|
897
|
+
export interface LLMChatToolCall {
|
|
898
|
+
id: string;
|
|
899
|
+
name: string;
|
|
900
|
+
input: Record<string, unknown>;
|
|
901
|
+
}
|
|
902
|
+
/** Tool the model may call. The substrate translates this into the
|
|
903
|
+
* driver-native shape (Anthropic input_schema vs OpenAI function.
|
|
904
|
+
* parameters vs Gemini function_declarations) — caller passes the
|
|
905
|
+
* flat JSON schema and trusts the gateway's per-driver translation. */
|
|
906
|
+
export interface LLMTool {
|
|
907
|
+
name: string;
|
|
908
|
+
description?: string;
|
|
909
|
+
input_schema: Record<string, unknown>;
|
|
910
|
+
}
|
|
911
|
+
/** Request body for llmChat / llmStream.
|
|
912
|
+
*
|
|
913
|
+
* Two RFC-mentioned fields are deliberately absent in v1:
|
|
914
|
+
* - `stop_sequences`: providers.Request has no matching field today;
|
|
915
|
+
* accepting it would silently drop it. Lands when the providers
|
|
916
|
+
* package surface grows the equivalent.
|
|
917
|
+
* - `user_bearer`: the gateway calls provider.Call() directly with
|
|
918
|
+
* no MCP transport, so `${run.user_bearer}` substitution has
|
|
919
|
+
* nowhere to apply. Lands when the gateway grows an MCP path. */
|
|
920
|
+
export interface LLMChatOptions {
|
|
921
|
+
messages: LLMChatMessage[];
|
|
922
|
+
tools?: LLMTool[];
|
|
923
|
+
max_tokens?: number;
|
|
924
|
+
temperature?: number | null;
|
|
925
|
+
/** Routing hint. When set with `model`, the resolver short-circuits
|
|
926
|
+
* to that explicit pin. When set alone, the resolver picks the
|
|
927
|
+
* best model in that provider given tier/user_tier. */
|
|
928
|
+
provider?: string;
|
|
929
|
+
/** Routing hint. When set with `provider`, explicit pin. When set
|
|
930
|
+
* alone, the resolver picks the provider hosting that model. */
|
|
931
|
+
model?: string;
|
|
932
|
+
/** Tier for resolver dispatch. Defaults to "default" when neither
|
|
933
|
+
* pin nor tier supplied. */
|
|
934
|
+
tier?: string;
|
|
935
|
+
/** Per-user quota tracking. Empty bypasses the per-user cap. */
|
|
936
|
+
user_id?: string;
|
|
937
|
+
/** Per-user tier overlay; takes precedence over `tier` when set. */
|
|
938
|
+
user_tier?: string;
|
|
939
|
+
/** Optional AbortSignal for caller-driven cancellation. */
|
|
940
|
+
signal?: AbortSignal;
|
|
941
|
+
}
|
|
942
|
+
/** Non-streaming response shape. */
|
|
943
|
+
export interface LLMChatResponse {
|
|
944
|
+
/** Per-response id (llm_<hex>); useful in audit logs. */
|
|
945
|
+
id: string;
|
|
946
|
+
/** Per-request id (req_<hex>); cross-references the audit log. */
|
|
947
|
+
request_id: string;
|
|
948
|
+
/** Which provider the resolver picked. */
|
|
949
|
+
provider: string;
|
|
950
|
+
/** Specific model id picked. */
|
|
951
|
+
model: string;
|
|
952
|
+
/** Content blocks; one per text or tool_use output. */
|
|
953
|
+
content: LLMChatContent[];
|
|
954
|
+
stop_reason: "end_turn" | "max_tokens" | "tool_use" | "stop_sequence";
|
|
955
|
+
usage: LLMChatUsage;
|
|
956
|
+
}
|
|
957
|
+
/** One output content block. */
|
|
958
|
+
export type LLMChatContent = {
|
|
959
|
+
type: "text";
|
|
960
|
+
text: string;
|
|
961
|
+
} | {
|
|
962
|
+
type: "tool_use";
|
|
963
|
+
id: string;
|
|
964
|
+
name: string;
|
|
965
|
+
input: Record<string, unknown>;
|
|
966
|
+
};
|
|
967
|
+
/** Token-accounting payload. Cache fields are populated only on
|
|
968
|
+
* providers that surface them (Anthropic today). */
|
|
969
|
+
export interface LLMChatUsage {
|
|
970
|
+
input_tokens: number;
|
|
971
|
+
output_tokens: number;
|
|
972
|
+
cache_creation_input_tokens?: number;
|
|
973
|
+
cache_read_input_tokens?: number;
|
|
974
|
+
}
|
|
975
|
+
/** One streaming-mode SSE frame. The `kind` field is the SSE event
|
|
976
|
+
* name; the `payload` carries the per-frame shape. v1 mirrors
|
|
977
|
+
* Anthropic's streaming event names. */
|
|
978
|
+
export type LLMChatStreamItem = {
|
|
979
|
+
kind: "provider_chosen";
|
|
980
|
+
payload: {
|
|
981
|
+
provider: string;
|
|
982
|
+
model: string;
|
|
983
|
+
request_id: string;
|
|
984
|
+
};
|
|
985
|
+
} | {
|
|
986
|
+
kind: "content_block_start";
|
|
987
|
+
payload: {
|
|
988
|
+
index: number;
|
|
989
|
+
block: LLMChatContent;
|
|
990
|
+
};
|
|
991
|
+
} | {
|
|
992
|
+
kind: "content_block_delta";
|
|
993
|
+
payload: {
|
|
994
|
+
index: number;
|
|
995
|
+
delta: LLMChatStreamDelta;
|
|
996
|
+
};
|
|
997
|
+
} | {
|
|
998
|
+
kind: "content_block_stop";
|
|
999
|
+
payload: {
|
|
1000
|
+
index: number;
|
|
1001
|
+
};
|
|
1002
|
+
} | {
|
|
1003
|
+
kind: "message_delta";
|
|
1004
|
+
payload: {
|
|
1005
|
+
delta: {
|
|
1006
|
+
stop_reason?: string;
|
|
1007
|
+
};
|
|
1008
|
+
usage: LLMChatUsage;
|
|
1009
|
+
};
|
|
1010
|
+
} | {
|
|
1011
|
+
kind: "done";
|
|
1012
|
+
payload: {
|
|
1013
|
+
id: string;
|
|
1014
|
+
stop_reason: string;
|
|
1015
|
+
usage: LLMChatUsage;
|
|
1016
|
+
};
|
|
1017
|
+
} | {
|
|
1018
|
+
kind: "error";
|
|
1019
|
+
payload: {
|
|
1020
|
+
type: string;
|
|
1021
|
+
code: string;
|
|
1022
|
+
message: string;
|
|
1023
|
+
};
|
|
1024
|
+
};
|
|
1025
|
+
export interface LLMChatStreamDelta {
|
|
1026
|
+
type: "text_delta" | "input_json_delta";
|
|
1027
|
+
text?: string;
|
|
1028
|
+
partial_json?: string;
|
|
1029
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomcycle/client",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "TypeScript client for the loomcycle sidecar (HTTP+SSE).
|
|
3
|
+
"version": "0.11.0",
|
|
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).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|