* docs: thread-bound subagents plan * docs: add exact thread-bound subagent implementation touchpoints * Docs: prioritize auto thread-bound subagent flow * Docs: add ACP harness thread-binding extensions * Discord: add thread-bound session routing and auto-bind spawn flow * Subagents: add focus commands and ACP/session binding lifecycle hooks * Tests: cover thread bindings, focus commands, and ACP unbind hooks * Docs: add plugin-hook appendix for thread-bound subagents * Plugins: add subagent lifecycle hook events * Core: emit subagent lifecycle hooks and decouple Discord bindings * Discord: handle subagent bind lifecycle via plugin hooks * Subagents: unify completion finalizer and split registry modules * Add subagent lifecycle events module * Hooks: fix subagent ended context key * Discord: share thread bindings across ESM and Jiti * Subagents: add persistent sessions_spawn mode for thread-bound sessions * Subagents: clarify thread intro and persistent completion copy * test(subagents): stabilize sessions_spawn lifecycle cleanup assertions * Discord: add thread-bound session TTL with auto-unfocus * Subagents: fail session spawns when thread bind fails * Subagents: cover thread session failure cleanup paths * Session: add thread binding TTL config and /session ttl controls * Tests: align discord reaction expectations * Agent: persist sessionFile for keyed subagent sessions * Discord: normalize imports after conflict resolution * Sessions: centralize sessionFile resolve/persist helper * Discord: harden thread-bound subagent session routing * Rebase: resolve upstream/main conflicts * Subagents: move thread binding into hooks and split bindings modules * Docs: add channel-agnostic subagent routing hook plan * Agents: decouple subagent routing from Discord * Discord: refactor thread-bound subagent flows * Subagents: prevent duplicate end hooks and orphaned failed sessions * Refactor: split subagent command and provider phases * Subagents: honor hook delivery target overrides * Discord: add thread binding kill switches and refresh plan doc * Discord: fix thread bind channel resolution * Routing: centralize account id normalization * Discord: clean up thread bindings on startup failures * Discord: add startup cleanup regression tests * Docs: add long-term thread-bound subagent architecture * Docs: split session binding plan and dedupe thread-bound doc * Subagents: add channel-agnostic session binding routing * Subagents: stabilize announce completion routing tests * Subagents: cover multi-bound completion routing * Subagents: suppress lifecycle hooks on failed thread bind * tests: fix discord provider mock typing regressions * docs/protocol: sync slash command aliases and delete param models * fix: add changelog entry for Discord thread-bound subagents (#21805) (thanks @onutc) --------- Co-authored-by: Shadow <hi@shadowing.dev>
132 lines
5.1 KiB
TypeScript
132 lines
5.1 KiB
TypeScript
import { Type } from "@sinclair/typebox";
|
|
import { NonEmptyString, SessionLabelString } from "./primitives.js";
|
|
|
|
export const SessionsListParamsSchema = Type.Object(
|
|
{
|
|
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
activeMinutes: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
includeGlobal: Type.Optional(Type.Boolean()),
|
|
includeUnknown: Type.Optional(Type.Boolean()),
|
|
/**
|
|
* Read first 8KB of each session transcript to derive title from first user message.
|
|
* Performs a file read per session - use `limit` to bound result set on large stores.
|
|
*/
|
|
includeDerivedTitles: Type.Optional(Type.Boolean()),
|
|
/**
|
|
* Read last 16KB of each session transcript to extract most recent message preview.
|
|
* Performs a file read per session - use `limit` to bound result set on large stores.
|
|
*/
|
|
includeLastMessage: Type.Optional(Type.Boolean()),
|
|
label: Type.Optional(SessionLabelString),
|
|
spawnedBy: Type.Optional(NonEmptyString),
|
|
agentId: Type.Optional(NonEmptyString),
|
|
search: Type.Optional(Type.String()),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsPreviewParamsSchema = Type.Object(
|
|
{
|
|
keys: Type.Array(NonEmptyString, { minItems: 1 }),
|
|
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
maxChars: Type.Optional(Type.Integer({ minimum: 20 })),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsResolveParamsSchema = Type.Object(
|
|
{
|
|
key: Type.Optional(NonEmptyString),
|
|
sessionId: Type.Optional(NonEmptyString),
|
|
label: Type.Optional(SessionLabelString),
|
|
agentId: Type.Optional(NonEmptyString),
|
|
spawnedBy: Type.Optional(NonEmptyString),
|
|
includeGlobal: Type.Optional(Type.Boolean()),
|
|
includeUnknown: Type.Optional(Type.Boolean()),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsPatchParamsSchema = Type.Object(
|
|
{
|
|
key: NonEmptyString,
|
|
label: Type.Optional(Type.Union([SessionLabelString, Type.Null()])),
|
|
thinkingLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
verboseLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
reasoningLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
responseUsage: Type.Optional(
|
|
Type.Union([
|
|
Type.Literal("off"),
|
|
Type.Literal("tokens"),
|
|
Type.Literal("full"),
|
|
// Backward compat with older clients/stores.
|
|
Type.Literal("on"),
|
|
Type.Null(),
|
|
]),
|
|
),
|
|
elevatedLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
execHost: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
execSecurity: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
execAsk: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
execNode: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
model: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
spawnedBy: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
spawnDepth: Type.Optional(Type.Union([Type.Integer({ minimum: 0 }), Type.Null()])),
|
|
sendPolicy: Type.Optional(
|
|
Type.Union([Type.Literal("allow"), Type.Literal("deny"), Type.Null()]),
|
|
),
|
|
groupActivation: Type.Optional(
|
|
Type.Union([Type.Literal("mention"), Type.Literal("always"), Type.Null()]),
|
|
),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsResetParamsSchema = Type.Object(
|
|
{
|
|
key: NonEmptyString,
|
|
reason: Type.Optional(Type.Union([Type.Literal("new"), Type.Literal("reset")])),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsDeleteParamsSchema = Type.Object(
|
|
{
|
|
key: NonEmptyString,
|
|
deleteTranscript: Type.Optional(Type.Boolean()),
|
|
// Internal control: when false, still unbind thread bindings but skip hook emission.
|
|
emitLifecycleHooks: Type.Optional(Type.Boolean()),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsCompactParamsSchema = Type.Object(
|
|
{
|
|
key: NonEmptyString,
|
|
maxLines: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const SessionsUsageParamsSchema = Type.Object(
|
|
{
|
|
/** Specific session key to analyze; if omitted returns all sessions. */
|
|
key: Type.Optional(NonEmptyString),
|
|
/** Start date for range filter (YYYY-MM-DD). */
|
|
startDate: Type.Optional(Type.String({ pattern: "^\\d{4}-\\d{2}-\\d{2}$" })),
|
|
/** End date for range filter (YYYY-MM-DD). */
|
|
endDate: Type.Optional(Type.String({ pattern: "^\\d{4}-\\d{2}-\\d{2}$" })),
|
|
/** How start/end dates should be interpreted. Defaults to UTC when omitted. */
|
|
mode: Type.Optional(
|
|
Type.Union([Type.Literal("utc"), Type.Literal("gateway"), Type.Literal("specific")]),
|
|
),
|
|
/** UTC offset to use when mode is `specific` (for example, UTC-4 or UTC+5:30). */
|
|
utcOffset: Type.Optional(Type.String({ pattern: "^UTC[+-]\\d{1,2}(?::[0-5]\\d)?$" })),
|
|
/** Maximum sessions to return (default 50). */
|
|
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
/** Include context weight breakdown (systemPromptReport). */
|
|
includeContextWeight: Type.Optional(Type.Boolean()),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|