@yanlinglabs/winter-agent-sdk 0.0.1
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/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/brand.d.ts +113 -0
- package/dist/errors.d.ts +42 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +2191 -0
- package/dist/options.d.ts +252 -0
- package/dist/paths/home.d.ts +48 -0
- package/dist/paths/keys.d.ts +6 -0
- package/dist/paths/project-key.d.ts +1 -0
- package/dist/permissions/types.d.ts +272 -0
- package/dist/protocol/codec.d.ts +10 -0
- package/dist/protocol/config.d.ts +535 -0
- package/dist/protocol/frames.d.ts +598 -0
- package/dist/query.d.ts +81 -0
- package/dist/sessions.d.ts +50 -0
- package/dist/settings/model-slots.d.ts +33 -0
- package/dist/settings/resolve.d.ts +79 -0
- package/dist/settings/sources.d.ts +29 -0
- package/dist/settings/types.d.ts +291 -0
- package/dist/store/fork-session.d.ts +19 -0
- package/dist/store/leases.d.ts +15 -0
- package/dist/store/session-store.d.ts +111 -0
- package/dist/transport.d.ts +26 -0
- package/package.json +51 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type { SpawnClaudeCodeProcess } from "./transport.js";
|
|
2
|
+
import type { PermissionMode, CanUseTool, HookEvent, HookCallbackMatcher } from "./permissions/types.js";
|
|
3
|
+
import type { SandboxSettingsConfig, McpServerToolPolicy, McpStdioServerConfig, McpHttpServerConfig, McpSSEServerConfig, McpSdkServerConfig, RuntimeAgentDefinition, SdkPluginConfig, SystemPromptOption, OutputFormat, SkillsOption, ProviderSelection, ThinkingConfig, EffortLevel, AutoClassifierConfig, AdvisorConfig } from "./protocol/config.js";
|
|
4
|
+
import type { SettingSource } from "./settings/types.js";
|
|
5
|
+
import type { SessionStore } from "./store/session-store.js";
|
|
6
|
+
import { type BrandProfile } from "./brand.js";
|
|
7
|
+
export type { BrandProfile, BrandValidation } from "./brand.js";
|
|
8
|
+
export type { SdkPluginConfig, SystemPromptOption, OutputFormat, JsonSchemaOutputFormat, SkillsOption } from "./protocol/config.js";
|
|
9
|
+
export type { ProviderSelection, ProviderConnectionConfig, CredentialRef, ThinkingConfig, EffortLevel, AutoClassifierConfig, AdvisorConfig } from "./protocol/config.js";
|
|
10
|
+
export declare const SYSTEM_PROMPT_DYNAMIC_BOUNDARY = "__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__";
|
|
11
|
+
export declare const DEFAULT_CONTEXT_WINDOW_TOKENS = 200000;
|
|
12
|
+
export declare const DEFAULT_COMPACTION_THRESHOLD = 0.92;
|
|
13
|
+
export declare const DEFAULT_PLANS_DIRECTORY: string;
|
|
14
|
+
export declare const DEFAULT_OUTPUT_STYLE = "default";
|
|
15
|
+
export declare const DEFAULT_PROVIDER_STALL_TIMEOUT_MS = 120000;
|
|
16
|
+
export declare const DEFAULT_KEYCHAIN_SERVICE: string;
|
|
17
|
+
export interface McpSdkServerConfigWithInstance extends McpSdkServerConfig {
|
|
18
|
+
instance: unknown;
|
|
19
|
+
}
|
|
20
|
+
export type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig | McpSSEServerConfig | McpSdkServerConfigWithInstance;
|
|
21
|
+
export type { McpServerToolPolicy, McpStdioServerConfig, McpHttpServerConfig, McpSSEServerConfig, McpSdkServerConfig };
|
|
22
|
+
export interface WinterMcpServerInstance {
|
|
23
|
+
listTools(): Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
inputSchema: Record<string, unknown>;
|
|
27
|
+
outputSchema?: Record<string, unknown>;
|
|
28
|
+
annotations?: {
|
|
29
|
+
readOnlyHint?: boolean;
|
|
30
|
+
destructiveHint?: boolean;
|
|
31
|
+
openWorldHint?: boolean;
|
|
32
|
+
title?: string;
|
|
33
|
+
idempotentHint?: boolean;
|
|
34
|
+
};
|
|
35
|
+
_meta?: Record<string, unknown>;
|
|
36
|
+
}>;
|
|
37
|
+
callTool(name: string, args: Record<string, unknown>): Promise<{
|
|
38
|
+
content: unknown[];
|
|
39
|
+
isError?: boolean;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
export declare function isWinterMcpServerInstance(value: unknown): value is WinterMcpServerInstance;
|
|
43
|
+
export type AgentDefinition = Omit<RuntimeAgentDefinition, "permissionMode"> & {
|
|
44
|
+
permissionMode?: PermissionMode;
|
|
45
|
+
};
|
|
46
|
+
export interface Options {
|
|
47
|
+
model?: string;
|
|
48
|
+
permissionMode?: PermissionMode;
|
|
49
|
+
maxTurns?: number;
|
|
50
|
+
cwd?: string;
|
|
51
|
+
env?: Record<string, string>;
|
|
52
|
+
pathToClaudeCodeExecutable?: string;
|
|
53
|
+
spawnClaudeCodeProcess?: SpawnClaudeCodeProcess;
|
|
54
|
+
stderr?: (chunk: string) => void;
|
|
55
|
+
maxBufferSize?: number;
|
|
56
|
+
abortController?: AbortController;
|
|
57
|
+
sessionId?: string;
|
|
58
|
+
continue?: boolean;
|
|
59
|
+
resume?: string;
|
|
60
|
+
forkSession?: boolean;
|
|
61
|
+
resumeSessionAt?: string;
|
|
62
|
+
resumeDropsTurn?: boolean;
|
|
63
|
+
persistSession?: boolean;
|
|
64
|
+
allowedTools?: string[];
|
|
65
|
+
disallowedTools?: string[];
|
|
66
|
+
permissions?: {
|
|
67
|
+
allow?: string[];
|
|
68
|
+
ask?: string[];
|
|
69
|
+
deny?: string[];
|
|
70
|
+
disableBypassPermissionsMode?: boolean;
|
|
71
|
+
};
|
|
72
|
+
settingSources?: SettingSource[];
|
|
73
|
+
/**
|
|
74
|
+
* Phase 5 fix wave, C1: the MANAGED policy tiers, threaded to the runtime's own settings
|
|
75
|
+
* resolution. `managedSettings` is filtered restrictive-only there; `serverManagedSettings` is
|
|
76
|
+
* deliberately not (`sdk.d.ts:2838-2839`). Before this existed the pinned `managed` rule source had
|
|
77
|
+
* no producer in a live session at all.
|
|
78
|
+
*/
|
|
79
|
+
managedSettings?: Record<string, unknown>;
|
|
80
|
+
serverManagedSettings?: Record<string, unknown>;
|
|
81
|
+
permissionPromptToolName?: string;
|
|
82
|
+
additionalDirectories?: string[];
|
|
83
|
+
sandbox?: SandboxSettingsConfig;
|
|
84
|
+
outputsDir?: string;
|
|
85
|
+
capabilities?: string[];
|
|
86
|
+
toolSearchEnabled?: boolean;
|
|
87
|
+
insideSubagent?: boolean;
|
|
88
|
+
familyMetadata?: {
|
|
89
|
+
taskNative?: boolean;
|
|
90
|
+
};
|
|
91
|
+
allowDangerouslySkipPermissions?: boolean;
|
|
92
|
+
canUseTool?: CanUseTool;
|
|
93
|
+
hooks?: Partial<Record<HookEvent, HookCallbackMatcher[]>>;
|
|
94
|
+
includeHookEvents?: boolean;
|
|
95
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
96
|
+
strictMcpConfig?: boolean;
|
|
97
|
+
toolAliases?: Record<string, string>;
|
|
98
|
+
agents?: Record<string, AgentDefinition>;
|
|
99
|
+
forwardSubagentText?: boolean;
|
|
100
|
+
onElicitation?: (request: {
|
|
101
|
+
serverName: string;
|
|
102
|
+
message: string;
|
|
103
|
+
mode?: "form" | "url";
|
|
104
|
+
url?: string;
|
|
105
|
+
elicitationId?: string;
|
|
106
|
+
requestedSchema?: Record<string, unknown>;
|
|
107
|
+
title?: string;
|
|
108
|
+
displayName?: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
}, options: {
|
|
111
|
+
signal: AbortSignal;
|
|
112
|
+
requestId: string;
|
|
113
|
+
}) => Promise<{
|
|
114
|
+
action: "accept" | "decline" | "cancel";
|
|
115
|
+
content?: Record<string, unknown>;
|
|
116
|
+
} | null>;
|
|
117
|
+
systemPrompt?: SystemPromptOption;
|
|
118
|
+
plugins?: SdkPluginConfig[];
|
|
119
|
+
skills?: SkillsOption;
|
|
120
|
+
outputFormat?: OutputFormat;
|
|
121
|
+
enableFileCheckpointing?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* `sdk.d.ts:1672-1683`: an external session store the runtime MIRRORS transcript writes to. A
|
|
124
|
+
* DUAL-WRITE MIRROR, never a replacement -- local writes always still happen, which is exactly why
|
|
125
|
+
* the checkpointing rejection below is about backup blobs specifically rather than about external
|
|
126
|
+
* storage in general.
|
|
127
|
+
*
|
|
128
|
+
* A LIVE OBJECT, like `canUseTool`/`hooks`/`mcpServers[].instance`: it is never serialized into
|
|
129
|
+
* `--config-json`, so a spawned-process transport reaches it only through the wrapper. Winter does
|
|
130
|
+
* not yet mirror to it (Lane K / a later phase); it is declared here because two documented
|
|
131
|
+
* combination REJECTIONS depend on its presence and capture (2) pins both of them at construction.
|
|
132
|
+
*/
|
|
133
|
+
sessionStore?: SessionStore;
|
|
134
|
+
contextWindowTokens?: number;
|
|
135
|
+
compactionThreshold?: number;
|
|
136
|
+
trustedWorkspace?: boolean;
|
|
137
|
+
plansDirectory?: string;
|
|
138
|
+
outputStyle?: string;
|
|
139
|
+
/**
|
|
140
|
+
* DISCLOSED WINTER option (R6-9). Which provider a BARE `model` id resolves against, plus that
|
|
141
|
+
* provider's connection metadata and credential reference.
|
|
142
|
+
*
|
|
143
|
+
* `model` itself stays the pinned bare string and `system/init.model` keeps reporting what the
|
|
144
|
+
* caller passed — the resolved identity rides Winter-only init extension fields instead. A
|
|
145
|
+
* qualified `"<providerId>/<model>"` key needs no `provider` at all; the pinned Anthropic aliases
|
|
146
|
+
* (`sonnet`/`opus`/`haiku`/`claude-*`) resolve to the `anthropic` provider when a credential ref
|
|
147
|
+
* for it is configured. No model and no provider is a typed resolution error, never a silent
|
|
148
|
+
* default (WS-13 §9: no routing, no substitution in the provider layer).
|
|
149
|
+
*/
|
|
150
|
+
provider?: ProviderSelection;
|
|
151
|
+
/**
|
|
152
|
+
* `sdk.d.ts:1540` — a **single string carrying a COMMA-SEPARATED list**, tried in order. This is
|
|
153
|
+
* the pin's own convention, not an oversight: the settings twin `Settings.fallbackModel` (`5577`)
|
|
154
|
+
* is a `string[]`, and the two shapes coexist with a documented precedence. Typing this `string[]`
|
|
155
|
+
* would be a parity divergence (derived-shapes-p6.md item (g), finding 1).
|
|
156
|
+
*
|
|
157
|
+
* Pinned semantics, AS IMPLEMENTED (P6 fix wave, Ruling E-3): the trigger is an R6-6
|
|
158
|
+
* retryable-class provider failure -- 5xx/overloaded, 429 (non-billing), 408, network, timeout --
|
|
159
|
+
* AFTER the adapter's own retries are exhausted (NOT a refusal: the `model_refusal_fallback`
|
|
160
|
+
* frame's `trigger` is the literal `'refusal'`). The failed round is re-run on the next candidate,
|
|
161
|
+
* candidates are tried in order, each once per turn, and the primary is re-tried at the START OF
|
|
162
|
+
* EACH USER TURN, so a temporary outage never permanently demotes the session. The swap emits NO
|
|
163
|
+
* pinned frame (capture (G): the only observable is the outgoing request's `model`); Winter
|
|
164
|
+
* additionally emits its disclosed `system/model_switch{reason: "fallback"}` for the swap AND for
|
|
165
|
+
* the restoration, and records both in the dialect record's `providerHistory`. A candidate is
|
|
166
|
+
* honoured only inside the CURRENT model's continuation domain (R6-9) -- a cross-domain candidate
|
|
167
|
+
* is a typed error at init and is skipped at engagement time if a `set_model` has since moved the
|
|
168
|
+
* session. A `set_model` parked during a fallback turn supersedes the restoration.
|
|
169
|
+
*/
|
|
170
|
+
fallbackModel?: string;
|
|
171
|
+
/** `sdk.d.ts:1736`, three arms (`adaptive` | `enabled` | `disabled`). Takes precedence over `maxThinkingTokens`, stated twice in the pin (`1732`, `8215`). */
|
|
172
|
+
thinking?: ThinkingConfig;
|
|
173
|
+
/**
|
|
174
|
+
* `sdk.d.ts:1749`. **No numeric form** — see `EffortLevel`'s own declaration comment (R6-E).
|
|
175
|
+
*
|
|
176
|
+
* Pinned adjacent rules a consumer must not fight: `'max'` is session-scoped and deliberately not
|
|
177
|
+
* persistable (`Settings.effortLevel` excludes it), and the ACTIVE level is the one left after a
|
|
178
|
+
* per-model silent downgrade — which is exactly what the catalog's `reasoning.efforts` evidence
|
|
179
|
+
* exists to compute honestly rather than by guess.
|
|
180
|
+
*/
|
|
181
|
+
effort?: EffortLevel;
|
|
182
|
+
/**
|
|
183
|
+
* @deprecated Use `thinking` instead.
|
|
184
|
+
*
|
|
185
|
+
* `sdk.d.ts:1758`. Kept and typed rather than dropped, because dropping a pinned Options member is
|
|
186
|
+
* a drop-in parity break. Its semantics CHANGE BY MODEL and that is the trap: on a modern model it
|
|
187
|
+
* is reinterpreted as on/off — `0` disables, any other value means *adaptive* — so forwarding
|
|
188
|
+
* `maxThinkingTokens: 8000` is not "budget 8000" (R6-E maps it exactly that way).
|
|
189
|
+
*/
|
|
190
|
+
maxThinkingTokens?: number;
|
|
191
|
+
/**
|
|
192
|
+
* `stream_event` frames (`SDKPartialAssistantMessage`) are emitted only under this gate (R6-5).
|
|
193
|
+
* Absent/false keeps the stream byte-identical to every session before partial streaming existed.
|
|
194
|
+
*/
|
|
195
|
+
includePartialMessages?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* A cumulative USD ceiling for this query's provider spend, LIVE since the P6 fix wave (Ruling
|
|
198
|
+
* E-4, R6-H). Checked BEFORE every provider request: once the accrued `total_cost_usd` exceeds it,
|
|
199
|
+
* the next request does not go out and the turn ends on the pinned `error_max_budget_usd` result
|
|
200
|
+
* (`is_error: true`), which carries the cost that crossed it. The generation that crossed the
|
|
201
|
+
* ceiling still delivers its own frames -- the cut is a request never sent, not an answer lost.
|
|
202
|
+
*
|
|
203
|
+
* The descriptor's `pricing` evidence is the ONLY price source: a priced row makes every result
|
|
204
|
+
* frame carry `total_cost_usd` (accumulated over the whole run and repeated on each result) and a
|
|
205
|
+
* `modelUsage` row keyed by the model string, with the catalog key as `canonicalModel` and
|
|
206
|
+
* `costBasis: "list"`; an UNPRICED row emits NO cost field at all and leaves this ceiling inert
|
|
207
|
+
* (disclosed). Winter deliberately does NOT do what the pin does here -- capture (K) shows the
|
|
208
|
+
* pinned runtime reporting a non-zero cost for a model no price table contains -- and it does not
|
|
209
|
+
* emit the main-loop-only `usage` block, which the pin's own JSDoc deprioritises (disclosed).
|
|
210
|
+
*/
|
|
211
|
+
maxBudgetUsd?: number;
|
|
212
|
+
/** DISCLOSED WINTER option (R6-6): a stream silent for this long aborts as a typed `ProviderStallError`. Absent means DEFAULT_PROVIDER_STALL_TIMEOUT_MS. */
|
|
213
|
+
providerStallTimeoutMs?: number;
|
|
214
|
+
/** DISCLOSED WINTER option (R6-10): the macOS Keychain service every `{ kind: "keychain" }` ref resolves under. Absent means DEFAULT_KEYCHAIN_SERVICE. */
|
|
215
|
+
keychainService?: string;
|
|
216
|
+
/** DISCLOSED WINTER option (R6-14): the permission classifier's own model/credential, resolved through the SAME selection path as the session model. With none configured the worker serves only a `classifierEligible` model, else Manual fallback — never a silent weakening. */
|
|
217
|
+
autoClassifier?: AutoClassifierConfig;
|
|
218
|
+
/**
|
|
219
|
+
* DISCLOSED WINTER option (P2 carry, wired in T10): the advisor/reviewer backend's model, same
|
|
220
|
+
* selection path. Its optional `authRef` (fix wave, Ruling E-1) is the advisor's OWN credential:
|
|
221
|
+
* a target on another provider than the session's never inherits the session's -- it uses the
|
|
222
|
+
* route's ref, else the target provider's own keychain record (`<providerId>:default`), else a
|
|
223
|
+
* typed `no-credential-for-provider` refusal at its first generation.
|
|
224
|
+
*
|
|
225
|
+
* The MODEL may also come from `settings.advisor.model` (D30, hot); `Options.advisor.model` wins.
|
|
226
|
+
*/
|
|
227
|
+
advisor?: AdvisorConfig;
|
|
228
|
+
/**
|
|
229
|
+
* DISCLOSED WINTER option (P7a, D19): THE BRAND PROFILE — every Winter-owned name this session
|
|
230
|
+
* runs under, as a partial that folds onto Winter's own defaults (brand.ts's `WINTER_BRAND`).
|
|
231
|
+
*
|
|
232
|
+
* This is what makes the SDK genuinely reusable rather than merely open: a host consuming Winter
|
|
233
|
+
* alone (D19's tier 1) gets its OWN home dir, project dir, instructions file, env prefix, keychain
|
|
234
|
+
* service, MCP server name and codex originator, resolved once here and carried to the runtime on
|
|
235
|
+
* `RuntimeConfig.brand` so a spawned or compiled child derives the same names the wrapper did.
|
|
236
|
+
*
|
|
237
|
+
* VALIDATED AT `query()` (brand.ts's grammar rules), and a refusal is a typed `InvalidBrandError`
|
|
238
|
+
* thrown synchronously at construction, like the other option-combination rejections above --
|
|
239
|
+
* never a silently-substituted default, because a session that quietly ran under the wrong home
|
|
240
|
+
* dir or the wrong keychain service is the worst possible outcome of a typo here.
|
|
241
|
+
*
|
|
242
|
+
* `keychainService` above is the DEPRECATED standalone alias for `brand.keychainService`: when
|
|
243
|
+
* both are set the standalone one WINS (it predates the profile and existing hosts pass it), and
|
|
244
|
+
* `query()` warns when the two are set to DIFFERENT values so the losing one is never silent.
|
|
245
|
+
*
|
|
246
|
+
* Claude-mirroring literals are NOT in the profile and cannot be rebranded (WS-01 §5): the
|
|
247
|
+
* official runtime's `CLAUDE_CONFIG_DIR`/`CLAUDE_CODE_TMPDIR`/`preset: "claude_code"`/
|
|
248
|
+
* `.claude-plugin` are its names, not ours. Neither are this repository's own test-harness env
|
|
249
|
+
* names.
|
|
250
|
+
*/
|
|
251
|
+
brand?: Partial<BrandProfile>;
|
|
252
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type BrandProfile } from "../brand.js";
|
|
2
|
+
export declare function isUnset(value: string | undefined): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* The two brand fields this module needs. A `Pick` rather than the whole profile so a caller
|
|
5
|
+
* holding a partially-threaded config (or a test) can call it without constructing one.
|
|
6
|
+
*/
|
|
7
|
+
export type HomeBrand = Pick<BrandProfile, "envPrefix" | "homeDirName">;
|
|
8
|
+
/**
|
|
9
|
+
* `<PREFIX>HOME` || `~/<homeDirName>` — mirrors `CLAUDE_CONFIG_DIR`'s env-override semantics
|
|
10
|
+
* (WS-05 §4), with the brand's own token instead of Claude's.
|
|
11
|
+
*
|
|
12
|
+
* `env` is injectable so tests never read the real process environment; it defaults to
|
|
13
|
+
* `process.env` in production. `brand` defaults to `WINTER_BRAND`, so every existing caller keeps
|
|
14
|
+
* exactly today's behaviour (`WINTER_HOME` || `~/.winter`) until it threads a profile through.
|
|
15
|
+
*
|
|
16
|
+
* THE ENV NAME IS DERIVED, NEVER SPELLED, and it is read INSIDE this function — never at module
|
|
17
|
+
* load. The brand arrives with `--config-json`, so a module-level read of a literal `<PREFIX>HOME`
|
|
18
|
+
* would bake in the wrong prefix for a reuser and could never be corrected; the sweep gate
|
|
19
|
+
* (packages/runtime/src/brand-gate.test.ts, rules 9 and 10) is what keeps it that way.
|
|
20
|
+
*
|
|
21
|
+
* PRECEDENCE (WS-01 §2.2, and the same rule the current daemon has always had): an explicit
|
|
22
|
+
* `<PREFIX>HOME` wins over EVERYTHING, including the dev profile. `<PREFIX>PROFILE=dev` selects
|
|
23
|
+
* `~/<homeDirName>-dev` — the dev/dist split, so a development build can never share a home (or a
|
|
24
|
+
* transcript store, or a settings file) with the copy a user actually runs.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveWinterHome(env?: Record<string, string | undefined>, brand?: HomeBrand): string;
|
|
27
|
+
/**
|
|
28
|
+
* P7a fix wave (item 5, whole-branch review M-3): THE OTHER HALF OF THE DEV PROFILE.
|
|
29
|
+
*
|
|
30
|
+
* WS-01's Phase 6 amendment pairs `<PREFIX>PROFILE=dev` with BOTH `~/<homeDirName>-dev` and a
|
|
31
|
+
* `.dev`-suffixed Keychain service, and assigns the fold "to whichever phase introduces the
|
|
32
|
+
* profile" -- this one. Only the home half landed: an env-selected dev session got its own home and
|
|
33
|
+
* its own transcript store while reading and WRITING the dist Keychain service, which is the one
|
|
34
|
+
* piece of state a developer most needs separated from the copy they actually use.
|
|
35
|
+
*
|
|
36
|
+
* It lives here, immediately beside `resolveWinterHome`, because the two are one rule read from two
|
|
37
|
+
* fields -- putting them in different files is how they came to disagree in the first place.
|
|
38
|
+
*
|
|
39
|
+
* AN EXPLICIT VALUE IS NEVER REWRITTEN. `hostSetKeychainService` is true when the host passed
|
|
40
|
+
* `brand.keychainService` or the deprecated `keychainService` alias: they named a service, and a
|
|
41
|
+
* runtime that silently appended to it would be rewriting a host's own decision -- the same
|
|
42
|
+
* precedence `resolveWinterHome` gives an explicit `<PREFIX>HOME` over the profile.
|
|
43
|
+
*
|
|
44
|
+
* The suffix is applied only when the result still satisfies `BrandProfile`'s own service grammar
|
|
45
|
+
* (64 chars); a longer name is left alone rather than made invalid, since an invalid service reaches
|
|
46
|
+
* the Keychain as a lookup that can never match.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveKeychainServiceForProfile(brand: Pick<BrandProfile, "envPrefix" | "keychainService">, env: Record<string, string | undefined> | undefined, hostSetKeychainService: boolean): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function transcriptProjectKey(absPath: string): string;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
export type PermissionMode = "default" | "acceptEdits" | "bypassPermissions" | "plan" | "dontAsk" | "auto";
|
|
2
|
+
export type PermissionBehavior = "allow" | "deny" | "ask";
|
|
3
|
+
export type PermissionRuleValue = {
|
|
4
|
+
toolName: string;
|
|
5
|
+
ruleContent?: string;
|
|
6
|
+
};
|
|
7
|
+
export type PermissionUpdate = {
|
|
8
|
+
type: "addRules";
|
|
9
|
+
rules: PermissionRuleValue[];
|
|
10
|
+
behavior: PermissionBehavior;
|
|
11
|
+
destination: PermissionUpdateDestination;
|
|
12
|
+
} | {
|
|
13
|
+
type: "replaceRules";
|
|
14
|
+
rules: PermissionRuleValue[];
|
|
15
|
+
behavior: PermissionBehavior;
|
|
16
|
+
destination: PermissionUpdateDestination;
|
|
17
|
+
} | {
|
|
18
|
+
type: "removeRules";
|
|
19
|
+
rules: PermissionRuleValue[];
|
|
20
|
+
behavior: PermissionBehavior;
|
|
21
|
+
destination: PermissionUpdateDestination;
|
|
22
|
+
} | {
|
|
23
|
+
type: "setMode";
|
|
24
|
+
mode: PermissionMode;
|
|
25
|
+
destination: PermissionUpdateDestination;
|
|
26
|
+
} | {
|
|
27
|
+
type: "addDirectories";
|
|
28
|
+
directories: string[];
|
|
29
|
+
destination: PermissionUpdateDestination;
|
|
30
|
+
} | {
|
|
31
|
+
type: "removeDirectories";
|
|
32
|
+
directories: string[];
|
|
33
|
+
destination: PermissionUpdateDestination;
|
|
34
|
+
};
|
|
35
|
+
export type PermissionUpdateDestination = "userSettings" | "projectSettings" | "localSettings" | "session" | "cliArg";
|
|
36
|
+
export type RuleSource = "managed" | "user" | "project" | "local" | "cliArg" | "session" | "sdk";
|
|
37
|
+
export type CanUseTool = (toolName: string, input: Record<string, unknown>, options: {
|
|
38
|
+
signal: AbortSignal;
|
|
39
|
+
suggestions?: PermissionUpdate[];
|
|
40
|
+
blockedPath?: string;
|
|
41
|
+
decisionReason?: string;
|
|
42
|
+
title?: string;
|
|
43
|
+
displayName?: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
toolUseID: string;
|
|
46
|
+
agentID?: string;
|
|
47
|
+
requestId: string;
|
|
48
|
+
matchedAskRule?: {
|
|
49
|
+
source: string;
|
|
50
|
+
toolName: string;
|
|
51
|
+
ruleContent?: string;
|
|
52
|
+
};
|
|
53
|
+
}) => Promise<PermissionResult | null>;
|
|
54
|
+
export type PermissionDecisionClassification = "user_temporary" | "user_permanent" | "user_reject";
|
|
55
|
+
export type PermissionResult = {
|
|
56
|
+
behavior: "allow";
|
|
57
|
+
updatedInput?: Record<string, unknown>;
|
|
58
|
+
updatedPermissions?: PermissionUpdate[];
|
|
59
|
+
toolUseID?: string;
|
|
60
|
+
decisionClassification?: PermissionDecisionClassification;
|
|
61
|
+
} | {
|
|
62
|
+
behavior: "deny";
|
|
63
|
+
message: string;
|
|
64
|
+
interrupt?: boolean;
|
|
65
|
+
toolUseID?: string;
|
|
66
|
+
decisionClassification?: PermissionDecisionClassification;
|
|
67
|
+
};
|
|
68
|
+
export interface PermissionRequestPayload {
|
|
69
|
+
toolName: string;
|
|
70
|
+
input: Record<string, unknown>;
|
|
71
|
+
suggestions?: PermissionUpdate[];
|
|
72
|
+
blockedPath?: string;
|
|
73
|
+
decisionReason?: string;
|
|
74
|
+
title?: string;
|
|
75
|
+
displayName?: string;
|
|
76
|
+
description?: string;
|
|
77
|
+
toolUseID: string;
|
|
78
|
+
agentID?: string;
|
|
79
|
+
requestId: string;
|
|
80
|
+
matchedAskRule?: {
|
|
81
|
+
source: string;
|
|
82
|
+
toolName: string;
|
|
83
|
+
ruleContent?: string;
|
|
84
|
+
};
|
|
85
|
+
policyVersion: number;
|
|
86
|
+
}
|
|
87
|
+
export declare const HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure", "UserPromptSubmit", "Stop", "SubagentStart", "SubagentStop", "PreCompact", "PermissionRequest", "Notification", "PostToolBatch", "UserPromptExpansion", "MessageDisplay", "StopFailure", "PostCompact", "PermissionDenied", "SessionStart", "SessionEnd", "Setup", "TeammateIdle", "TaskCreated", "TaskCompleted", "Elicitation", "ElicitationResult", "ConfigChange", "InstructionsLoaded", "WorktreeCreate", "WorktreeRemove", "CwdChanged", "FileChanged", "DirectoryAdded"];
|
|
88
|
+
export type HookEvent = (typeof HOOK_EVENTS)[number];
|
|
89
|
+
export type HookEventName = HookEvent;
|
|
90
|
+
export type HookSource = "managed" | "user" | "project" | "local" | "sdk" | "plugin";
|
|
91
|
+
export interface BaseHookInput {
|
|
92
|
+
session_id: string;
|
|
93
|
+
transcript_path: string;
|
|
94
|
+
cwd: string;
|
|
95
|
+
prompt_id?: string;
|
|
96
|
+
permission_mode?: string;
|
|
97
|
+
agent_id?: string;
|
|
98
|
+
agent_type?: string;
|
|
99
|
+
effort?: {
|
|
100
|
+
level: string;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export type HookPermissionDecision = "allow" | "ask" | "deny" | "defer";
|
|
104
|
+
export interface PreToolUseHookInput extends BaseHookInput {
|
|
105
|
+
hook_event_name: "PreToolUse";
|
|
106
|
+
tool_name: string;
|
|
107
|
+
tool_input: unknown;
|
|
108
|
+
tool_use_id: string;
|
|
109
|
+
}
|
|
110
|
+
export interface PostToolUseHookInput extends BaseHookInput {
|
|
111
|
+
hook_event_name: "PostToolUse";
|
|
112
|
+
tool_name: string;
|
|
113
|
+
tool_input: unknown;
|
|
114
|
+
tool_response: unknown;
|
|
115
|
+
tool_use_id: string;
|
|
116
|
+
duration_ms?: number;
|
|
117
|
+
}
|
|
118
|
+
export interface PostToolUseFailureHookInput extends BaseHookInput {
|
|
119
|
+
hook_event_name: "PostToolUseFailure";
|
|
120
|
+
tool_name: string;
|
|
121
|
+
tool_input: unknown;
|
|
122
|
+
tool_use_id: string;
|
|
123
|
+
error: string;
|
|
124
|
+
is_interrupt?: boolean;
|
|
125
|
+
duration_ms?: number;
|
|
126
|
+
}
|
|
127
|
+
export interface UserPromptSubmitHookInput extends BaseHookInput {
|
|
128
|
+
hook_event_name: "UserPromptSubmit";
|
|
129
|
+
prompt: string;
|
|
130
|
+
source?: "user" | "sdk" | "system" | "loop_wakeup" | "schedule_wakeup" | "poll_event";
|
|
131
|
+
session_title?: string;
|
|
132
|
+
}
|
|
133
|
+
export interface StopHookInput extends BaseHookInput {
|
|
134
|
+
hook_event_name: "Stop";
|
|
135
|
+
stop_hook_active: boolean;
|
|
136
|
+
last_assistant_message?: unknown;
|
|
137
|
+
background_tasks?: unknown[];
|
|
138
|
+
session_crons?: unknown[];
|
|
139
|
+
}
|
|
140
|
+
export interface SessionStartHookInput extends BaseHookInput {
|
|
141
|
+
hook_event_name: "SessionStart";
|
|
142
|
+
source: "startup" | "resume" | "clear" | "compact" | "fork";
|
|
143
|
+
agent_type?: string;
|
|
144
|
+
model?: string;
|
|
145
|
+
session_title?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface SessionEndHookInput extends BaseHookInput {
|
|
148
|
+
hook_event_name: "SessionEnd";
|
|
149
|
+
reason: string;
|
|
150
|
+
}
|
|
151
|
+
export interface NotificationHookInput extends BaseHookInput {
|
|
152
|
+
hook_event_name: "Notification";
|
|
153
|
+
message: string;
|
|
154
|
+
title?: string;
|
|
155
|
+
notification_type: string;
|
|
156
|
+
}
|
|
157
|
+
export interface PermissionRequestHookInput extends BaseHookInput {
|
|
158
|
+
hook_event_name: "PermissionRequest";
|
|
159
|
+
tool_name: string;
|
|
160
|
+
tool_input: unknown;
|
|
161
|
+
permission_suggestions?: PermissionUpdate[];
|
|
162
|
+
}
|
|
163
|
+
export interface PermissionDeniedHookInput extends BaseHookInput {
|
|
164
|
+
hook_event_name: "PermissionDenied";
|
|
165
|
+
tool_name: string;
|
|
166
|
+
tool_input: unknown;
|
|
167
|
+
tool_use_id: string;
|
|
168
|
+
reason: string;
|
|
169
|
+
}
|
|
170
|
+
export interface GenericHookInput extends BaseHookInput {
|
|
171
|
+
hook_event_name: string;
|
|
172
|
+
}
|
|
173
|
+
export type HookInput = PreToolUseHookInput | PostToolUseHookInput | PostToolUseFailureHookInput | UserPromptSubmitHookInput | StopHookInput | SessionStartHookInput | SessionEndHookInput | NotificationHookInput | PermissionRequestHookInput | PermissionDeniedHookInput | GenericHookInput;
|
|
174
|
+
export interface AsyncHookJSONOutput {
|
|
175
|
+
async: true;
|
|
176
|
+
asyncTimeout?: number;
|
|
177
|
+
}
|
|
178
|
+
export interface PreToolUseHookSpecificOutput {
|
|
179
|
+
hookEventName: "PreToolUse";
|
|
180
|
+
permissionDecision?: HookPermissionDecision;
|
|
181
|
+
permissionDecisionReason?: string;
|
|
182
|
+
updatedInput?: Record<string, unknown>;
|
|
183
|
+
additionalContext?: string;
|
|
184
|
+
}
|
|
185
|
+
export interface PostToolUseHookSpecificOutput {
|
|
186
|
+
hookEventName: "PostToolUse";
|
|
187
|
+
additionalContext?: string;
|
|
188
|
+
classifierContext?: string;
|
|
189
|
+
updatedToolOutput?: unknown;
|
|
190
|
+
updatedMCPToolOutput?: unknown;
|
|
191
|
+
}
|
|
192
|
+
export interface PostToolUseFailureHookSpecificOutput {
|
|
193
|
+
hookEventName: "PostToolUseFailure";
|
|
194
|
+
additionalContext?: string;
|
|
195
|
+
}
|
|
196
|
+
export interface UserPromptSubmitHookSpecificOutput {
|
|
197
|
+
hookEventName: "UserPromptSubmit";
|
|
198
|
+
additionalContext?: string;
|
|
199
|
+
sessionTitle?: string;
|
|
200
|
+
suppressOriginalPrompt?: boolean;
|
|
201
|
+
}
|
|
202
|
+
export interface StopHookSpecificOutput {
|
|
203
|
+
hookEventName: "Stop";
|
|
204
|
+
additionalContext?: string;
|
|
205
|
+
}
|
|
206
|
+
export interface SessionStartHookSpecificOutput {
|
|
207
|
+
hookEventName: "SessionStart";
|
|
208
|
+
additionalContext?: string;
|
|
209
|
+
initialUserMessage?: string;
|
|
210
|
+
sessionTitle?: string;
|
|
211
|
+
watchPaths?: string[];
|
|
212
|
+
reloadSkills?: boolean;
|
|
213
|
+
}
|
|
214
|
+
export interface NotificationHookSpecificOutput {
|
|
215
|
+
hookEventName: "Notification";
|
|
216
|
+
additionalContext?: string;
|
|
217
|
+
}
|
|
218
|
+
export interface PermissionRequestHookSpecificOutput {
|
|
219
|
+
hookEventName: "PermissionRequest";
|
|
220
|
+
decision: {
|
|
221
|
+
behavior: "allow";
|
|
222
|
+
updatedInput?: Record<string, unknown>;
|
|
223
|
+
updatedPermissions?: PermissionUpdate[];
|
|
224
|
+
} | {
|
|
225
|
+
behavior: "deny";
|
|
226
|
+
message?: string;
|
|
227
|
+
interrupt?: boolean;
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
export interface PermissionDeniedHookSpecificOutput {
|
|
231
|
+
hookEventName: "PermissionDenied";
|
|
232
|
+
retry?: boolean;
|
|
233
|
+
}
|
|
234
|
+
export interface GenericHookSpecificOutput {
|
|
235
|
+
hookEventName: string;
|
|
236
|
+
additionalContext?: string;
|
|
237
|
+
[key: string]: unknown;
|
|
238
|
+
}
|
|
239
|
+
export type HookSpecificOutput = PreToolUseHookSpecificOutput | PostToolUseHookSpecificOutput | PostToolUseFailureHookSpecificOutput | UserPromptSubmitHookSpecificOutput | StopHookSpecificOutput | SessionStartHookSpecificOutput | NotificationHookSpecificOutput | PermissionRequestHookSpecificOutput | PermissionDeniedHookSpecificOutput | GenericHookSpecificOutput;
|
|
240
|
+
export interface SyncHookJSONOutput {
|
|
241
|
+
continue?: boolean;
|
|
242
|
+
suppressOutput?: boolean;
|
|
243
|
+
stopReason?: string;
|
|
244
|
+
decision?: "approve" | "block";
|
|
245
|
+
systemMessage?: string;
|
|
246
|
+
terminalSequence?: string;
|
|
247
|
+
reason?: string;
|
|
248
|
+
hookSpecificOutput?: HookSpecificOutput;
|
|
249
|
+
}
|
|
250
|
+
export type HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput;
|
|
251
|
+
export type HookCallback = (input: HookInput, toolUseID: string | undefined, options: {
|
|
252
|
+
signal: AbortSignal;
|
|
253
|
+
}) => Promise<HookJSONOutput>;
|
|
254
|
+
export interface HookCallbackMatcher {
|
|
255
|
+
matcher?: string;
|
|
256
|
+
hooks: HookCallback[];
|
|
257
|
+
timeout?: number;
|
|
258
|
+
}
|
|
259
|
+
export interface HookInvocationPayload {
|
|
260
|
+
event: string;
|
|
261
|
+
matchedMatcher?: string;
|
|
262
|
+
sessionId: string;
|
|
263
|
+
agentID?: string;
|
|
264
|
+
toolUseID?: string;
|
|
265
|
+
toolName?: string;
|
|
266
|
+
input?: Record<string, unknown>;
|
|
267
|
+
payload?: unknown;
|
|
268
|
+
policyVersion: string;
|
|
269
|
+
requestId: string;
|
|
270
|
+
hookId: string;
|
|
271
|
+
hookName?: string;
|
|
272
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WinterFrame } from "./frames.js";
|
|
2
|
+
export declare class ProtocolError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare function encodeFrame(frame: WinterFrame): string;
|
|
6
|
+
export declare function decodeFrame(line: string): WinterFrame;
|
|
7
|
+
export declare function splitFrames(chunk: string, carry: string): {
|
|
8
|
+
frames: WinterFrame[];
|
|
9
|
+
carry: string;
|
|
10
|
+
};
|