@loomcycle/client 1.121.0 → 1.122.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/types.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * `client.ts` for the input shapes (RunOptions, CreateSnapshotOptions,
8
8
  * etc.) — those are translated to snake_case in the request body.
9
9
  */
10
- export type EventType = "started" | "text" | "tool_call" | "tool_result" | "usage" | "done" | "error" | "retry" | "host_widened" | "session" | "agent" | "awaiting_input" | "awaiting_review" | "subagent_hold" | "awaiting_children" | "children_note" | "steer" | "context_compaction" | "capability_inert" | "hook_decision" | "limit" | "override" | "context_recap" | "context_state" | "context_distill_declined" | "context_exhausted" | "thinking" | "team_decision" | "turn_cancelled" | "provider_fallback" | "fallback_suppressed" | "model_downgraded" | "cache_invalidated" | "reasoning_invalidated" | "channel_publish" | "channel_delivery" | "interruption_pending" | "spawn_child_started" | "spawn_child_result" | "spawn_child_read" | "prompt_snapshot" | "queued" | "admitted" | "call_queued" | "call_admitted" | "_meta";
10
+ export type EventType = "started" | "text" | "tool_call" | "tool_result" | "usage" | "done" | "error" | "retry" | "host_widened" | "session" | "agent" | "awaiting_input" | "awaiting_review" | "subagent_hold" | "awaiting_children" | "children_note" | "steer" | "context_compaction" | "capability_inert" | "hook_decision" | "limit" | "file_captured" | "override" | "context_recap" | "context_state" | "context_distill_declined" | "context_exhausted" | "thinking" | "team_decision" | "turn_cancelled" | "provider_fallback" | "fallback_suppressed" | "model_downgraded" | "cache_invalidated" | "reasoning_invalidated" | "channel_publish" | "channel_delivery" | "interruption_pending" | "spawn_child_started" | "spawn_child_result" | "spawn_child_read" | "prompt_snapshot" | "queued" | "admitted" | "call_queued" | "call_admitted" | "_meta";
11
11
  export interface ToolUse {
12
12
  id: string;
13
13
  name: string;
@@ -445,6 +445,23 @@ export interface AdmissionInfo {
445
445
  /** On `call_queued` / `call_admitted`: the call lane's model kind (`"chat"`). */
446
446
  kind?: string;
447
447
  }
448
+ /** Payload on `event: file_captured`: a file a tool returned, as the runtime
449
+ * kept it in the run's inbox volume. Never the bytes, never a URL's query. */
450
+ export interface FileCapturedInfo {
451
+ /** The file's reference, `volume:inbox:<dir>/<name>`. */
452
+ ref: string;
453
+ media_type: string;
454
+ /** Length in bytes. */
455
+ size: number;
456
+ /** Hex SHA-256 of the bytes. */
457
+ sha256: string;
458
+ /** Which producer returned it: `mcp:<server>/<tool>`, `http`, `webfetch` or
459
+ * `download:<host>`. */
460
+ origin: string;
461
+ /** The run whose tool call returned it (a sub-agent's capture is reported
462
+ * on the tree's stream). */
463
+ run_id?: string;
464
+ }
448
465
  export interface LimitInfo {
449
466
  /** Which axis tripped: "operator" | "tenant" | "user". */
450
467
  scope: string;
@@ -685,6 +702,9 @@ export interface AgentEvent {
685
702
  /** Payload on `event: limit` (RFC AW) — a per-scope token-budget crossing.
686
703
  * Nil on all other event types. */
687
704
  limit?: LimitInfo;
705
+ /** Payload on `event: file_captured` — a file a tool returned, kept in the
706
+ * run's inbox. Nil on all other event types. */
707
+ file?: FileCapturedInfo;
688
708
  /** Payload on `event: queued` (why the run waits, and its place) and
689
709
  * `event: admitted` (how long it waited), and on `event: call_queued` /
690
710
  * `event: call_admitted` (the same for one model call, with its provider
@@ -1499,6 +1519,15 @@ export interface RunSpec {
1499
1519
  * own `crypto_scopes` were narrowed to, and are narrowed to again on
1500
1520
  * resume. Absent: the parent held none. */
1501
1521
  crypto_scopes?: string[];
1522
+ /** The parent run's shell-credential narrowing at spawn (RFC EW): the
1523
+ * names the child's own `shell_credentials` were narrowed to, and are
1524
+ * narrowed to again on resume. Absent: the parent narrowed nothing. `[]`:
1525
+ * the parent allowed none. */
1526
+ shell_credentials?: string[];
1527
+ /** The parent run's Git network grant at spawn (RFC FB): the operations
1528
+ * the child's own `git_remote` was narrowed to, and is narrowed to again
1529
+ * on resume. Absent: the parent had none. */
1530
+ git_remote?: Array<'fetch' | 'push'>;
1502
1531
  /** The override offer the child passes on to its own children: its
1503
1532
  * parent's, unchanged, so a resume offers what the live child did. Only
1504
1533
  * a child of the offering run's definition (`def_id`, else `agent_name`)
@@ -1801,6 +1830,22 @@ export interface ErasureResidue {
1801
1830
  sessions_examined: number;
1802
1831
  truncated: boolean;
1803
1832
  }
1833
+ /** One bearer token an erasure names: its def id and name, never the bearer. */
1834
+ export interface ErasureTokenRef {
1835
+ def_id: string;
1836
+ name: string;
1837
+ }
1838
+ /**
1839
+ * What an erasure removes from the subject's authority — in a report or a dry
1840
+ * run, what it would: the groups the subject leaves, the lists its bindings
1841
+ * (and its tokens' bindings) named, and the member tokens revoked.
1842
+ * Config-declared rows are not listed; the store cannot remove them.
1843
+ */
1844
+ export interface ErasureAccess {
1845
+ groups: string[];
1846
+ lists: string[];
1847
+ tokens: ErasureTokenRef[];
1848
+ }
1804
1849
  /** Result of {@link LoomcycleClient.erasureReport} (RFC BL P5). */
1805
1850
  export interface ErasureReport {
1806
1851
  tenant: string;
@@ -1808,6 +1853,7 @@ export interface ErasureReport {
1808
1853
  tier1_covered: ErasureTier;
1809
1854
  tier2_uncovered: ErasureTier;
1810
1855
  tier3_residue: ErasureResidue;
1856
+ access: ErasureAccess;
1811
1857
  notes: string[];
1812
1858
  /** Planes that could not be READ. Non-empty means every count is a lower bound. */
1813
1859
  errors?: string[];
@@ -1821,6 +1867,8 @@ export interface ErasureResult {
1821
1867
  /** Plane -> why it was kept. Never empty. */
1822
1868
  retained: Record<string, string>;
1823
1869
  residue: ErasureResidue;
1870
+ /** The groups, lists and member tokens removed (or, in a dry run, that would be). */
1871
+ access: ErasureAccess;
1824
1872
  errors?: string[];
1825
1873
  notes: string[];
1826
1874
  }
@@ -2059,6 +2107,26 @@ export interface WhoamiResponse {
2059
2107
  is_admin: boolean;
2060
2108
  legacy: boolean;
2061
2109
  open_mode?: boolean;
2110
+ /** The deployment's access-control rollout mode: `compat`, `shadow` or
2111
+ * `enforce`. Absent on a server that predates access-control lists. */
2112
+ acl_mode?: AclMode;
2113
+ /** The caller's groups, transitive. Absent when none were resolved. */
2114
+ groups?: string[];
2115
+ /** The version of the caller's compiled access-control set. Absent in open
2116
+ * mode and when the set could not be resolved. */
2117
+ acl_version?: number;
2118
+ /** What the caller may reach, as the server's own gates would answer it.
2119
+ * Absent on a server that predates the summary. */
2120
+ effective?: WhoamiEffective;
2121
+ }
2122
+ /** GET /v1/_me's capability summary. Bounded and non-secret: a fixed list of
2123
+ * Web UI pages, no per-instance data. */
2124
+ export interface WhoamiEffective {
2125
+ /** Per Web UI page id (`run`, `runs`, `channels`, `access`, `users`, …),
2126
+ * whether a request to the route the page loads first would pass the
2127
+ * route's scope gate and its access-control question in the current mode.
2128
+ * Every page is true in open mode. */
2129
+ surfaces: Record<string, boolean>;
2062
2130
  }
2063
2131
  export type RuntimeStateStatus = "running" | "pausing" | "paused";
2064
2132
  /** A timed override of an agent's no-trace mode: until `until`, runs of
@@ -3928,6 +3996,15 @@ export interface EnsureMcpServerOptions {
3928
3996
  * loomcycle's idempotent create dedup the re-registration. */
3929
3997
  headers?: Record<string, string>;
3930
3998
  description?: string;
3999
+ /** How the server's text results reach the model. `"passthrough"` (the
4000
+ * default) hands them over as they came. `"capture"` keeps a file the
4001
+ * server returns as base64 inside a text block — the whole block, or a
4002
+ * JSON string field such as Microsoft Graph's `contentBytes` — in the
4003
+ * run's inbox and hands the model a one-line reference instead. Opt in
4004
+ * only for a server that returns files that way: a long opaque token
4005
+ * could otherwise look like one. Part of the registration's content, so
4006
+ * changing it mints a new version. Sent as the overlay's `binary_results`. */
4007
+ binaryResults?: "passthrough" | "capture";
3931
4008
  /** Force a `tools/list` refresh after registering. Default false.
3932
4009
  *
3933
4010
  * You usually do NOT need this: registration auto-discovers the upstream's
@@ -4186,6 +4263,19 @@ export interface AgentDefOverlay {
4186
4263
  * only. Held to the author's own grant; a sub-agent holds only what its
4187
4264
  * parent run also holds. */
4188
4265
  crypto_scopes?: string[];
4266
+ /** Which operator-listed credentials the agent's `Bash` and Bashbox host
4267
+ * commands receive (RFC EW): only these names of
4268
+ * `LOOMCYCLE_BASH_ALLOWED_CREDS` / `LOOMCYCLE_BASHBOX_FALLBACK_ALLOWED_CREDS`.
4269
+ * Unset = every credential the operator lists; `[]` = none; never adds one.
4270
+ * Held to the author's own narrowing; a sub-agent gets only the names its
4271
+ * parent run also allows. */
4272
+ shell_credentials?: string[];
4273
+ /** Which network operations the agent's `Git` tool may perform (RFC FB):
4274
+ * `['fetch']` (clone, fetch, pull, ls_remote) or `['fetch', 'push']`.
4275
+ * Unset or `[]` = none, local repositories only; `push` needs `fetch`.
4276
+ * Held to the author's own grant; a sub-agent may perform an operation
4277
+ * only when its parent run also may. */
4278
+ git_remote?: Array<'fetch' | 'push'>;
4189
4279
  /** Channel tool ACL (default-deny until set). */
4190
4280
  channels?: AgentChannelACL;
4191
4281
  /** Interruption tool gate — `enabled: true` REQUIRED for the tool to work. */
@@ -4881,6 +4971,10 @@ export interface LibraryEntry<T = unknown> {
4881
4971
  active_def_id?: string;
4882
4972
  latest_version?: number;
4883
4973
  last_updated?: string;
4974
+ /** /v1/_library/agents only: the context window, in tokens, a run of
4975
+ * this agent starts with — the resolved provider's window, lowered by
4976
+ * the agent's own max_context_tokens. Omitted when unknown. */
4977
+ context_window?: number;
4884
4978
  /** Static-side definition body. Omitted when in_static is false
4885
4979
  * (dynamic-only entries have no static body — query the substrate
4886
4980
  * via AgentDef/SkillDef/MCPServerDef tools to fetch the active
@@ -5732,16 +5826,20 @@ export interface DefNameSummary {
5732
5826
  export interface DefNamesResponse {
5733
5827
  names: DefNameSummary[];
5734
5828
  }
5735
- /** One token name's summary from {@link LoomcycleClient.listOperatorTokenDefNames}.
5736
- * Carries no secret material. */
5829
+ /** One (tenant, token name) summary from {@link LoomcycleClient.listOperatorTokenDefNames}.
5830
+ * A per-user (`u-`) name repeats across tenants, so it can appear once per
5831
+ * tenant. Carries no secret material. */
5737
5832
  export interface OperatorTokenDefNameSummary {
5738
5833
  name: string;
5739
5834
  tenant_id: string;
5740
5835
  subject: string;
5741
- /** Every token minted under the name, rotated and retired ones included. */
5836
+ /** Every token minted under the name in this tenant, rotated and retired ones included. */
5742
5837
  token_count: number;
5743
- /** A non-retired token exists. */
5838
+ /** A non-retired, unexpired token exists. */
5744
5839
  has_current: boolean;
5840
+ /** The newest live token's def_id; absent when none is live. Rotate or
5841
+ * retire by it: a per-user name is refused as a target. */
5842
+ current_def_id?: string;
5745
5843
  last_updated: string;
5746
5844
  }
5747
5845
  /** Response of {@link LoomcycleClient.listOperatorTokenDefNames}. */
@@ -5913,6 +6011,49 @@ export interface RoutingResponse {
5913
6011
  throughput_mode?: string;
5914
6012
  /** Absent when no search providers are configured. */
5915
6013
  search?: SearchRoutingProvider[];
6014
+ /** The memory embedder. Absent when none is configured. */
6015
+ embedder?: RoutingEmbedder;
6016
+ /** The decision models. Absent when none are configured. */
6017
+ decision?: RoutingDecision;
6018
+ }
6019
+ /** The memory embedder in {@link RoutingResponse}. `state` is what its calls
6020
+ * did since boot, not a probe: `untried` means nothing has been embedded yet.
6021
+ * No error text or address is reported. */
6022
+ export interface RoutingEmbedder {
6023
+ state: "untried" | "ok" | "failing";
6024
+ provider?: string;
6025
+ model?: string;
6026
+ /** The `models:` alias `memory.embedder` names, when it names one. */
6027
+ alias?: string;
6028
+ /** Absent until the embedder has learned it. */
6029
+ dimension?: number;
6030
+ calls: number;
6031
+ failures: number;
6032
+ last_failure_kind?: string;
6033
+ last_ok_unix?: number;
6034
+ last_failure_unix?: number;
6035
+ }
6036
+ /** The decision block in {@link RoutingResponse}. */
6037
+ export interface RoutingDecision {
6038
+ /** The model a call that names none is asked. */
6039
+ default: string;
6040
+ models: RoutingDecisionModel[];
6041
+ }
6042
+ /** One decision model. The state fields are its provider's probe; all three are
6043
+ * absent when the provider was never probed, and `listed` is also absent while
6044
+ * the provider is unreachable. Under the operator-key gate a tenant sees only
6045
+ * the models it can key. */
6046
+ export interface RoutingDecisionModel {
6047
+ /** What a caller names: a `models:` alias or a model name. */
6048
+ name: string;
6049
+ provider: string;
6050
+ model: string;
6051
+ default?: boolean;
6052
+ /** Reachable and listed. */
6053
+ available?: boolean;
6054
+ reachable?: boolean;
6055
+ /** The provider's model list carries the model (for Ollama: it is pulled). */
6056
+ listed?: boolean;
5916
6057
  }
5917
6058
  /** Response of {@link LoomcycleClient.listProviderModels}: a live listing from
5918
6059
  * the provider, not the cached probe matrix. */
@@ -6050,3 +6191,337 @@ export interface StreamChangesOptions {
6050
6191
  /** Abort to close the stream; the iterator then throws an `AbortError`. */
6051
6192
  signal?: AbortSignal;
6052
6193
  }
6194
+ /** The access-control rollout mode a deployment runs in. */
6195
+ export type AclMode = "compat" | "shadow" | "enforce";
6196
+ /** Marks an entry the config declares rather than the store holds. */
6197
+ export type AclSource = "config";
6198
+ export type AclEffect = "allow" | "deny";
6199
+ /** What a binding attaches a list to. `tenant` is everyone in the tenant. */
6200
+ export type AclSubjectKind = "user" | "group" | "token" | "tenant";
6201
+ /** The closed `when` set of a rule. Every present field narrows the rule; an
6202
+ * absent one does not. */
6203
+ export interface AclCondition {
6204
+ /** The request arrived on one of these (see `AclCatalog.transports`). */
6205
+ transport?: string[];
6206
+ /** A wall-clock window: on one of `days` (`mon`…`sun`), inside
6207
+ * `between: [from, to)` (`HH:MM`), in `tz` (an IANA zone). */
6208
+ time?: {
6209
+ days?: string[];
6210
+ between?: string[];
6211
+ tz?: string;
6212
+ };
6213
+ interactive?: boolean;
6214
+ tier?: string[];
6215
+ user_tier?: string[];
6216
+ source_cidr?: string[];
6217
+ owner_is_self?: boolean;
6218
+ /** Inside a run: the run's agent matches this glob. */
6219
+ agent?: string;
6220
+ /** The run's spawn depth is at most `max`. */
6221
+ depth?: {
6222
+ max: number;
6223
+ };
6224
+ }
6225
+ /** One rule: `effect` on any of `actions` over any of `resources`
6226
+ * (`type:selector`, e.g. `agent:reviewer-*`), when `when` holds. */
6227
+ export interface AclRule {
6228
+ effect: AclEffect;
6229
+ actions: string[];
6230
+ resources: string[];
6231
+ when?: AclCondition;
6232
+ description?: string;
6233
+ }
6234
+ /** A rule list as written: a built-in baseline, or a draft list for
6235
+ * {@link LoomcycleClient.authzSimulate}. */
6236
+ export interface AclList {
6237
+ name: string;
6238
+ description?: string;
6239
+ rules: AclRule[];
6240
+ }
6241
+ /** One rule list: a stored one, or (`source: "config"`) one the config
6242
+ * declares, which has only a name, a description and its rules. */
6243
+ export interface AclDefRow {
6244
+ tenant_id?: string;
6245
+ name: string;
6246
+ /** Bumped on every write. Absent on a config list. */
6247
+ version?: number;
6248
+ content_sha256?: string;
6249
+ catalog_version?: number;
6250
+ rules: AclRule[];
6251
+ description?: string;
6252
+ created_at?: string;
6253
+ updated_at?: string;
6254
+ created_by?: string;
6255
+ /** Set once the list is retired; absent while it is live. */
6256
+ retired_at?: string;
6257
+ source?: AclSource;
6258
+ }
6259
+ /** `aclDef({op: "list"})`. `builtin` is the code-defined baselines, which no
6260
+ * call can change. */
6261
+ export interface AclDefListResponse {
6262
+ acls: AclDefRow[];
6263
+ builtin: AclList[];
6264
+ }
6265
+ /** `GET /v1/_acldef/names`: every live list name the tenant's bindings can
6266
+ * reach, stored and config, sorted. */
6267
+ export interface AclDefNamesResponse {
6268
+ names: string[];
6269
+ }
6270
+ /** `aclDef({op: "validate"})` on rules the server accepts. Rules it refuses
6271
+ * are a 400 (`acl_invalid`) naming the fault. */
6272
+ export interface AclValidateResult {
6273
+ valid: boolean;
6274
+ /** How many rules were read. */
6275
+ rules: number;
6276
+ catalog_version: number;
6277
+ }
6278
+ /** One resource type of the catalog: its verbs, and for a scoped type the
6279
+ * scopes a selector may name (`separator` joins scope and name). */
6280
+ export interface AclCatalogType {
6281
+ type: string;
6282
+ verbs: string[];
6283
+ scopes?: string[];
6284
+ separator?: string;
6285
+ }
6286
+ /** `aclDef({op: "catalog"})`: what a rule may name. */
6287
+ export interface AclCatalog {
6288
+ catalog_version: number;
6289
+ types: AclCatalogType[];
6290
+ transports: string[];
6291
+ }
6292
+ /** The ops of the AclDef family. `create`, `update` and `put` are the same
6293
+ * upsert. */
6294
+ export type AclDefOp = "create" | "update" | "put" | "get" | "list" | "retire" | "validate" | "catalog" | "names";
6295
+ /** The input of {@link LoomcycleClient.aclDef}. `name` is required by
6296
+ * create/update/put/get/retire, `rules` by create/update/put/validate,
6297
+ * `include_retired` is read by list. */
6298
+ export interface AclDefInput {
6299
+ op: AclDefOp;
6300
+ name?: string;
6301
+ rules?: AclRule[];
6302
+ description?: string;
6303
+ include_retired?: boolean;
6304
+ }
6305
+ /** One group: a stored one, or (`source: "config"`) one the config declares,
6306
+ * which lists its direct `members` (subjects) and member `groups` inline and
6307
+ * has no timestamps. A stored group's members come from
6308
+ * {@link LoomcycleClient.getGroup}. */
6309
+ export interface GroupRow {
6310
+ tenant_id?: string;
6311
+ name: string;
6312
+ description?: string;
6313
+ /** Set on a group an identity provider owns: its members are managed there,
6314
+ * and a write here is refused (409 `group_external`). */
6315
+ external_id?: string;
6316
+ created_at?: string;
6317
+ updated_at?: string;
6318
+ created_by?: string;
6319
+ source?: AclSource;
6320
+ members?: string[];
6321
+ groups?: string[];
6322
+ }
6323
+ export type GroupMemberKind = "user" | "group";
6324
+ /** One direct membership edge of a stored group. */
6325
+ export interface GroupMember {
6326
+ tenant_id?: string;
6327
+ group: string;
6328
+ member_kind: GroupMemberKind;
6329
+ member_id: string;
6330
+ added_at: string;
6331
+ added_by?: string;
6332
+ }
6333
+ export interface GroupListResponse {
6334
+ groups: GroupRow[];
6335
+ }
6336
+ /** `GET /v1/_groups/{name}`: a stored group with its direct members. */
6337
+ export interface GroupDetail {
6338
+ group: GroupRow;
6339
+ members: GroupMember[] | null;
6340
+ /** Every group a member of this one is also in, transitively, this one
6341
+ * included. */
6342
+ contained_in: string[] | null;
6343
+ }
6344
+ /** `GET /v1/_groups/{name}/effective`: everyone the group holds, at any
6345
+ * nesting depth, config-declared members included. */
6346
+ export interface GroupEffective {
6347
+ group: string;
6348
+ /** User subjects, sorted. */
6349
+ users: string[];
6350
+ /** The nested groups walked, sorted (the group itself excluded). */
6351
+ groups: string[];
6352
+ }
6353
+ /** The body of {@link LoomcycleClient.createGroup}: an upsert by name. */
6354
+ export interface CreateGroupBody {
6355
+ name: string;
6356
+ description?: string;
6357
+ external_id?: string;
6358
+ }
6359
+ /** What a membership write reports. `removed` is set by a removal. */
6360
+ export interface GroupMemberChange {
6361
+ group: string;
6362
+ kind: GroupMemberKind;
6363
+ id: string;
6364
+ removed?: boolean;
6365
+ }
6366
+ /** One binding of a list to a subject: a stored one, or (`source: "config"`)
6367
+ * one the config declares, which has no `binding_id` and no timestamps. */
6368
+ export interface AclBinding {
6369
+ binding_id?: string;
6370
+ tenant_id?: string;
6371
+ acl: string;
6372
+ subject_kind: AclSubjectKind;
6373
+ /** Absent for a tenant-wide binding. */
6374
+ subject_id?: string;
6375
+ /** Absent when the binding never expires. */
6376
+ expires_at?: string;
6377
+ created_at?: string;
6378
+ created_by?: string;
6379
+ /** Set once retired; absent while live. */
6380
+ retired_at?: string;
6381
+ source?: AclSource;
6382
+ }
6383
+ export interface AclBindingListResponse {
6384
+ bindings: AclBinding[];
6385
+ }
6386
+ /** The body of {@link LoomcycleClient.createAclBinding}. The list must exist
6387
+ * and `expires_at` (RFC 3339) must be in the future, or the server refuses
6388
+ * with 400 `acl_binding_invalid`. */
6389
+ export interface CreateAclBindingBody {
6390
+ acl: string;
6391
+ subject_kind: AclSubjectKind;
6392
+ subject_id?: string;
6393
+ expires_at?: string;
6394
+ }
6395
+ /** One rule that decided: list, its version, the rule's index, its effect. */
6396
+ export interface AuthzReason {
6397
+ acl: string;
6398
+ version?: number;
6399
+ rule: number;
6400
+ effect: AclEffect;
6401
+ }
6402
+ /** An access-control decision (AuthZEN 1.0 shape). `decision` is true only
6403
+ * when a rule allowed; `outcome` `no_match` means no rule spoke, which in
6404
+ * `compat` and `shadow` mode the scope gate then decides. */
6405
+ export interface AuthzDecision {
6406
+ decision: boolean;
6407
+ outcome: "allow" | "deny" | "no_match";
6408
+ reasons?: AuthzReason[];
6409
+ /** The request crossed a tenant and no rule was read. */
6410
+ tenant_floor?: boolean;
6411
+ mode: AclMode;
6412
+ }
6413
+ /** The request context a rule's `when` is judged against. Omitted fields take
6414
+ * the call's own (`transport` is the transport the call arrived on). */
6415
+ export interface AuthzRequestContext {
6416
+ transport?: string;
6417
+ interactive?: boolean;
6418
+ tier?: string;
6419
+ user_tier?: string;
6420
+ agent?: string;
6421
+ depth?: number;
6422
+ }
6423
+ /** One question: may `subject` do `action` to `resource`? An omitted
6424
+ * `subject` (or one naming the caller) asks about the caller; naming another
6425
+ * subject of the tenant needs a tenant operator. An empty `resource.id` asks
6426
+ * about any instance of the type. */
6427
+ export interface AuthzEvaluationRequest {
6428
+ subject?: {
6429
+ type?: string;
6430
+ id?: string;
6431
+ };
6432
+ action: {
6433
+ name: string;
6434
+ };
6435
+ resource: {
6436
+ type: string;
6437
+ id: string;
6438
+ owner?: string;
6439
+ };
6440
+ context?: AuthzRequestContext;
6441
+ }
6442
+ /** How {@link LoomcycleClient.authzEvaluations} runs its batch. */
6443
+ export type AuthzEvaluationsSemantic = "execute_all" | "deny_on_first_deny" | "permit_on_first_permit";
6444
+ /** A batch of questions for one subject. A top-level `action`, `resource` or
6445
+ * `context` is the default each entry that omits its own inherits. 1 to 256
6446
+ * entries. */
6447
+ export interface AuthzEvaluationsRequest {
6448
+ subject?: {
6449
+ type?: string;
6450
+ id?: string;
6451
+ };
6452
+ action?: {
6453
+ name: string;
6454
+ };
6455
+ resource?: {
6456
+ type: string;
6457
+ id: string;
6458
+ owner?: string;
6459
+ };
6460
+ context?: AuthzRequestContext;
6461
+ evaluations: Array<Partial<Omit<AuthzEvaluationRequest, "subject">>>;
6462
+ options?: {
6463
+ evaluations_semantic?: AuthzEvaluationsSemantic;
6464
+ };
6465
+ }
6466
+ export interface AuthzEvaluationsResponse {
6467
+ evaluations: AuthzDecision[];
6468
+ }
6469
+ /** One rule the engine read for an explanation, matching or not, and why. */
6470
+ export interface AuthzTrace {
6471
+ acl: string;
6472
+ version?: number;
6473
+ rule: number;
6474
+ effect: AclEffect;
6475
+ matched: boolean;
6476
+ why: string;
6477
+ }
6478
+ /** A binding as the engine applied it. */
6479
+ export interface AuthzAppliedBinding {
6480
+ id?: string;
6481
+ acl: string;
6482
+ subject_kind: AclSubjectKind;
6483
+ subject_id?: string;
6484
+ expires_at?: string;
6485
+ }
6486
+ /** `POST /v1/_authz/explain`: the decision, every rule read for the resource's
6487
+ * type, the bound lists that do not exist, the bindings applied, and the
6488
+ * subject's groups. */
6489
+ export interface AuthzExplainResponse {
6490
+ decision: AuthzDecision;
6491
+ traces: AuthzTrace[] | null;
6492
+ missing_acls: string[] | null;
6493
+ applied_bindings: AuthzAppliedBinding[] | null;
6494
+ groups: string[] | null;
6495
+ }
6496
+ /** A draft binding for {@link LoomcycleClient.authzSimulate}. */
6497
+ export interface AuthzDraftBinding {
6498
+ acl: string;
6499
+ subject_kind: AclSubjectKind;
6500
+ subject_id?: string;
6501
+ expires_at?: string;
6502
+ }
6503
+ /** Evaluate questions against a DRAFT: the subject's lists and bindings now,
6504
+ * with `acls` added or replaced by name and `bindings` added. Nothing is
6505
+ * written. 1 to 256 requests. */
6506
+ export interface AuthzSimulateRequest {
6507
+ subject?: {
6508
+ type?: string;
6509
+ id?: string;
6510
+ };
6511
+ acls?: AclList[];
6512
+ bindings?: AuthzDraftBinding[];
6513
+ requests: AuthzEvaluationRequest[];
6514
+ }
6515
+ export interface AuthzSimulateResult {
6516
+ /** The request, echoed. */
6517
+ request: AuthzEvaluationRequest;
6518
+ now: AuthzDecision;
6519
+ with_draft: AuthzDecision;
6520
+ /** The outcome differs between `now` and `with_draft`. */
6521
+ changed: boolean;
6522
+ }
6523
+ export interface AuthzSimulateResponse {
6524
+ results: AuthzSimulateResult[];
6525
+ /** Lists the draft's bindings name that no layer has. */
6526
+ missing_acls: string[] | null;
6527
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loomcycle/client",
3
- "version": "1.121.0",
3
+ "version": "1.122.0",
4
4
  "description": "TypeScript client for the loomcycle sidecar (HTTP+SSE). 71 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. v0.21.0 — run/continue accept optional non-secret `metadata` (repo name, review policy, …) passed to the agent, symmetric with the WebHook/Schedule trigger paths. v0.22.0 — version-aligned lockstep release; no client-surface change (RFC N tenant isolation of the agent/skill/MCP/Schedule/Webhook definition plane + real op-schemas on the builtin MCP meta-tools are both server-side). v0.23.0 — version-aligned lockstep release; no client-surface change (RFCs O/P/R MCP-server hardening + thin client and the RFC Q DeepSeek tool-content fix are all server-side / MCP-transport-side). v0.24.0 — purgeChannel clears a channel's buffered messages without deleting its definition (allowed on yaml-declared channels too, unlike deleteChannel — F20); AgentDefOverlay gains channels / evaluation_scopes / interruption so a COMPLETE interactive/multi-agent agent round-trips over the substrate (F14). (Consolidates the interim 0.24/0.25 package bumps, which were never tag-published, back into lockstep with the loomcycle v0.24.0 tag.) v0.25.0 — adds the RFC S channel fan-in/fan-out client twins: awaitChannels() (wait for any/all/at_least N messages across channels, or a timeout — non-committing) + broadcastChannels() (publish one payload to N channels in one atomic-pre-flight call), the client-facing counterparts of the in-band Channel.await / Channel.broadcast tool ops (the rest of v0.25.0 — the manual-management Web UI console + Context op=time + max_fires self-retiring schedules — is server-side / in-band, no client-surface change). v0.29.1 — Usage gains optional `max_context_tokens` (the serving model's context-window ceiling, stamped by the loop from Provider.Capabilities() on each usage event) so a consumer can render a 'context used / max' gauge without a hard-coded per-model table; additive + optional, no behavior change. (Lockstep catch-up: the field landed in loomcycle v0.29.0 but the adapter publish skipped on a version mismatch; v0.29.1 realigns the package version with the release tag so it publishes.) v0.33.0 — gRPC + TS client parity for the RFC Y external fan-out and the compaction surface: spawnRunBatch() (POST /v1/runs:batch — spawn up to 32 fresh runs concurrently in one call, combined index-aligned envelope, per-child failures in-envelope) + compactRun(runId) (POST /v1/runs/{run_id}/compact — summarize a parked run's context); plus per-run sampling + compaction overrides now accepted on runStreaming / continueSession (an explicit temperature 0 is preserved as deterministic, not dropped as falsy). (The gRPC half adds the matching SpawnRunBatch / CompactRun RPCs + the sampling/compaction fields on RunRequest/ContinueRequest — server-side.) v0.34.0 — version-aligned lockstep release; no client-surface change (context-transform plugins / RFC Z Phase 1a are server-side config; the exp7 hardening pass is server-side; the R2 cross-provider thinking-model downgrade surfaces a new `model_downgraded` SSE event the generic stream passes through unchanged). v0.35.0 — RFC AH dynamic filesystem volumes: volumeDef() (POST /v1/_volumedef — op-discriminated create/get/list/delete/purge; a Volume is flat, so delete unmaps + purge RemoveAll's, no retire/promote/fork) + listVolumes() / listEphemeralVolumes() (GET /v1/_volumes[/ephemeral] — tenant-scoped; host paths redacted for non-operator callers). Tenant-confined; the runtime derives the path inside an operator-blessed dynamic_root, so callers pass name + mode, never a host path. v1.1.1 — RFC AI interactive agentic sessions: an `interactive: true` flag on runStreaming/continueSession (a run that parks at end_turn for steering) + sendRunInput(runId, text) (POST /v1/runs/{id}/input — steer a live run) + streamRunByID(runId, {fromSeq}) (GET /v1/runs/{id}/stream — re-attach by run_id; the operator's prior turns replay as `steer` events so a cold client reconstructs the whole conversation) + a high-level InteractiveSession driver (client.interactiveSession / attachInteractiveSession — events()/send()/cancel(), the adapter port of the Web UI run terminal). The AgentEvent union gains awaiting_input/steer/context_compaction frames. Version-aligned with the loomcycle v1.1.x line so the v1.1.1 tag publishes it (also carrying the previously-unpublished v0.35.0 volume surface). v1.4.0 — RFC AL Path VFS + RFC AK Document on the wire: path(input) (POST /v1/_path — a Unix-like filesystem over Memory/Volumes/Documents; resolve/ls/stat/mkdir/mv/rm) + document(input) (POST /v1/_document — chunked-graph documents; 13 ops, needs SQL Memory on the sidecar). Scope (agent/user/tenant) + tenant are resolved server-side from the authenticated principal, never the wire; an off-run scope:'user' op keys on the principal subject so it interoperates with that user's agent runs. New PathToolInput / DocumentToolInput types; responses are op-varying (unknown — narrow as needed). v1.7.0 — RFC AT image/vision input: the PromptContent union gains an `image` variant ({ type:'image'; media_type: ImageMediaType; data: base64-no-prefix }) accepted in a user segment by runStreaming / continueSession (segments pass through unchanged — no method change). The model must be vision-capable or the run errors before the call. New ImageMediaType type (image/png|jpeg|gif|webp). v1.12.1 — Path/Document browse-by-subject + the full Document op set (RFC AS/AK): path(input, opts) / document(input, opts) accept optional scopeId / tenant browse overrides sent as ?scope_id= / ?tenant= query params (server reads them from the URL, re-checks authorization; omit both to browse your own subject — byte-identical to the pre-RFC-AS request), and DocumentToolInput.op now covers all 16 backend ops (adds set_path, export_md, import_md) with the matching include_metadata / markdown fields. Additive — existing path() / document() callers are unchanged. v1.16.0 — RFC BC client-executed tools (local tool host): connectClientTools({tools,onInvoke}) opens a persistent WebSocket to /v1/client-tools, registers tools this client runs on the user's machine (browser DOM / files / shell), and answers the invoke frames loomcycle routes when an agent of your principal calls a client:<tool> — returning your reply as an ordinary tool result. Returns a ClientToolHost driver (.close() to stop; auto-reconnect); dependency-free (global WebSocket in browsers / Node 22+, or an injected WebSocketImpl like the ws package on older Node); the bearer rides the Sec-WebSocket-Protocol subprotocol (browsers can't set an Authorization header on a WebSocket). The runtime's first WebSocket surface. v1.45.0 — RFC BL P5 subject erasure: erasureReport(subject, {tenant}) (GET /v1/_erasure — what this deployment holds about one subject, in three tiers: deletable with existing primitives, subject-keyed but not deletable, and facts ABOUT the subject in scopes they do not own) + erasureExecute(subject, {dryRun, confirm, tenant}) (POST /v1/_erasure — removes tiers 1 and 2). DEFAULTS TO A DRY RUN: dryRun defaults true and a live run also requires confirm === subject. The tier-3 residue is traceable only through the subject's chats, which a live run deletes, so a report afterwards shows rows: 0 while those facts remain — the returned object is the only durable record of what was not reached; persist it. New ErasureReport / ErasureResult / ErasureTier / ErasureResidue types. v1.47.0 — RFC BV memory-view SDK: memorySearch() (POST /v1/_memory/search — off-run unified semantic search spanning k/v entries AND document-chunk bodies in one ranked list, each hit tagged kind memory|document with chunk_id on document hits) + memoryEmbedStats(scope) + reembedMemory(scope, scopeId, {dryRun,limit}) (the Vector Memory embed-admin reads the memory-view console needs; dry_run defaults true). Fact reads (list_facts + get_chunk's entity block) ride the existing document() passthrough. Additive — existing callers unchanged. v1.61.0 — RFC CJ per-run context-window override: runStreaming / continueSession accept an optional maxContextTokens (integer tokens) that wins over the agent's own max_context_tokens; omitted inherits it (which defers to the provider/driver default). Distinct from a model's output cap; primarily for local inference (Ollama num_ctx). Serialized as the snake_case max_context_tokens field on POST /v1/runs + the continuation body; additive, existing callers unchanged. v1.72.1 — the TeamDef version lifecycle: listTeamVersions(name) (op=list — every version of one team, newest first), promoteTeam(defId) (op=promote — point the active pointer, which is what a run BY NAME executes; forkTeam defaults to promote:false, so authoring and putting in force stay two steps), retireTeam(defId, retired) (op=retire — reversible and version-scoped, unlike deleteTeam) and verifyTeam(name, contentSha256) (op=verify — the drift check for a workflow kept in source control and pushed to several deployments; an absent team answers deployed:false rather than raising). The ops existed on the substrate and over HTTP; a client that could author a team could not put one in force.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",