@cleocode/contracts 2026.6.12 → 2026.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/operation-def.test.js +5 -1
- package/dist/__tests__/operation-def.test.js.map +1 -1
- package/dist/__tests__/provider-def.test.d.ts +12 -0
- package/dist/__tests__/provider-def.test.d.ts.map +1 -0
- package/dist/__tests__/provider-def.test.js +84 -0
- package/dist/__tests__/provider-def.test.js.map +1 -0
- package/dist/__tests__/sealed-credential.test.d.ts +19 -0
- package/dist/__tests__/sealed-credential.test.d.ts.map +1 -0
- package/dist/__tests__/sealed-credential.test.js +74 -0
- package/dist/__tests__/sealed-credential.test.js.map +1 -0
- package/dist/__tests__/service-provider.test.d.ts +17 -0
- package/dist/__tests__/service-provider.test.d.ts.map +1 -0
- package/dist/__tests__/service-provider.test.js +108 -0
- package/dist/__tests__/service-provider.test.js.map +1 -0
- package/dist/__tests__/skill-executor-contract.test.js +3 -0
- package/dist/__tests__/skill-executor-contract.test.js.map +1 -1
- package/dist/acceptance-gate.d.ts +2 -3
- package/dist/acceptance-gate.d.ts.map +1 -1
- package/dist/boundary.d.ts +52 -0
- package/dist/boundary.d.ts.map +1 -1
- package/dist/boundary.js +24 -19
- package/dist/boundary.js.map +1 -1
- package/dist/conduit.d.ts +171 -0
- package/dist/conduit.d.ts.map +1 -1
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +22 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config.d.ts +104 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/data-accessor.d.ts +21 -1
- package/dist/data-accessor.d.ts.map +1 -1
- package/dist/data-accessor.js.map +1 -1
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.d.ts +21 -0
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.d.ts.map +1 -0
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.js +84 -0
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.js.map +1 -0
- package/dist/dispatch/identity.d.ts +1 -1
- package/dist/dispatch/identity.d.ts.map +1 -1
- package/dist/dispatch/identity.js +25 -0
- package/dist/dispatch/identity.js.map +1 -1
- package/dist/dispatch/operation-def.d.ts +20 -0
- package/dist/dispatch/operation-def.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +1044 -182
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/docs/read.d.ts +2 -2
- package/dist/index.d.ts +25 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/lease-ipc/__tests__/freeze.test.d.ts +15 -0
- package/dist/lease-ipc/__tests__/freeze.test.d.ts.map +1 -0
- package/dist/lease-ipc/__tests__/freeze.test.js +313 -0
- package/dist/lease-ipc/__tests__/freeze.test.js.map +1 -0
- package/dist/lease-ipc/index.d.ts +17 -0
- package/dist/lease-ipc/index.d.ts.map +1 -0
- package/dist/lease-ipc/index.js +16 -0
- package/dist/lease-ipc/index.js.map +1 -0
- package/dist/lease-ipc/messages.d.ts +918 -0
- package/dist/lease-ipc/messages.d.ts.map +1 -0
- package/dist/lease-ipc/messages.js +476 -0
- package/dist/lease-ipc/messages.js.map +1 -0
- package/dist/lease-ipc/version.d.ts +41 -0
- package/dist/lease-ipc/version.d.ts.map +1 -0
- package/dist/lease-ipc/version.js +43 -0
- package/dist/lease-ipc/version.js.map +1 -0
- package/dist/llm/catalog-schema.d.ts +242 -0
- package/dist/llm/catalog-schema.d.ts.map +1 -0
- package/dist/llm/catalog-schema.js +153 -0
- package/dist/llm/catalog-schema.js.map +1 -0
- package/dist/llm/catalog-schema.json +139 -0
- package/dist/llm/index.d.ts +15 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +14 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/interfaces.d.ts +23 -0
- package/dist/llm/interfaces.d.ts.map +1 -1
- package/dist/llm/oauth.d.ts +16 -2
- package/dist/llm/oauth.d.ts.map +1 -1
- package/dist/llm/onboarding.d.ts +126 -0
- package/dist/llm/onboarding.d.ts.map +1 -0
- package/dist/llm/onboarding.js +34 -0
- package/dist/llm/onboarding.js.map +1 -0
- package/dist/llm/provider-def.d.ts +254 -0
- package/dist/llm/provider-def.d.ts.map +1 -0
- package/dist/llm/provider-def.js +93 -0
- package/dist/llm/provider-def.js.map +1 -0
- package/dist/llm/sealed-credential.d.ts +164 -0
- package/dist/llm/sealed-credential.d.ts.map +1 -0
- package/dist/llm/sealed-credential.js +43 -0
- package/dist/llm/sealed-credential.js.map +1 -0
- package/dist/llm/system-of-use.d.ts +383 -0
- package/dist/llm/system-of-use.d.ts.map +1 -0
- package/dist/llm/system-of-use.js +238 -0
- package/dist/llm/system-of-use.js.map +1 -0
- package/dist/llm/system-resolver.d.ts +87 -11
- package/dist/llm/system-resolver.d.ts.map +1 -1
- package/dist/llm/system-resolver.js +14 -7
- package/dist/llm/system-resolver.js.map +1 -1
- package/dist/operations/__tests__/ensures-schema-registry.test.d.ts +17 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.d.ts.map +1 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.js +113 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.js.map +1 -0
- package/dist/operations/admin.d.ts +124 -1
- package/dist/operations/admin.d.ts.map +1 -1
- package/dist/operations/ensures-schema-registry.d.ts +172 -0
- package/dist/operations/ensures-schema-registry.d.ts.map +1 -0
- package/dist/operations/ensures-schema-registry.js +226 -0
- package/dist/operations/ensures-schema-registry.js.map +1 -0
- package/dist/operations/entities.d.ts +110 -0
- package/dist/operations/entities.d.ts.map +1 -0
- package/dist/operations/entities.js +695 -0
- package/dist/operations/entities.js.map +1 -0
- package/dist/operations/llm.d.ts +116 -9
- package/dist/operations/llm.d.ts.map +1 -1
- package/dist/operations/output-contracts-data.d.ts.map +1 -1
- package/dist/operations/output-contracts-data.js +230 -0
- package/dist/operations/output-contracts-data.js.map +1 -1
- package/dist/operations/service.d.ts +68 -0
- package/dist/operations/service.d.ts.map +1 -0
- package/dist/operations/service.js +336 -0
- package/dist/operations/service.js.map +1 -0
- package/dist/operations/tasks.d.ts +109 -0
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/operations/tasks.js.map +1 -1
- package/dist/operations/validate.d.ts +1 -12
- package/dist/operations/validate.d.ts.map +1 -1
- package/dist/operations/validate.js +1 -1
- package/dist/playbook.d.ts +116 -0
- package/dist/playbook.d.ts.map +1 -1
- package/dist/release/plan.d.ts +5 -5
- package/dist/session.d.ts +11 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/templates/manifest.d.ts +1 -1
- package/dist/tools/agent-tools.d.ts +231 -0
- package/dist/tools/agent-tools.d.ts.map +1 -0
- package/dist/tools/agent-tools.js +25 -0
- package/dist/tools/agent-tools.js.map +1 -0
- package/dist/tools/atomic.d.ts +19 -0
- package/dist/tools/atomic.d.ts.map +1 -1
- package/dist/tools/atomic.js +17 -0
- package/dist/tools/atomic.js.map +1 -1
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/skill-executor.d.ts +7 -0
- package/dist/tools/skill-executor.d.ts.map +1 -1
- package/dist/tools/web-tools.d.ts +217 -0
- package/dist/tools/web-tools.d.ts.map +1 -0
- package/dist/tools/web-tools.js +31 -0
- package/dist/tools/web-tools.js.map +1 -0
- package/dist/vault/service-provider.d.ts +343 -0
- package/dist/vault/service-provider.d.ts.map +1 -0
- package/dist/vault/service-provider.js +857 -0
- package/dist/vault/service-provider.js.map +1 -0
- package/dist/workgraph.d.ts +12 -12
- package/package.json +14 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/__tests__/operation-def.test.ts +7 -1
- package/src/__tests__/provider-def.test.ts +93 -0
- package/src/__tests__/sealed-credential.test.ts +100 -0
- package/src/__tests__/service-provider.test.ts +129 -0
- package/src/__tests__/skill-executor-contract.test.ts +3 -0
- package/src/acceptance-gate.ts +2 -3
- package/src/boundary.ts +70 -20
- package/src/conduit.ts +200 -0
- package/src/config/index.ts +35 -0
- package/src/config.ts +106 -1
- package/src/data-accessor.ts +22 -1
- package/src/dispatch/__tests__/tasks-gateway-crud-ops.test.ts +99 -0
- package/src/dispatch/identity.ts +25 -0
- package/src/dispatch/operation-def.ts +21 -0
- package/src/dispatch/operations-registry.ts +1083 -176
- package/src/index.ts +240 -25
- package/src/lease-ipc/__tests__/freeze.test.ts +342 -0
- package/src/lease-ipc/index.ts +75 -0
- package/src/lease-ipc/messages.ts +588 -0
- package/src/lease-ipc/version.ts +46 -0
- package/src/llm/catalog-schema.json +139 -0
- package/src/llm/catalog-schema.ts +184 -0
- package/src/llm/index.ts +29 -0
- package/src/llm/interfaces.ts +23 -0
- package/src/llm/oauth.ts +16 -2
- package/src/llm/onboarding.ts +131 -0
- package/src/llm/provider-def.ts +291 -0
- package/src/llm/sealed-credential.ts +166 -0
- package/src/llm/system-of-use.ts +503 -0
- package/src/llm/system-resolver.ts +91 -11
- package/src/operations/__tests__/ensures-schema-registry.test.ts +169 -0
- package/src/operations/admin.ts +144 -0
- package/src/operations/ensures-schema-registry.ts +260 -0
- package/src/operations/entities.ts +758 -0
- package/src/operations/llm.ts +120 -8
- package/src/operations/output-contracts-data.ts +264 -0
- package/src/operations/service.ts +360 -0
- package/src/operations/tasks.ts +119 -0
- package/src/operations/validate.ts +1 -14
- package/src/playbook.ts +117 -0
- package/src/session.ts +11 -0
- package/src/tools/agent-tools.ts +270 -0
- package/src/tools/atomic.ts +21 -0
- package/src/tools/index.ts +46 -0
- package/src/tools/skill-executor.ts +7 -0
- package/src/tools/web-tools.ts +247 -0
- package/src/vault/service-provider.ts +1137 -0
- package/dist/tessera.d.ts +0 -32
- package/dist/tessera.d.ts.map +0 -1
- package/dist/tessera.js +0 -11
- package/dist/tessera.js.map +0 -1
- package/dist/warp-chain.d.ts +0 -129
- package/dist/warp-chain.d.ts.map +0 -1
- package/dist/warp-chain.js +0 -13
- package/dist/warp-chain.js.map +0 -1
- package/src/tessera.ts +0 -35
- package/src/warp-chain.ts +0 -185
package/src/conduit.ts
CHANGED
|
@@ -264,6 +264,206 @@ export interface Conduit {
|
|
|
264
264
|
readonly agentId: string;
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// Channel Adapter (T11952 · epic T11854 · saga T10419)
|
|
269
|
+
// ============================================================================
|
|
270
|
+
//
|
|
271
|
+
// A ChannelAdapter is the boundary between an external conversation surface
|
|
272
|
+
// (a terminal TUI, Telegram chat, Discord channel, …) and the CLEO agent
|
|
273
|
+
// runtime. Each adapter wraps a {@link Transport} (the wire layer) and exposes
|
|
274
|
+
// a uniform, platform-agnostic contract so the Session Store + Delivery Router
|
|
275
|
+
// can route inbound user messages to the agent and route the agent's reply back
|
|
276
|
+
// to the originating channel.
|
|
277
|
+
//
|
|
278
|
+
// The Local-TUI adapter is the FIRST reference adapter (T11952): it rides the
|
|
279
|
+
// in-process {@link Transport} (conduit `LocalTransport`) and works fully
|
|
280
|
+
// offline, daemon-OFF, with no network and no platform credential. Platform
|
|
281
|
+
// adapters (Telegram/Discord/Slack/WhatsApp) implement this same contract but
|
|
282
|
+
// are credential+network gated and out of scope for T11952.
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Liveness verdict for a single channel adapter.
|
|
286
|
+
*
|
|
287
|
+
* - `connected` — the adapter is connected to its transport and ready to
|
|
288
|
+
* receive/send.
|
|
289
|
+
* - `degraded` — the adapter is reachable but operating with reduced capability
|
|
290
|
+
* (e.g. polling fallback, partial subscription).
|
|
291
|
+
* - `disconnected` — the adapter is not currently connected.
|
|
292
|
+
* - `error` — the adapter encountered a fatal error; see {@link ChannelHealth.detail}.
|
|
293
|
+
*/
|
|
294
|
+
export type ChannelHealthStatus = 'connected' | 'degraded' | 'disconnected' | 'error';
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Health snapshot for a single {@link ChannelAdapter}.
|
|
298
|
+
*
|
|
299
|
+
* Surfaced by `cleo channels list` as part of the LAFS RenderableEnvelope and
|
|
300
|
+
* consumed by the Delivery Router to skip dead channels.
|
|
301
|
+
*/
|
|
302
|
+
export interface ChannelHealth {
|
|
303
|
+
/** Stable channel identifier (matches {@link ChannelAdapter.id}). */
|
|
304
|
+
channelId: string;
|
|
305
|
+
/** Coarse liveness verdict. */
|
|
306
|
+
status: ChannelHealthStatus;
|
|
307
|
+
/** Underlying transport name (e.g. `'local'`, `'http'`, `'sse'`). */
|
|
308
|
+
transport: string;
|
|
309
|
+
/** Human-readable detail for non-`connected` states (error message, reason). */
|
|
310
|
+
detail?: string;
|
|
311
|
+
/** ISO 8601 timestamp the health was sampled. */
|
|
312
|
+
checkedAt: string;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Per-channel configuration knobs shared by every {@link ChannelAdapter}.
|
|
317
|
+
*
|
|
318
|
+
* Platform adapters extend this with credential fields; the Local-TUI adapter
|
|
319
|
+
* uses only the platform-agnostic subset.
|
|
320
|
+
*
|
|
321
|
+
* @see T11854 AC1 — `home_channel`, `require_mention`, `allowed_users`.
|
|
322
|
+
*/
|
|
323
|
+
export interface ChannelConfig {
|
|
324
|
+
/**
|
|
325
|
+
* The home channel address replies fall back to when an inbound message has
|
|
326
|
+
* no explicit reply target (e.g. the default conversation/thread id).
|
|
327
|
+
*/
|
|
328
|
+
homeChannel?: string;
|
|
329
|
+
/**
|
|
330
|
+
* When `true`, the adapter only dispatches inbound messages that explicitly
|
|
331
|
+
* mention the agent. Defaults to `false` for the Local-TUI adapter (every
|
|
332
|
+
* line is addressed to the agent).
|
|
333
|
+
*/
|
|
334
|
+
requireMention?: boolean;
|
|
335
|
+
/**
|
|
336
|
+
* Allowlist of sender identifiers permitted to reach the agent. When omitted
|
|
337
|
+
* or empty, all senders are allowed (the Local-TUI default — a single local
|
|
338
|
+
* operator).
|
|
339
|
+
*/
|
|
340
|
+
allowedUsers?: readonly string[];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* An inbound message arriving from a channel surface, normalized into the
|
|
345
|
+
* platform-agnostic shape the Delivery Router consumes.
|
|
346
|
+
*
|
|
347
|
+
* It is a thin projection over {@link ConduitMessage} carrying the originating
|
|
348
|
+
* channel so the router can preserve session affinity.
|
|
349
|
+
*/
|
|
350
|
+
export interface InboundMsg {
|
|
351
|
+
/** Stable message id (from the underlying transport). */
|
|
352
|
+
id: string;
|
|
353
|
+
/** Channel the message originated on (the {@link ChannelAdapter.id}). */
|
|
354
|
+
channelId: string;
|
|
355
|
+
/** Sender identifier within the channel (user/agent id). */
|
|
356
|
+
from: string;
|
|
357
|
+
/** Message text content. */
|
|
358
|
+
content: string;
|
|
359
|
+
/**
|
|
360
|
+
* Channel-native conversation/thread id used for session affinity. The router
|
|
361
|
+
* keys the {@link ChannelSession} on `(channelId, sessionKey)`.
|
|
362
|
+
*/
|
|
363
|
+
sessionKey: string;
|
|
364
|
+
/** ISO 8601 timestamp the message was received. */
|
|
365
|
+
timestamp: string;
|
|
366
|
+
/** Optional structured payload carried alongside the message. */
|
|
367
|
+
payload?: Record<string, unknown>;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* An outbound reply the agent emits in response to an {@link InboundMsg}.
|
|
372
|
+
*
|
|
373
|
+
* The Delivery Router resolves the target channel + session from the originating
|
|
374
|
+
* {@link InboundMsg} (or an explicit {@link OutboundReply.channelId}) and calls
|
|
375
|
+
* {@link ChannelAdapter.send}.
|
|
376
|
+
*/
|
|
377
|
+
export interface OutboundReply {
|
|
378
|
+
/**
|
|
379
|
+
* Target channel id. When omitted, the router routes to the channel that
|
|
380
|
+
* originated the {@link InboundMsg} being replied to (session affinity).
|
|
381
|
+
*/
|
|
382
|
+
channelId?: string;
|
|
383
|
+
/**
|
|
384
|
+
* Target session/thread key. When omitted, the router uses the originating
|
|
385
|
+
* inbound message's {@link InboundMsg.sessionKey}, then the channel's
|
|
386
|
+
* {@link ChannelConfig.homeChannel} fallback.
|
|
387
|
+
*/
|
|
388
|
+
sessionKey?: string;
|
|
389
|
+
/** Reply text content. */
|
|
390
|
+
content: string;
|
|
391
|
+
/** Optional structured payload carried with the reply. */
|
|
392
|
+
payload?: Record<string, unknown>;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* A persisted per-channel session-affinity record.
|
|
397
|
+
*
|
|
398
|
+
* The Session Store tracks the most recent inbound exchange per
|
|
399
|
+
* `(channelId, sessionKey)` so the Delivery Router can route an agent reply
|
|
400
|
+
* back to the originating channel without the caller threading routing state.
|
|
401
|
+
*
|
|
402
|
+
* @see T1797 — Session Store + Delivery Router.
|
|
403
|
+
*/
|
|
404
|
+
export interface ChannelSession {
|
|
405
|
+
/** Channel the session belongs to. */
|
|
406
|
+
channelId: string;
|
|
407
|
+
/** Channel-native conversation/thread key. */
|
|
408
|
+
sessionKey: string;
|
|
409
|
+
/** Sender identifier of the last inbound message in this session. */
|
|
410
|
+
lastFrom: string;
|
|
411
|
+
/** Id of the last inbound message routed for this session. */
|
|
412
|
+
lastInboundId: string;
|
|
413
|
+
/** ISO 8601 timestamp the session was last touched. */
|
|
414
|
+
updatedAt: string;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* The platform-agnostic channel boundary contract.
|
|
419
|
+
*
|
|
420
|
+
* Every channel (Local-TUI, Telegram, Discord, Slack, WhatsApp, …) implements
|
|
421
|
+
* this interface. Adapters wrap a {@link Transport} and translate between the
|
|
422
|
+
* channel-native surface and the normalized {@link InboundMsg} /
|
|
423
|
+
* {@link OutboundReply} shapes the router consumes.
|
|
424
|
+
*
|
|
425
|
+
* Implementations:
|
|
426
|
+
* - `LocalTuiChannelAdapter` (`@cleocode/core` — rides conduit `LocalTransport`,
|
|
427
|
+
* the first reference adapter, T11952).
|
|
428
|
+
* - Platform adapters (Telegram/Discord/Slack/WhatsApp) — credential+network
|
|
429
|
+
* gated, implemented under T11855 (out of scope for T11952).
|
|
430
|
+
*
|
|
431
|
+
* @see T11854 AC1 — start/stop/onMessage/sendMessage/health.
|
|
432
|
+
*/
|
|
433
|
+
export interface ChannelAdapter {
|
|
434
|
+
/** Stable, kebab-case channel identifier (e.g. `'local-tui'`). */
|
|
435
|
+
readonly id: string;
|
|
436
|
+
/** Effective per-channel configuration. */
|
|
437
|
+
readonly config: ChannelConfig;
|
|
438
|
+
|
|
439
|
+
/** Start the adapter: connect its transport and begin receiving. */
|
|
440
|
+
start(): Promise<void>;
|
|
441
|
+
|
|
442
|
+
/** Stop the adapter: detach handlers and disconnect its transport. */
|
|
443
|
+
stop(): Promise<void>;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Stream of inbound messages from the channel.
|
|
447
|
+
*
|
|
448
|
+
* Yields each {@link InboundMsg} as it arrives until {@link ChannelAdapter.stop}
|
|
449
|
+
* is called (which ends the iterator). Honors {@link ChannelConfig.requireMention}
|
|
450
|
+
* and {@link ChannelConfig.allowedUsers} filtering before yielding.
|
|
451
|
+
*/
|
|
452
|
+
receive(): AsyncIterable<InboundMsg>;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Send a reply back to the channel.
|
|
456
|
+
*
|
|
457
|
+
* @param reply - The outbound reply. The adapter resolves the destination
|
|
458
|
+
* session via {@link OutboundReply.sessionKey} then
|
|
459
|
+
* {@link ChannelConfig.homeChannel}.
|
|
460
|
+
*/
|
|
461
|
+
send(reply: OutboundReply): Promise<void>;
|
|
462
|
+
|
|
463
|
+
/** Sample the adapter's current health. */
|
|
464
|
+
health(): ChannelHealth;
|
|
465
|
+
}
|
|
466
|
+
|
|
267
467
|
// ============================================================================
|
|
268
468
|
// Factory
|
|
269
469
|
// ============================================================================
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cleocode/contracts/config` — config-domain contract surface.
|
|
3
|
+
*
|
|
4
|
+
* Subpath barrel that surfaces the `ConfigManifest` contract (the
|
|
5
|
+
* {@link ConfigManifestEntry} shape, its Zod validator
|
|
6
|
+
* {@link configManifestEntrySchema}, and the built-in manifest entries) under a
|
|
7
|
+
* stable, config-scoped import path. This is the AC3 surface for the
|
|
8
|
+
* config-as-domain work (T11917): consumers that only need the manifest contract
|
|
9
|
+
* import from `@cleocode/contracts/config` instead of pulling the full index.
|
|
10
|
+
*
|
|
11
|
+
* The types are also re-exported from the package root (`@cleocode/contracts`)
|
|
12
|
+
* for backwards compatibility — this barrel is an additive, narrower entrypoint.
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
* @module @cleocode/contracts/config
|
|
16
|
+
*
|
|
17
|
+
* @task T11917 — config-as-domain (M5/AC3)
|
|
18
|
+
* @task T9876 — ConfigManifest contract
|
|
19
|
+
* @saga T9855
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export type {
|
|
23
|
+
ConfigManifestEntry,
|
|
24
|
+
ConfigManifestScope,
|
|
25
|
+
ConfigScope,
|
|
26
|
+
DriftDetection,
|
|
27
|
+
} from './manifest.js';
|
|
28
|
+
export {
|
|
29
|
+
CLEO_CONFIG_MANIFEST,
|
|
30
|
+
CONFIG_MANIFEST_ENTRIES,
|
|
31
|
+
configManifestEntrySchema,
|
|
32
|
+
GLOBAL_CLEO_CONFIG_MANIFEST,
|
|
33
|
+
PROJECT_CONTEXT_MANIFEST,
|
|
34
|
+
PROJECT_INFO_MANIFEST,
|
|
35
|
+
} from './manifest.js';
|
package/src/config.ts
CHANGED
|
@@ -475,6 +475,29 @@ export interface LlmProfileTuning {
|
|
|
475
475
|
temperature?: number;
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
+
/**
|
|
479
|
+
* Capability lane a named profile occupies — the hermes "global-base +
|
|
480
|
+
* granular-override" tiering model (E9 · T11745 · T11748).
|
|
481
|
+
*
|
|
482
|
+
* A profile's `tier` is a coarse capability hint a runner can use to pick the
|
|
483
|
+
* right lane for a turn independently of the role/system axis:
|
|
484
|
+
*
|
|
485
|
+
* | Tier | Meaning |
|
|
486
|
+
* |--------------|------------------------------------------------------------------|
|
|
487
|
+
* | `prime` | The flagship reasoning lane — orchestration / hard turns. |
|
|
488
|
+
* | `aux` | The auxiliary lane — cheap background subsystems (the hermes |
|
|
489
|
+
* | | `_AUX_TASKS` default model bucket; see {@link LlmProfileConfig.defaultAuxModel}). |
|
|
490
|
+
* | `background` | The lowest lane — fire-and-forget background work (titles, etc.). |
|
|
491
|
+
*
|
|
492
|
+
* Advisory metadata only: it does NOT alter the provider/model resolution
|
|
493
|
+
* chain in {@link LlmConfig} — it lets callers and diagnostics reason about
|
|
494
|
+
* which lane a profile belongs to without re-deriving it from the model id.
|
|
495
|
+
*
|
|
496
|
+
* @task T11748
|
|
497
|
+
* @epic T11745
|
|
498
|
+
*/
|
|
499
|
+
export type LlmProfileTier = 'prime' | 'aux' | 'background';
|
|
500
|
+
|
|
478
501
|
/**
|
|
479
502
|
* A named, reusable LLM profile.
|
|
480
503
|
*
|
|
@@ -503,6 +526,67 @@ export interface LlmProfileConfig {
|
|
|
503
526
|
credentialLabel?: string;
|
|
504
527
|
/** Optional tuning parameters (max tokens, temperature). */
|
|
505
528
|
params?: LlmProfileTuning;
|
|
529
|
+
/**
|
|
530
|
+
* Optional capability lane this profile occupies (see {@link LlmProfileTier}).
|
|
531
|
+
*
|
|
532
|
+
* Advisory metadata only — does NOT participate in provider/model resolution.
|
|
533
|
+
* Lets callers/diagnostics reason about a profile's lane (prime/aux/background)
|
|
534
|
+
* without re-deriving it from the model id. The hermes tiering model.
|
|
535
|
+
*
|
|
536
|
+
* @task T11748
|
|
537
|
+
*/
|
|
538
|
+
tier?: LlmProfileTier;
|
|
539
|
+
/**
|
|
540
|
+
* Optional default auxiliary model for this profile — the hermes
|
|
541
|
+
* `auxiliary.defaultModel` analog (E9 · T11748).
|
|
542
|
+
*
|
|
543
|
+
* When this profile is a `prime`/global-base binding, `defaultAuxModel` names
|
|
544
|
+
* the cheaper model an aux-tier subsystem should use instead of {@link model}
|
|
545
|
+
* when it has no more-specific binding. Advisory metadata; consumers that want
|
|
546
|
+
* an aux-tier model read this rather than re-selecting a profile.
|
|
547
|
+
*
|
|
548
|
+
* @task T11748
|
|
549
|
+
*/
|
|
550
|
+
defaultAuxModel?: string;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* A per-system LLM binding — the granular override half of the hermes
|
|
555
|
+
* "global-base + granular-override" model (E9 · T11745 · T11748).
|
|
556
|
+
*
|
|
557
|
+
* A {@link LlmConfig.systems} entry pins the provider/model (or a named
|
|
558
|
+
* {@link LlmProfileConfig}) for ONE encoded system-of-use key (e.g.
|
|
559
|
+
* `'sentient'`, `'tool:web-search'`, `'skill:ct-cleo'`). It is consulted in the
|
|
560
|
+
* resolution chain AFTER an explicit role/argument override but BEFORE the
|
|
561
|
+
* global {@link LlmConfig.defaultProfile} — giving each subsystem a targeted
|
|
562
|
+
* override without touching the global base.
|
|
563
|
+
*
|
|
564
|
+
* Either `profile` (a key of {@link LlmConfig.profiles}) OR an inline
|
|
565
|
+
* `provider` + `model` tuple supplies the binding; `profile` wins when both are
|
|
566
|
+
* present. An entry that supplies neither a resolvable `profile` nor a complete
|
|
567
|
+
* `provider`+`model` tuple is structurally incomplete and is skipped (resolution
|
|
568
|
+
* falls through to the next tier) — never an error.
|
|
569
|
+
*
|
|
570
|
+
* @task T11748
|
|
571
|
+
* @epic T11745
|
|
572
|
+
*/
|
|
573
|
+
export interface SystemBinding {
|
|
574
|
+
/**
|
|
575
|
+
* Optional reference to a named profile in {@link LlmConfig.profiles}. When
|
|
576
|
+
* set and resolvable, the named profile's provider/model/credentialLabel win
|
|
577
|
+
* over this entry's inline `provider`/`model`.
|
|
578
|
+
*/
|
|
579
|
+
profile?: string;
|
|
580
|
+
/** Inline LLM provider transport for this system (used when `profile` absent). */
|
|
581
|
+
provider?: LlmProviderTransport;
|
|
582
|
+
/** Inline full model identifier for this system (used when `profile` absent). */
|
|
583
|
+
model?: string;
|
|
584
|
+
/**
|
|
585
|
+
* Optional credential label pinning this system to a specific credential pool
|
|
586
|
+
* entry. When omitted, the standard priority-based credential resolution
|
|
587
|
+
* applies (or the resolved profile's `credentialLabel`).
|
|
588
|
+
*/
|
|
589
|
+
credentialLabel?: string;
|
|
506
590
|
}
|
|
507
591
|
|
|
508
592
|
/**
|
|
@@ -554,11 +638,32 @@ export interface LlmConfig {
|
|
|
554
638
|
* role that does NOT pin its own provider/model/profile. This is the
|
|
555
639
|
* user-selectable default binding for background roles — it is NEVER a
|
|
556
640
|
* hardcoded provider in code; the owner re-selects it with
|
|
557
|
-
* `cleo
|
|
641
|
+
* `cleo config set llm.defaultProfile <profileName>`.
|
|
558
642
|
*
|
|
559
643
|
* @task T11617
|
|
644
|
+
* @task T11723
|
|
560
645
|
*/
|
|
561
646
|
defaultProfile?: string;
|
|
647
|
+
/**
|
|
648
|
+
* Per-system-of-use LLM overrides — the granular-override half of the hermes
|
|
649
|
+
* "global-base + granular-override" model (E9 · T11745 · T11748).
|
|
650
|
+
*
|
|
651
|
+
* Keyed by an encoded system-of-use key: a flat role-mapped label
|
|
652
|
+
* (`'sentient'`, `'memory'`, …) or an open-axis key
|
|
653
|
+
* (`'tool:<name>'` / `'skill:<name>'` / `'cantbook:<node>'` /
|
|
654
|
+
* `'spawn-unit:<id>'`). Each value is a {@link SystemBinding}.
|
|
655
|
+
*
|
|
656
|
+
* Resolution priority for a system-of-use call:
|
|
657
|
+
* explicit-arg (role override) → `systems[key]` → `defaultProfile` →
|
|
658
|
+
* implicit fallback.
|
|
659
|
+
*
|
|
660
|
+
* `systems[key]` is consulted AFTER any explicit role/argument override but
|
|
661
|
+
* BEFORE the global {@link defaultProfile}, so a subsystem can be pointed at a
|
|
662
|
+
* targeted model without disturbing the global base.
|
|
663
|
+
*
|
|
664
|
+
* @task T11748
|
|
665
|
+
*/
|
|
666
|
+
systems?: Record<string, SystemBinding>;
|
|
562
667
|
}
|
|
563
668
|
|
|
564
669
|
/** SignalDock transport mode. */
|
package/src/data-accessor.ts
CHANGED
|
@@ -468,9 +468,30 @@ export interface DataAccessor {
|
|
|
468
468
|
|
|
469
469
|
// ---- Fine-grained session operations ----
|
|
470
470
|
|
|
471
|
-
/**
|
|
471
|
+
/**
|
|
472
|
+
* Get the currently active session (status='active', most recent).
|
|
473
|
+
*
|
|
474
|
+
* SCAN-meaning: answers "is there any active session?" — NOT "who am I".
|
|
475
|
+
* Identity-meaning callers MUST use {@link DataAccessor.resolveCurrentSession}
|
|
476
|
+
* (T11640), which resolves the caller's OWN session via the
|
|
477
|
+
* connection-handle → `CLEO_SESSION_ID` → most-recent-active precedence.
|
|
478
|
+
*/
|
|
472
479
|
getActiveSession(): Promise<Session | null>;
|
|
473
480
|
|
|
481
|
+
/**
|
|
482
|
+
* Resolve the CALLER's current session (T11640 · Epic T11638).
|
|
483
|
+
*
|
|
484
|
+
* Identity-meaning resolution for accessor-based consumers, mirroring the
|
|
485
|
+
* standalone `resolveCurrentSession` in `@cleocode/core`. Precedence:
|
|
486
|
+
* 1. daemon connection handle (the connection bound at accept-time),
|
|
487
|
+
* 2. env-named session (`CLEO_SESSION_ID`),
|
|
488
|
+
* 3. most-recent-active row (legacy single-process fallback).
|
|
489
|
+
*
|
|
490
|
+
* Use this — NOT {@link DataAccessor.getActiveSession} — anywhere the meaning
|
|
491
|
+
* is "the session of whoever issued THIS request".
|
|
492
|
+
*/
|
|
493
|
+
resolveCurrentSession(): Promise<Session | null>;
|
|
494
|
+
|
|
474
495
|
/** Upsert a single session (targeted write). */
|
|
475
496
|
upsertSingleSession(session: Session): Promise<void>;
|
|
476
497
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry regression tests for the E1-GATEWAY-CRUD epic (T11556).
|
|
3
|
+
*
|
|
4
|
+
* - T11784: `tasks.update` OperationDef.params enumerates EVERY mutable field
|
|
5
|
+
* declared in `TASKS_UPDATE_INPUT_SCHEMA`, and carries the inline
|
|
6
|
+
* input/output schemas — so dispatch introspection (`--describe`, the SDK
|
|
7
|
+
* `describeOperation`) no longer hides the real update surface behind a
|
|
8
|
+
* `taskId`-only param list.
|
|
9
|
+
* - T11786: the three bulk task mutate ops (`reorder-rank`, `bulk-move`,
|
|
10
|
+
* `assignee`) are registered as `mutate` ops with the expected required
|
|
11
|
+
* params and inline output schemas.
|
|
12
|
+
* - T11785: the first streaming task op (`tasks.subscribe`) is registered as a
|
|
13
|
+
* `query` op flagged `streaming: true`.
|
|
14
|
+
*
|
|
15
|
+
* @task T11784
|
|
16
|
+
* @task T11785
|
|
17
|
+
* @task T11786
|
|
18
|
+
* @epic T11556
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { describe, expect, it } from 'vitest';
|
|
22
|
+
import { TASKS_UPDATE_INPUT_SCHEMA } from '../../operations/tasks.js';
|
|
23
|
+
import { OPERATIONS } from '../operations-registry.js';
|
|
24
|
+
|
|
25
|
+
function findOp(gateway: 'query' | 'mutate', operation: string) {
|
|
26
|
+
return OPERATIONS.find(
|
|
27
|
+
(o) => o.domain === 'tasks' && o.gateway === gateway && o.operation === operation,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe('T11784 — tasks.update OperationDef params parity', () => {
|
|
32
|
+
const update = findOp('mutate', 'update');
|
|
33
|
+
|
|
34
|
+
it('registers tasks.update as a mutate op', () => {
|
|
35
|
+
expect(update).toBeDefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('enumerates every mutable field from TASKS_UPDATE_INPUT_SCHEMA', () => {
|
|
39
|
+
const schemaFields = Object.keys(
|
|
40
|
+
(TASKS_UPDATE_INPUT_SCHEMA.properties ?? {}) as Record<string, unknown>,
|
|
41
|
+
);
|
|
42
|
+
const paramNames = new Set((update?.params ?? []).map((p) => p.name));
|
|
43
|
+
// Every schema property must be a declared param (no silent-dropped fields).
|
|
44
|
+
for (const field of schemaFields) {
|
|
45
|
+
expect(paramNames.has(field), `tasks.update param "${field}" missing from OperationDef`).toBe(
|
|
46
|
+
true,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
// taskId is the only required param.
|
|
50
|
+
expect(update?.requiredParams).toEqual(['taskId']);
|
|
51
|
+
expect((update?.params ?? []).filter((p) => p.required).map((p) => p.name)).toEqual(['taskId']);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('carries the inline input + output schemas', () => {
|
|
55
|
+
expect(update?.inputSchema?.operation).toBe('tasks.update');
|
|
56
|
+
expect(update?.outputSchema?.operation).toBe('tasks.update');
|
|
57
|
+
// The output contract points at the bare-string updated-id pointer.
|
|
58
|
+
expect(update?.outputSchema?.fieldPointers).toContain('/data/updated/0');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('T11786 — bulk task mutate ops', () => {
|
|
63
|
+
it('registers tasks.reorder-rank with orderedIds required + output schema', () => {
|
|
64
|
+
const op = findOp('mutate', 'reorder-rank');
|
|
65
|
+
expect(op).toBeDefined();
|
|
66
|
+
expect(op?.requiredParams).toEqual(['orderedIds']);
|
|
67
|
+
expect(op?.outputSchema?.operation).toBe('tasks.reorder-rank');
|
|
68
|
+
expect(op?.outputSchema?.fieldPointers).toContain('/data/ranked/0');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('registers tasks.bulk-move with taskIds required + output schema', () => {
|
|
72
|
+
const op = findOp('mutate', 'bulk-move');
|
|
73
|
+
expect(op).toBeDefined();
|
|
74
|
+
expect(op?.requiredParams).toEqual(['taskIds']);
|
|
75
|
+
expect(op?.outputSchema?.operation).toBe('tasks.bulk-move');
|
|
76
|
+
expect(op?.outputSchema?.fieldPointers).toContain('/data/moved/0');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('registers tasks.assignee with taskId required + output schema', () => {
|
|
80
|
+
const op = findOp('mutate', 'assignee');
|
|
81
|
+
expect(op).toBeDefined();
|
|
82
|
+
expect(op?.requiredParams).toEqual(['taskId']);
|
|
83
|
+
expect(op?.outputSchema?.operation).toBe('tasks.assignee');
|
|
84
|
+
expect(op?.outputSchema?.fieldPointers).toContain('/data/assignee');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('T11785 — streaming task op', () => {
|
|
89
|
+
it('registers tasks.subscribe as a query op flagged streaming', () => {
|
|
90
|
+
const op = findOp('query', 'subscribe');
|
|
91
|
+
expect(op).toBeDefined();
|
|
92
|
+
expect(op?.streaming).toBe(true);
|
|
93
|
+
// No required params — subscribe is open by default (optional root/ticks scope).
|
|
94
|
+
expect(op?.requiredParams).toEqual([]);
|
|
95
|
+
const paramNames = (op?.params ?? []).map((p) => p.name);
|
|
96
|
+
expect(paramNames).toContain('root');
|
|
97
|
+
expect(paramNames).toContain('ticks');
|
|
98
|
+
});
|
|
99
|
+
});
|
package/src/dispatch/identity.ts
CHANGED
|
@@ -99,6 +99,31 @@ export const CANONICAL_DOMAINS = [
|
|
|
99
99
|
// T11373: 'cleo attention add|show|list' (alias 'jot') — Tier-2 scope-keyed
|
|
100
100
|
// working-memory buffer (Epic T11288 · Saga T11283).
|
|
101
101
|
'attention',
|
|
102
|
+
// T11889 (T11889-D): 'cleo selfimprove run' — the self-dogfooding loop verb.
|
|
103
|
+
// Boots ONE sandbox → replays a canned scenario → diffs vs golden → on a
|
|
104
|
+
// regression emits ONE leased `selfimprove_dhq` row + ONE DRAFT PR. Default
|
|
105
|
+
// OFF (requires --execute); the engine lives in CORE (P5 self-improvement spec).
|
|
106
|
+
'selfimprove',
|
|
107
|
+
// T11939 (epic T11765 · M2): 'cleo service auth-url|exchange|refresh|self-heal'
|
|
108
|
+
// — the universal service-vault OAuth flow. auth-url builds a PKCE auth URL;
|
|
109
|
+
// exchange persists encrypted tokens; refresh/self-heal renew them honoring the
|
|
110
|
+
// per-provider RefreshConfig. The flow lives in CORE (store/service-oauth.ts),
|
|
111
|
+
// driven by the declarative SERVICE_PROVIDERS registry (contracts).
|
|
112
|
+
'service',
|
|
113
|
+
// T11700 (epic T11666 · M3 · North-Star §2): the 5-entity provider experience —
|
|
114
|
+
// the addressable Provider / Alias / Account / Model / Profile surface.
|
|
115
|
+
// 'account' — 'cleo account add|list|remove' (the credential pool; add is
|
|
116
|
+
// secret-bearing/cli-only, MCP-default-denied).
|
|
117
|
+
// 'provider' — 'cleo provider list|show|connect' (the declarative providers
|
|
118
|
+
// table #1039 + alias resolution; connect is secret-bearing).
|
|
119
|
+
// 'model' — 'cleo model query|show' (the models_catalog table #1037; QUERY-ONLY).
|
|
120
|
+
// 'profile' — 'cleo profile create|list|pin|use' (the named account+model
|
|
121
|
+
// binding persisted into llm.profiles[name], the resolver SSoT).
|
|
122
|
+
// Each dispatches to the CORE entity-ops layer (llm/entity-ops.ts).
|
|
123
|
+
'account',
|
|
124
|
+
'provider',
|
|
125
|
+
'model',
|
|
126
|
+
'profile',
|
|
102
127
|
] as const;
|
|
103
128
|
|
|
104
129
|
/**
|
|
@@ -95,6 +95,27 @@ export interface OperationDef {
|
|
|
95
95
|
*/
|
|
96
96
|
mcpExposed?: boolean;
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Whether this operation is a **streaming** operation served over the gateway
|
|
100
|
+
* HTTP/SSE transport as `GET /v1/<domain>/<operation>` (T11921).
|
|
101
|
+
*
|
|
102
|
+
* **Default-deny**: absent / `false` means the operation is unary only — it is
|
|
103
|
+
* dispatched via the POST path and returns a single LAFS envelope. When
|
|
104
|
+
* `streaming: true`, the `/v1` HTTP listener routes a `GET` to the same
|
|
105
|
+
* `(domain, operation)` pair through {@link createSseStream}, emitting a
|
|
106
|
+
* sequence of `GatewayStreamEvent` frames (`data` … terminated by `done` or
|
|
107
|
+
* `error`) over a `text/event-stream` body. This is the realtime transport the
|
|
108
|
+
* Studio Kanban (T11929) and Pi-TUI (T11936) consume.
|
|
109
|
+
*
|
|
110
|
+
* A streaming op is still a normal registry entry (it has a `gateway`, a
|
|
111
|
+
* `domain`, an `operation`, a `tier`), so it co-exists with the unary POST
|
|
112
|
+
* routes and is discoverable by every existing registry helper — only the wire
|
|
113
|
+
* framing (a long-lived SSE body vs a single JSON response) differs.
|
|
114
|
+
*
|
|
115
|
+
* @task T11921 — gateway SSE streaming on `/v1`
|
|
116
|
+
*/
|
|
117
|
+
streaming?: boolean;
|
|
118
|
+
|
|
98
119
|
/**
|
|
99
120
|
* Schema-first INPUT contract for this operation (DHQ-033 / T11692).
|
|
100
121
|
*
|