@yanlinglabs/winter-agent-sdk 0.0.1 → 0.0.3

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/index.js CHANGED
@@ -1,3 +1,26 @@
1
+ import {
2
+ BRAND_TOKEN_RE2,
3
+ FIRST_PARTY_ORIGINATORS2,
4
+ WINTER_BRAND2,
5
+ resolveBrand2,
6
+ envName2,
7
+ mcpToolName2,
8
+ userAgent2,
9
+ isUnset2,
10
+ resolveWinterHome2,
11
+ resolveKeychainServiceForProfile2,
12
+ WinterStoreError2,
13
+ WinterStoreLeaseError2,
14
+ DIALECT_RECORD_ENTRY_TYPE2,
15
+ PROVIDER_STATE_FILE_SUFFIX2,
16
+ WinterCompatibilitySessionStore2
17
+ } from "./index-9e98bg1r.js";
18
+ import {
19
+ deliveryUncertain2,
20
+ refused2,
21
+ unavailable2
22
+ } from "./index-51ysrfm8.js";
23
+
1
24
  // src/query.ts
2
25
  import { randomUUID } from "node:crypto";
3
26
 
@@ -35,120 +58,14 @@ function splitFrames(chunk, carry) {
35
58
  return { frames, carry: nextCarry };
36
59
  }
37
60
 
38
- // src/brand.ts
39
- var BRAND_TOKEN_RE = /^[a-z][a-z0-9-]{0,31}$/;
40
- var DOT_DIR_RE = /^\.[a-z][a-z0-9-]{0,31}$/;
41
- var INSTRUCTIONS_FILE_RE = /^[A-Z][A-Z0-9_]{0,31}\.md$/;
42
- var ENV_PREFIX_RE = /^[A-Z][A-Z0-9]{0,15}_$/;
43
- var KEYCHAIN_SERVICE_RE = /^[a-z][a-z0-9.-]{0,63}$/;
44
- var MAX_PRODUCT_NAME = 64;
45
- var CONTROL_BYTE_RE = /[\u0000-\u001f\u007f]/;
46
- function isHttpsUrl(value) {
47
- let url;
48
- try {
49
- url = new URL(value);
50
- } catch {
51
- return false;
52
- }
53
- if (CONTROL_BYTE_RE.test(value))
54
- return false;
55
- return url.protocol === "https:";
56
- }
57
- var FIRST_PARTY_ORIGINATORS = ["codex", "codex_cli_rs", "openai", "anthropic", "claude", "claude-code"];
58
- var WINTER_BRAND = Object.freeze({
59
- productName: "Winter",
60
- packageName: "winter-agent-sdk",
61
- homeDirName: ".winter",
62
- projectDirName: ".winter",
63
- instructionsFile: "WINTER.md",
64
- envPrefix: "WINTER_",
65
- keychainService: "com.winter.core",
66
- mcpServerName: "winter",
67
- presetName: "winter_code",
68
- processLabel: "winter",
69
- codexOriginator: "winter",
70
- tempRootName: "winter",
71
- pluginManifestDir: ".winter-plugin",
72
- contactUrl: "https://github.com/yanlingLabs/winter-agent-sdk"
73
- });
74
- var FIELD_RULES = [
75
- { field: "packageName", re: BRAND_TOKEN_RE, shape: "a lowercase token of 1-32 chars: a letter, then letters/digits/hyphens" },
76
- { field: "mcpServerName", re: BRAND_TOKEN_RE, shape: "a lowercase token of 1-32 chars: a letter, then letters/digits/hyphens" },
77
- { field: "processLabel", re: BRAND_TOKEN_RE, shape: "a lowercase token of 1-32 chars: a letter, then letters/digits/hyphens" },
78
- { field: "tempRootName", re: BRAND_TOKEN_RE, shape: "a lowercase token of 1-32 chars: a letter, then letters/digits/hyphens" },
79
- { field: "codexOriginator", re: BRAND_TOKEN_RE, shape: "a lowercase token of 1-32 chars: a letter, then letters/digits/hyphens" },
80
- { field: "homeDirName", re: DOT_DIR_RE, shape: "a LEADING DOT then a lowercase token (it names a hidden directory)" },
81
- { field: "projectDirName", re: DOT_DIR_RE, shape: "a LEADING DOT then a lowercase token (it names a hidden directory)" },
82
- { field: "pluginManifestDir", re: DOT_DIR_RE, shape: "a LEADING DOT then a lowercase token (it names a hidden directory)" },
83
- { field: "instructionsFile", re: INSTRUCTIONS_FILE_RE, shape: 'an UPPERCASE name with a `.md` extension, e.g. "ACME.md"' },
84
- { field: "envPrefix", re: ENV_PREFIX_RE, shape: 'an UPPERCASE prefix ENDING IN AN UNDERSCORE, e.g. "ACME_"' },
85
- { field: "keychainService", re: KEYCHAIN_SERVICE_RE, shape: 'a lowercase reverse-DNS-style service name, e.g. "com.acme.core"' }
86
- ];
87
- function resolveBrand(partial) {
88
- const p = partial ?? {};
89
- const pick = (key) => p[key] === undefined ? WINTER_BRAND[key] : p[key];
90
- const brand = {
91
- productName: pick("productName"),
92
- packageName: pick("packageName"),
93
- homeDirName: pick("homeDirName"),
94
- projectDirName: pick("projectDirName"),
95
- instructionsFile: pick("instructionsFile"),
96
- envPrefix: pick("envPrefix"),
97
- keychainService: pick("keychainService"),
98
- mcpServerName: pick("mcpServerName"),
99
- presetName: pick("presetName"),
100
- processLabel: pick("processLabel"),
101
- codexOriginator: pick("codexOriginator"),
102
- tempRootName: pick("tempRootName"),
103
- pluginManifestDir: pick("pluginManifestDir"),
104
- contactUrl: pick("contactUrl")
105
- };
106
- for (const key of Object.keys(brand)) {
107
- if (typeof brand[key] !== "string")
108
- return { ok: false, reason: `brand.${key}: expected a string, got ${brand[key] === null ? "null" : typeof brand[key]}` };
109
- }
110
- if (brand.productName.length === 0 || brand.productName.length > MAX_PRODUCT_NAME) {
111
- return { ok: false, reason: `brand.productName: expected 1-${MAX_PRODUCT_NAME} characters, got ${brand.productName.length}` };
112
- }
113
- if (brand.presetName.length === 0)
114
- return { ok: false, reason: "brand.presetName: expected a non-empty preset name" };
115
- for (const rule of FIELD_RULES) {
116
- const value = brand[rule.field];
117
- if (!rule.re.test(value))
118
- return { ok: false, reason: `brand.${rule.field}: ${JSON.stringify(value)} is not ${rule.shape}` };
119
- }
120
- if (!isHttpsUrl(brand.contactUrl)) {
121
- return {
122
- ok: false,
123
- reason: `brand.contactUrl: ${JSON.stringify(brand.contactUrl)} is not an https:// URL — it is published to vendors in identity headers as the way to reach whoever runs this client`
124
- };
125
- }
126
- if (FIRST_PARTY_ORIGINATORS.includes(brand.codexOriginator)) {
127
- return {
128
- ok: false,
129
- reason: `brand.codexOriginator: ${JSON.stringify(brand.codexOriginator)} is a first-party value. ` + `The originator field names the CLIENT, and sending a vendor's own name presents this software as that vendor's tool — ` + `supply your own token instead (one of: ${FIRST_PARTY_ORIGINATORS.join(", ")} is never it).`
130
- };
131
- }
132
- return { ok: true, brand };
133
- }
134
- function envName(brand, suffix) {
135
- return `${brand.envPrefix}${suffix}`;
136
- }
137
- function mcpToolName(brand, tool) {
138
- return `mcp__${brand.mcpServerName}__${tool}`;
139
- }
140
- function userAgent(brand, version) {
141
- return `${brand.packageName}/${version}`;
142
- }
143
-
144
61
  // src/options.ts
145
62
  var SYSTEM_PROMPT_DYNAMIC_BOUNDARY = "__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__";
146
63
  var DEFAULT_CONTEXT_WINDOW_TOKENS = 200000;
147
64
  var DEFAULT_COMPACTION_THRESHOLD = 0.92;
148
- var DEFAULT_PLANS_DIRECTORY = `${WINTER_BRAND.projectDirName}/plans`;
65
+ var DEFAULT_PLANS_DIRECTORY = `${WINTER_BRAND2.projectDirName}/plans`;
149
66
  var DEFAULT_OUTPUT_STYLE = "default";
150
67
  var DEFAULT_PROVIDER_STALL_TIMEOUT_MS = 120000;
151
- var DEFAULT_KEYCHAIN_SERVICE = WINTER_BRAND.keychainService;
68
+ var DEFAULT_KEYCHAIN_SERVICE = WINTER_BRAND2.keychainService;
152
69
  function isWinterMcpServerInstance(value) {
153
70
  if (typeof value !== "object" || value === null)
154
71
  return false;
@@ -323,30 +240,132 @@ function defaultSpawn(opts) {
323
240
  };
324
241
  }
325
242
 
326
- // src/paths/home.ts
327
- import { homedir } from "node:os";
328
- import { join as join2 } from "node:path";
329
- function isUnset(value) {
330
- return value === undefined || value.trim() === "";
331
- }
332
- function resolveWinterHome(env, brand) {
333
- const b = brand ?? WINTER_BRAND;
334
- const e = env ?? process.env;
335
- const override = e[envName(b, "HOME")];
336
- if (!isUnset(override))
337
- return override;
338
- const profile = e[envName(b, "PROFILE")];
339
- const dirName = profile !== undefined && profile.trim() === "dev" ? `${b.homeDirName}-dev` : b.homeDirName;
340
- return join2(homedir(), dirName);
341
- }
342
- function resolveKeychainServiceForProfile(brand, env, hostSetKeychainService) {
343
- if (hostSetKeychainService)
344
- return brand.keychainService;
345
- const profile = (env ?? process.env)[envName(brand, "PROFILE")];
346
- if (profile === undefined || profile.trim() !== "dev")
347
- return brand.keychainService;
348
- const suffixed = `${brand.keychainService}.dev`;
349
- return suffixed.length <= 64 ? suffixed : brand.keychainService;
243
+ // src/protocol/messaging.ts
244
+ var MESSAGING_CONTROL_SUBTYPES = {
245
+ listReachable: "messaging.list_reachable",
246
+ deliver: "messaging.deliver",
247
+ steerChild: "messaging.steer_child",
248
+ resumeChild: "messaging.resume_child",
249
+ subscribeIdle: "messaging.subscribe_idle",
250
+ senderClass: "messaging.sender_class",
251
+ readNotifications: "messaging.read_notifications",
252
+ idleNotice: "messaging.idle_notice"
253
+ };
254
+ var MESSAGING_HOST_REQUEST_SUBTYPES = [
255
+ MESSAGING_CONTROL_SUBTYPES.listReachable,
256
+ MESSAGING_CONTROL_SUBTYPES.deliver,
257
+ MESSAGING_CONTROL_SUBTYPES.steerChild,
258
+ MESSAGING_CONTROL_SUBTYPES.resumeChild,
259
+ MESSAGING_CONTROL_SUBTYPES.subscribeIdle,
260
+ MESSAGING_CONTROL_SUBTYPES.senderClass,
261
+ MESSAGING_CONTROL_SUBTYPES.readNotifications
262
+ ];
263
+ var MESSAGING_RUNTIME_REQUEST_SUBTYPES = [MESSAGING_CONTROL_SUBTYPES.idleNotice];
264
+ var MESSAGING_CONTROL_SUBTYPE_LIST = Object.values(MESSAGING_CONTROL_SUBTYPES);
265
+ function isRecord(v) {
266
+ return typeof v === "object" && v !== null && !Array.isArray(v);
267
+ }
268
+ var RUNTIME_OBJECT_KINDS = ["session", "agent"];
269
+ var RUNTIME_KINDS = ["claude-agent", "winter-agent"];
270
+ var PERMISSION_CLASS_LABELS = ["prompts", "bypasses", "unknown"];
271
+ var DELIVERY_STATUSES = [
272
+ "delivered",
273
+ "queued",
274
+ "resumed_and_delivered",
275
+ "held",
276
+ "subscribed",
277
+ "delivery_uncertain",
278
+ "refused",
279
+ "ambiguous",
280
+ "not_found",
281
+ "unavailable"
282
+ ];
283
+ function isRuntimeAddress(v) {
284
+ if (!isRecord(v))
285
+ return false;
286
+ if (!RUNTIME_OBJECT_KINDS.includes(v.objectKind))
287
+ return false;
288
+ if (!RUNTIME_KINDS.includes(v.runtimeKind))
289
+ return false;
290
+ if (typeof v.winterSessionId !== "string" || v.winterSessionId.length === 0)
291
+ return false;
292
+ if (v.objectKind === "agent" && (typeof v.childId !== "string" || v.childId.length === 0))
293
+ return false;
294
+ return true;
295
+ }
296
+ function isGlobalAgentMessage(v) {
297
+ if (!isRecord(v))
298
+ return false;
299
+ if (typeof v.messageId !== "string" || v.messageId.length === 0)
300
+ return false;
301
+ if (!isRuntimeAddress(v.from) || !isRuntimeAddress(v.to))
302
+ return false;
303
+ if (typeof v.body !== "string")
304
+ return false;
305
+ if (typeof v.notifyWhenIdle !== "boolean")
306
+ return false;
307
+ if (typeof v.hopCount !== "number")
308
+ return false;
309
+ if (!PERMISSION_CLASS_LABELS.includes(v.senderPermissionClass))
310
+ return false;
311
+ return true;
312
+ }
313
+ function isDeliveryOutcome(v) {
314
+ if (!isRecord(v))
315
+ return false;
316
+ if (!DELIVERY_STATUSES.includes(v.status))
317
+ return false;
318
+ if (typeof v.messageId !== "string")
319
+ return false;
320
+ if (v.status === "ambiguous" && !Array.isArray(v.candidates))
321
+ return false;
322
+ if (v.status === "unavailable" && typeof v.retryable !== "boolean")
323
+ return false;
324
+ return true;
325
+ }
326
+ function isListedRuntimeObjectArray(v) {
327
+ return Array.isArray(v) && v.every((row) => isRecord(row) && typeof row.address === "string" && RUNTIME_OBJECT_KINDS.includes(row.objectKind) && isRecord(row.capabilities));
328
+ }
329
+ function isPermissionClassLabel(v) {
330
+ return typeof v === "string" && PERMISSION_CLASS_LABELS.includes(v);
331
+ }
332
+ function isMessagingDeliverRequest(v) {
333
+ return isRecord(v) && isGlobalAgentMessage(v.message);
334
+ }
335
+ function isMessagingChildRequest(v) {
336
+ return isRecord(v) && typeof v.id === "string" && v.id.length > 0 && isGlobalAgentMessage(v.message);
337
+ }
338
+ function isNotificationRecord(v) {
339
+ return isRecord(v) && typeof v.notification_id === "string" && typeof v.origin === "string" && typeof v.queued_at === "string" && typeof v.content === "string";
340
+ }
341
+ function isMessagingNotificationsPage(v) {
342
+ return isRecord(v) && Array.isArray(v.notifications) && v.notifications.every(isNotificationRecord) && typeof v.remaining === "number";
343
+ }
344
+ function isMessagingIdleNoticePayload(v) {
345
+ return isRecord(v) && typeof v.subscriberSessionId === "string" && isNotificationRecord(v.notice);
346
+ }
347
+ function isMessagingReadNotificationsRequest(v) {
348
+ if (!isRecord(v))
349
+ return false;
350
+ if (v.subscriberSessionId !== undefined && typeof v.subscriberSessionId !== "string")
351
+ return false;
352
+ if (v.max !== undefined && (typeof v.max !== "number" || !Number.isFinite(v.max) || v.max < 0))
353
+ return false;
354
+ return true;
355
+ }
356
+ function isMessagingSubscribeIdleRequest(v) {
357
+ if (!isRecord(v))
358
+ return false;
359
+ if (typeof v.id !== "string" || v.id.length === 0)
360
+ return false;
361
+ if (typeof v.messageId !== "string" || v.messageId.length === 0)
362
+ return false;
363
+ if (v.subscriberSessionId !== undefined && typeof v.subscriberSessionId !== "string")
364
+ return false;
365
+ return true;
366
+ }
367
+ function resolveFacetTarget(sessionId, id, parse, buildChild) {
368
+ return parse(id) ?? buildChild(sessionId, id);
350
369
  }
351
370
 
352
371
  // src/query.ts
@@ -503,7 +522,7 @@ function query(args) {
503
522
  }
504
523
  }
505
524
  if (options.sessionStore !== undefined && options.persistSession === false) {
506
- const homeVar = envName({ envPrefix: options.brand?.envPrefix ?? WINTER_BRAND.envPrefix }, "HOME");
525
+ const homeVar = envName2({ envPrefix: options.brand?.envPrefix ?? WINTER_BRAND2.envPrefix }, "HOME");
507
526
  throw new Error(`sessionStore cannot be used with persistSession: false -- the storage adapter requires local writes to mirror from. Use ${homeVar}=/tmp for ephemeral local writes with external mirroring.`);
508
527
  }
509
528
  if (options.sessionStore !== undefined && options.enableFileCheckpointing === true) {
@@ -512,7 +531,7 @@ function query(args) {
512
531
  if (options.keychainService !== undefined && options.brand?.keychainService !== undefined && options.brand.keychainService !== options.keychainService) {
513
532
  console.error(`winter: both 'keychainService' (${options.keychainService}) and 'brand.keychainService' (${options.brand.keychainService}) are set and differ — ` + `the deprecated 'keychainService' option wins. Set only 'brand.keychainService'.`);
514
533
  }
515
- const brandResolution = resolveBrand({
534
+ const brandResolution = resolveBrand2({
516
535
  ...options.brand,
517
536
  ...options.keychainService !== undefined ? { keychainService: options.keychainService } : {}
518
537
  });
@@ -521,7 +540,7 @@ function query(args) {
521
540
  const hostSetKeychainService = options.brand?.keychainService !== undefined || options.keychainService !== undefined;
522
541
  const brand = {
523
542
  ...brandResolution.brand,
524
- keychainService: resolveKeychainServiceForProfile(brandResolution.brand, options.env, hostSetKeychainService)
543
+ keychainService: resolveKeychainServiceForProfile2(brandResolution.brand, options.env, hostSetKeychainService)
525
544
  };
526
545
  const runtimeHooksConfig = buildRuntimeHooksConfig(options.hooks);
527
546
  const wireMcpServers = toWireMcpServers(options.mcpServers);
@@ -577,7 +596,7 @@ function query(args) {
577
596
  ...options.includePartialMessages !== undefined ? { includePartialMessages: options.includePartialMessages } : {},
578
597
  ...options.maxBudgetUsd !== undefined ? { maxBudgetUsd: options.maxBudgetUsd } : {},
579
598
  ...options.providerStallTimeoutMs !== undefined ? { providerStallTimeoutMs: options.providerStallTimeoutMs } : {},
580
- ...brand.keychainService !== WINTER_BRAND.keychainService || options.keychainService !== undefined ? { keychainService: brand.keychainService } : {},
599
+ ...brand.keychainService !== WINTER_BRAND2.keychainService || options.keychainService !== undefined ? { keychainService: brand.keychainService } : {},
581
600
  ...options.autoClassifier !== undefined ? { autoClassifier: options.autoClassifier } : {},
582
601
  ...options.advisor !== undefined ? { advisor: options.advisor } : {},
583
602
  brand
@@ -819,6 +838,7 @@ function query(args) {
819
838
  }
820
839
  }
821
840
  }
841
+ const idleNoticeHandlers = new Set;
822
842
  const gen = iterate();
823
843
  gen.interrupt = async () => {
824
844
  await sendControlRequest("interrupt", { scope: "turn" });
@@ -841,6 +861,85 @@ function query(args) {
841
861
  gen.setPermissionMode = async (mode) => {
842
862
  await sendControlRequest("set_permission_mode", mode);
843
863
  };
864
+ async function deliveryCall(subtype, payload, messageId) {
865
+ let answer;
866
+ try {
867
+ answer = await sendControlRequest(subtype, payload);
868
+ } catch (err) {
869
+ const code = err instanceof WinterRpcError ? err.code : "";
870
+ const message = err instanceof Error ? err.message : String(err);
871
+ if (code === "invalid_messaging_request")
872
+ return refused2(messageId, message);
873
+ if (code === "messaging_unavailable")
874
+ return unavailable2(messageId, false, message);
875
+ return deliveryUncertain2(messageId, `'${subtype}' failed: ${message}`);
876
+ }
877
+ return isDeliveryOutcome(answer) ? answer : deliveryUncertain2(messageId, `the runtime returned a malformed delivery outcome for '${subtype}'`);
878
+ }
879
+ gen.messaging = {
880
+ async listReachable() {
881
+ const payload = await sendControlRequest(MESSAGING_CONTROL_SUBTYPES.listReachable, undefined).catch(() => {
882
+ return;
883
+ });
884
+ return isListedRuntimeObjectArray(payload) ? payload : [];
885
+ },
886
+ deliver(msg) {
887
+ const request = { message: msg };
888
+ return deliveryCall(MESSAGING_CONTROL_SUBTYPES.deliver, request, msg.messageId);
889
+ },
890
+ steerChild(id, msg) {
891
+ const request = { id, message: msg };
892
+ return deliveryCall(MESSAGING_CONTROL_SUBTYPES.steerChild, request, msg.messageId);
893
+ },
894
+ resumeChild(id, msg) {
895
+ const request = { id, message: msg };
896
+ return deliveryCall(MESSAGING_CONTROL_SUBTYPES.resumeChild, request, msg.messageId);
897
+ },
898
+ subscribeIdle(id, opts) {
899
+ const request = {
900
+ id,
901
+ messageId: opts.messageId,
902
+ ...opts.subscriberSessionId !== undefined ? { subscriberSessionId: opts.subscriberSessionId } : {}
903
+ };
904
+ return deliveryCall(MESSAGING_CONTROL_SUBTYPES.subscribeIdle, request, opts.messageId);
905
+ },
906
+ async senderClass() {
907
+ const payload = await sendControlRequest(MESSAGING_CONTROL_SUBTYPES.senderClass, undefined).catch(() => {
908
+ return;
909
+ });
910
+ const label = typeof payload === "object" && payload !== null ? payload.senderClass : undefined;
911
+ return isPermissionClassLabel(label) ? label : "unknown";
912
+ },
913
+ async readNotifications(opts) {
914
+ const request = {
915
+ ...opts?.subscriberSessionId !== undefined ? { subscriberSessionId: opts.subscriberSessionId } : {},
916
+ ...opts?.max !== undefined ? { max: opts.max } : {}
917
+ };
918
+ const payload = await sendControlRequest(MESSAGING_CONTROL_SUBTYPES.readNotifications, request).catch(() => {
919
+ return;
920
+ });
921
+ return isMessagingNotificationsPage(payload) ? payload : { notifications: [], remaining: 0 };
922
+ },
923
+ onIdleNotice(handler) {
924
+ idleNoticeHandlers.add(handler);
925
+ return () => {
926
+ idleNoticeHandlers.delete(handler);
927
+ };
928
+ }
929
+ };
930
+ controlRequestHandlers.set(MESSAGING_CONTROL_SUBTYPES.idleNotice, async (payload) => {
931
+ if (!isMessagingIdleNoticePayload(payload)) {
932
+ return { ok: false, error: { code: "invalid_idle_notice", message: "messaging.idle_notice requires { subscriberSessionId: string, notice: NotificationRecord }" } };
933
+ }
934
+ for (const handler of [...idleNoticeHandlers]) {
935
+ try {
936
+ handler(payload);
937
+ } catch (err) {
938
+ console.error(`winter: onIdleNotice handler threw for notification ${payload.notice.notification_id}: ${err instanceof Error ? err.message : String(err)} -- the notice is still queued for readNotifications()`);
939
+ }
940
+ }
941
+ return { ok: true, payload: { delivered: idleNoticeHandlers.size } };
942
+ });
844
943
  gen.rewindFiles = async (userMessageId, options) => {
845
944
  const payload = await sendControlRequest("rewind_files", { user_message_id: userMessageId, ...options?.dryRun !== undefined ? { dry_run: options.dryRun } : {} });
846
945
  if (typeof payload !== "object" || payload === null || typeof payload.canRewind !== "boolean") {
@@ -861,8 +960,14 @@ function query(args) {
861
960
  };
862
961
  return gen;
863
962
  }
963
+ // src/version.ts
964
+ var SDK_VERSION = "0.0.3";
864
965
  // src/paths/project-key.ts
865
- var MAX_UNSUFFIXED_LENGTH = 200;
966
+ var TRANSCRIPT_PROJECT_KEY_MAX_LENGTH = 64;
967
+ var VENDOR_PROJECT_KEY_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
968
+ function isVendorCompliantProjectKey(key) {
969
+ return VENDOR_PROJECT_KEY_PATTERN.test(key);
970
+ }
866
971
  function sanitize(absPath) {
867
972
  return absPath.replace(/[^a-zA-Z0-9]/g, "-");
868
973
  }
@@ -878,9 +983,10 @@ function overflowSuffix(rawAbsPath) {
878
983
  }
879
984
  function transcriptProjectKey(absPath) {
880
985
  const sanitized = sanitize(absPath);
881
- if (sanitized.length <= MAX_UNSUFFIXED_LENGTH)
986
+ if (sanitized.length <= TRANSCRIPT_PROJECT_KEY_MAX_LENGTH)
882
987
  return sanitized;
883
- return `${sanitized.slice(0, MAX_UNSUFFIXED_LENGTH)}-${overflowSuffix(absPath)}`;
988
+ const suffix = overflowSuffix(absPath);
989
+ return sanitized.slice(0, TRANSCRIPT_PROJECT_KEY_MAX_LENGTH - 1 - suffix.length) + "-" + suffix;
884
990
  }
885
991
  // src/paths/keys.ts
886
992
  import { realpathSync } from "node:fs";
@@ -916,590 +1022,15 @@ function compatibilityKeys(cwd) {
916
1022
  const memoryKey = commonRoot === null ? cwdKey : transcriptProjectKey(commonRoot);
917
1023
  return { transcriptProjectKey: cwdKey, memoryProjectKey: memoryKey, tempProjectKey: cwdKey };
918
1024
  }
919
- // src/store/session-store.ts
920
- import {
921
- mkdirSync,
922
- lstatSync,
923
- chmodSync,
924
- readdirSync,
925
- readFileSync as readFileSync2,
926
- statSync,
927
- openSync as openSync2,
928
- fsyncSync as fsyncSync2,
929
- closeSync as closeSync2,
930
- renameSync as renameSync2,
931
- rmSync,
932
- ftruncateSync,
933
- constants as fsConstants
934
- } from "node:fs";
935
- import { randomUUID as randomUUID2 } from "node:crypto";
936
- import { join as join3 } from "node:path";
937
-
938
- // src/store/leases.ts
939
- import { openSync, readFileSync, writeSync, fsyncSync, closeSync, renameSync, linkSync, unlinkSync } from "node:fs";
940
-
941
- class WinterStoreError extends Error {
942
- constructor(message) {
943
- super(message);
944
- this.name = "WinterStoreError";
945
- }
946
- }
947
-
948
- class WinterStoreLeaseError extends WinterStoreError {
949
- heldByPid;
950
- constructor(message, heldByPid) {
951
- super(message);
952
- this.heldByPid = heldByPid;
953
- this.name = "WinterStoreLeaseError";
954
- }
955
- }
956
- function isPidAlive(pid) {
957
- try {
958
- process.kill(pid, 0);
959
- return true;
960
- } catch (err) {
961
- const code = err.code;
962
- if (code === "ESRCH")
963
- return false;
964
- if (code === "EPERM")
965
- return true;
966
- throw err;
967
- }
968
- }
969
- function writeAllSync(fd, buf) {
970
- let written = 0;
971
- while (written < buf.length) {
972
- written += writeSync(fd, buf, written, buf.length - written);
973
- }
974
- }
975
- function readLeaseInfo(lockPath) {
976
- let raw;
977
- try {
978
- raw = readFileSync(lockPath, "utf8");
979
- } catch (err) {
980
- if (err.code === "ENOENT")
981
- return null;
982
- throw err;
983
- }
984
- try {
985
- const parsed = JSON.parse(raw);
986
- if (typeof parsed.pid === "number" && typeof parsed.startTimeMs === "number") {
987
- return { pid: parsed.pid, startTimeMs: parsed.startTimeMs };
988
- }
989
- } catch {}
990
- return null;
991
- }
992
- function createExclusive(lockPath, info) {
993
- const data = Buffer.from(JSON.stringify(info), "utf8");
994
- const tmpPath = `${lockPath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
995
- const fd = openSync(tmpPath, "wx", 384);
996
- try {
997
- writeAllSync(fd, data);
998
- fsyncSync(fd);
999
- } finally {
1000
- closeSync(fd);
1001
- }
1002
- try {
1003
- linkSync(tmpPath, lockPath);
1004
- } finally {
1005
- try {
1006
- unlinkSync(tmpPath);
1007
- } catch (err) {
1008
- if (err.code !== "ENOENT")
1009
- throw err;
1010
- }
1011
- }
1012
- }
1013
- function writeLeaseInfoReplacing(lockPath, info) {
1014
- const data = Buffer.from(JSON.stringify(info), "utf8");
1015
- const tmpPath = `${lockPath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
1016
- const fd = openSync(tmpPath, "wx", 384);
1017
- try {
1018
- writeAllSync(fd, data);
1019
- fsyncSync(fd);
1020
- } finally {
1021
- closeSync(fd);
1022
- }
1023
- renameSync(tmpPath, lockPath);
1024
- }
1025
- function acquireLease(lockPath) {
1026
- const fresh = { pid: process.pid, startTimeMs: Date.now() };
1027
- try {
1028
- createExclusive(lockPath, fresh);
1029
- return fresh;
1030
- } catch (err) {
1031
- if (err.code !== "EEXIST")
1032
- throw err;
1033
- }
1034
- const existing = readLeaseInfo(lockPath);
1035
- if (existing !== null && existing.pid === process.pid) {
1036
- return existing;
1037
- }
1038
- if (existing !== null && isPidAlive(existing.pid)) {
1039
- throw new WinterStoreLeaseError(`session lease is held by another live process (pid ${existing.pid}); refusing a concurrent writer`, existing.pid);
1040
- }
1041
- writeLeaseInfoReplacing(lockPath, fresh);
1042
- return fresh;
1043
- }
1044
-
1045
- // src/store/session-store.ts
1046
- var DIALECT_RECORD_ENTRY_TYPE = "winter_dialect_record";
1047
- var PROVIDER_STATE_FILE_SUFFIX = ".provider-state.jsonl";
1048
- function assertSafeSingleSegment(value, label) {
1049
- if (value === "")
1050
- throw new WinterStoreError(`${label} must not be empty`);
1051
- if (value.includes("/"))
1052
- throw new WinterStoreError(`${label} must not contain a path separator: ${JSON.stringify(value)}`);
1053
- if (value === "." || value === "..")
1054
- throw new WinterStoreError(`${label} must not be a traversal segment: ${JSON.stringify(value)}`);
1055
- }
1056
- function assertSafeSubpath(value) {
1057
- if (value === "")
1058
- throw new WinterStoreError("subpath must not be empty");
1059
- if (value.startsWith("/"))
1060
- throw new WinterStoreError(`subpath must not be absolute: ${JSON.stringify(value)}`);
1061
- const segments = value.split("/");
1062
- for (const segment of segments) {
1063
- if (segment === "") {
1064
- throw new WinterStoreError(`subpath must not contain empty segments (double/trailing separators): ${JSON.stringify(value)}`);
1065
- }
1066
- if (segment === "." || segment === "..") {
1067
- throw new WinterStoreError(`subpath must not contain a traversal segment: ${JSON.stringify(value)}`);
1068
- }
1069
- }
1070
- return segments;
1071
- }
1072
- function projectDir(winterHome, projectKey) {
1073
- return join3(winterHome, "projects", projectKey);
1074
- }
1075
- function sessionStem(winterHome, projectKey, sessionId) {
1076
- assertSafeSingleSegment(projectKey, "projectKey");
1077
- assertSafeSingleSegment(sessionId, "sessionId");
1078
- return join3(projectDir(winterHome, projectKey), sessionId);
1079
- }
1080
- function locateResource(winterHome, key) {
1081
- assertSafeSingleSegment(key.projectKey, "projectKey");
1082
- assertSafeSingleSegment(key.sessionId, "sessionId");
1083
- const projDir = projectDir(winterHome, key.projectKey);
1084
- const dirLevels = [winterHome, join3(winterHome, "projects"), projDir];
1085
- if (key.subpath === undefined) {
1086
- return { dirLevels, stem: join3(projDir, key.sessionId) };
1087
- }
1088
- const segments = assertSafeSubpath(key.subpath);
1089
- let current = join3(projDir, key.sessionId);
1090
- dirLevels.push(current);
1091
- for (let i = 0;i < segments.length - 1; i++) {
1092
- current = join3(current, segments[i]);
1093
- dirLevels.push(current);
1094
- }
1095
- const stem = join3(current, segments[segments.length - 1]);
1096
- return { dirLevels, stem };
1097
- }
1098
- function realUid() {
1099
- return process.getuid();
1100
- }
1101
- function ensureSecureDir(path) {
1102
- try {
1103
- mkdirSync(path, { mode: 448 });
1104
- } catch (err) {
1105
- if (err.code !== "EEXIST")
1106
- throw err;
1107
- }
1108
- const stat = lstatSync(path);
1109
- if (stat.isSymbolicLink())
1110
- throw new WinterStoreError(`refusing a symlink at a level the store must own: ${path}`);
1111
- if (!stat.isDirectory())
1112
- throw new WinterStoreError(`expected a directory, found something else at: ${path}`);
1113
- if (stat.uid !== realUid())
1114
- throw new WinterStoreError(`refusing a directory owned by a different uid: ${path}`);
1115
- chmodSync(path, 448);
1116
- }
1117
- var APPEND_FLAGS = fsConstants.O_WRONLY | fsConstants.O_APPEND | fsConstants.O_CREAT | fsConstants.O_NOFOLLOW;
1118
- var RW_EXISTING_FLAGS = fsConstants.O_RDWR | fsConstants.O_NOFOLLOW;
1119
- function appendLinesAtomically(path, lines) {
1120
- const data = Buffer.from(lines.map((l) => l + `
1121
- `).join(""), "utf8");
1122
- const fd = openSync2(path, APPEND_FLAGS, 384);
1123
- try {
1124
- writeAllSync(fd, data);
1125
- fsyncSync2(fd);
1126
- } finally {
1127
- closeSync2(fd);
1128
- }
1129
- chmodSync(path, 384);
1130
- }
1131
- function quarantineTornTail(jsonlPath, tornRaw) {
1132
- const quarantinePath = `${jsonlPath}.tail-quarantine`;
1133
- const fd = openSync2(quarantinePath, APPEND_FLAGS, 384);
1134
- try {
1135
- writeAllSync(fd, tornRaw);
1136
- fsyncSync2(fd);
1137
- } finally {
1138
- closeSync2(fd);
1139
- }
1140
- chmodSync(quarantinePath, 384);
1141
- }
1142
- function repairTruncate(jsonlPath, keepBytes) {
1143
- const fd = openSync2(jsonlPath, RW_EXISTING_FLAGS);
1144
- try {
1145
- ftruncateSync(fd, keepBytes);
1146
- fsyncSync2(fd);
1147
- } finally {
1148
- closeSync2(fd);
1149
- }
1150
- }
1151
- function writeJsonAtomically(path, value) {
1152
- const data = Buffer.from(JSON.stringify(value), "utf8");
1153
- const tmpPath = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
1154
- const fd = openSync2(tmpPath, "wx", 384);
1155
- try {
1156
- writeAllSync(fd, data);
1157
- fsyncSync2(fd);
1158
- } finally {
1159
- closeSync2(fd);
1160
- }
1161
- renameSync2(tmpPath, path);
1162
- chmodSync(path, 384);
1163
- }
1164
- function readJsonIfExists(path) {
1165
- let raw;
1166
- try {
1167
- raw = readFileSync2(path, "utf8");
1168
- } catch (err) {
1169
- if (err.code === "ENOENT")
1170
- return null;
1171
- throw err;
1172
- }
1173
- try {
1174
- return JSON.parse(raw);
1175
- } catch {
1176
- return null;
1177
- }
1178
- }
1179
- function rmIfExists(path) {
1180
- try {
1181
- rmSync(path);
1182
- } catch (err) {
1183
- if (err.code !== "ENOENT")
1184
- throw err;
1185
- }
1186
- }
1187
- var NEWLINE = 10;
1188
- function isParseableJson(text) {
1189
- try {
1190
- JSON.parse(text);
1191
- return true;
1192
- } catch {
1193
- return false;
1194
- }
1195
- }
1196
- function decodeCompleteLines(buf) {
1197
- if (buf.length === 0)
1198
- return [];
1199
- const lines = buf.toString("utf8").split(`
1200
- `);
1201
- lines.pop();
1202
- return lines.map((line) => JSON.parse(line));
1203
- }
1204
- function parseWithTailRepair(buf) {
1205
- if (buf.length === 0)
1206
- return { entries: [], torn: null };
1207
- const endsWithNewline = buf[buf.length - 1] === NEWLINE;
1208
- if (endsWithNewline) {
1209
- const searchEnd = buf.length - 2;
1210
- const prevNL = searchEnd < 0 ? -1 : buf.lastIndexOf(NEWLINE, searchEnd);
1211
- const lastLineStart = prevNL + 1;
1212
- const lastLine = buf.subarray(lastLineStart, buf.length - 1).toString("utf8");
1213
- if (isParseableJson(lastLine)) {
1214
- return { entries: decodeCompleteLines(buf), torn: null };
1215
- }
1216
- const keepBytes = lastLineStart;
1217
- const tornRaw = Buffer.from(buf.subarray(lastLineStart));
1218
- return { entries: decodeCompleteLines(buf.subarray(0, keepBytes)), torn: { raw: tornRaw, keepBytes } };
1219
- }
1220
- const lastNL = buf.lastIndexOf(NEWLINE);
1221
- const keepBytes = lastNL + 1;
1222
- const tornRaw = Buffer.from(buf.subarray(keepBytes));
1223
- return { entries: decodeCompleteLines(buf.subarray(0, keepBytes)), torn: { raw: tornRaw, keepBytes } };
1224
- }
1225
- function hasLiveForeignLeaseHolder(lockPath) {
1226
- const lease = readLeaseInfo(lockPath);
1227
- return lease !== null && lease.pid !== process.pid && isPidAlive(lease.pid);
1228
- }
1229
- function walkResourceStems(dir, prefix, out) {
1230
- let entries;
1231
- try {
1232
- entries = readdirSync(dir, { withFileTypes: true });
1233
- } catch (err) {
1234
- if (err.code === "ENOENT")
1235
- return;
1236
- throw err;
1237
- }
1238
- for (const dirent of entries) {
1239
- const relPath = prefix === "" ? dirent.name : `${prefix}/${dirent.name}`;
1240
- if (dirent.isDirectory()) {
1241
- walkResourceStems(join3(dir, dirent.name), relPath, out);
1242
- } else if (dirent.isFile() && dirent.name.endsWith(".jsonl")) {
1243
- out.add(relPath.slice(0, -".jsonl".length));
1244
- } else if (dirent.isFile() && dirent.name.endsWith(".meta.json")) {
1245
- out.add(relPath.slice(0, -".meta.json".length));
1246
- }
1247
- }
1248
- }
1249
- function foldSummary(summaryPath, sessionId, newEntries, dialectExtra) {
1250
- const previous = readJsonIfExists(summaryPath) ?? {};
1251
- const mechanical = {};
1252
- if (newEntries.length > 0) {
1253
- const lastEntry = newEntries[newEntries.length - 1];
1254
- mechanical.entryCount = (previous.entryCount ?? 0) + newEntries.length;
1255
- mechanical.lastEntryType = lastEntry.type;
1256
- if (lastEntry.timestamp !== undefined)
1257
- mechanical.lastTimestamp = lastEntry.timestamp;
1258
- }
1259
- const updated = {
1260
- ...previous,
1261
- ...dialectExtra,
1262
- sessionId,
1263
- ...mechanical,
1264
- mtime: Date.now()
1265
- };
1266
- writeJsonAtomically(summaryPath, updated);
1267
- }
1268
-
1269
- class WinterCompatibilitySessionStore {
1270
- winterHome;
1271
- constructor(opts) {
1272
- this.winterHome = opts.winterHome;
1273
- }
1274
- async append(key, entries) {
1275
- if (entries.length === 0)
1276
- return;
1277
- const { dirLevels, stem } = locateResource(this.winterHome, key);
1278
- for (const level of dirLevels)
1279
- ensureSecureDir(level);
1280
- const lockPath = `${sessionStem(this.winterHome, key.projectKey, key.sessionId)}.lock`;
1281
- acquireLease(lockPath);
1282
- chmodSync(lockPath, 384);
1283
- const jsonlPath = `${stem}.jsonl`;
1284
- const metaPath = `${stem}.meta.json`;
1285
- const nativeEntries = [];
1286
- let latestMetadata;
1287
- let dialectExtra;
1288
- for (const e of entries) {
1289
- if (e.type === "agent_metadata") {
1290
- latestMetadata = e;
1291
- } else if (e.type === DIALECT_RECORD_ENTRY_TYPE) {
1292
- const { type: _type, ...fields } = e;
1293
- dialectExtra = fields;
1294
- } else {
1295
- nativeEntries.push(e);
1296
- }
1297
- }
1298
- if (nativeEntries.length > 0) {
1299
- appendLinesAtomically(jsonlPath, nativeEntries.map((e) => JSON.stringify(e)));
1300
- }
1301
- if (latestMetadata !== undefined) {
1302
- writeJsonAtomically(metaPath, latestMetadata);
1303
- }
1304
- if (key.subpath === undefined && (nativeEntries.length > 0 || dialectExtra !== undefined)) {
1305
- foldSummary(`${sessionStem(this.winterHome, key.projectKey, key.sessionId)}.summary.json`, key.sessionId, nativeEntries, dialectExtra);
1306
- }
1307
- }
1308
- async load(key) {
1309
- const { stem } = locateResource(this.winterHome, key);
1310
- const jsonlPath = `${stem}.jsonl`;
1311
- const metaPath = `${stem}.meta.json`;
1312
- let raw;
1313
- try {
1314
- raw = readFileSync2(jsonlPath);
1315
- } catch (err) {
1316
- if (err.code !== "ENOENT")
1317
- throw err;
1318
- raw = null;
1319
- }
1320
- if (raw === null) {
1321
- const meta = readJsonIfExists(metaPath);
1322
- return meta === null ? null : [meta];
1323
- }
1324
- const { entries, torn } = parseWithTailRepair(raw);
1325
- if (torn !== null) {
1326
- const lockPath = `${sessionStem(this.winterHome, key.projectKey, key.sessionId)}.lock`;
1327
- if (!hasLiveForeignLeaseHolder(lockPath)) {
1328
- quarantineTornTail(jsonlPath, torn.raw);
1329
- repairTruncate(jsonlPath, torn.keepBytes);
1330
- }
1331
- }
1332
- const meta = readJsonIfExists(metaPath);
1333
- if (meta !== null)
1334
- entries.push(meta);
1335
- return entries;
1336
- }
1337
- async listSessions(projectKey) {
1338
- assertSafeSingleSegment(projectKey, "projectKey");
1339
- const dir = projectDir(this.winterHome, projectKey);
1340
- let names;
1341
- try {
1342
- names = readdirSync(dir);
1343
- } catch (err) {
1344
- if (err.code === "ENOENT")
1345
- return [];
1346
- throw err;
1347
- }
1348
- const result = [];
1349
- const seenSessionIds = new Set;
1350
- for (const name of names) {
1351
- if (!name.endsWith(".jsonl"))
1352
- continue;
1353
- const full = join3(dir, name);
1354
- const stat = statSync(full);
1355
- if (!stat.isFile())
1356
- continue;
1357
- const sessionId = name.slice(0, -".jsonl".length);
1358
- seenSessionIds.add(sessionId);
1359
- result.push({ sessionId, mtime: stat.mtimeMs });
1360
- }
1361
- for (const name of names) {
1362
- if (!name.endsWith(".meta.json"))
1363
- continue;
1364
- const sessionId = name.slice(0, -".meta.json".length);
1365
- if (seenSessionIds.has(sessionId))
1366
- continue;
1367
- const full = join3(dir, name);
1368
- const stat = statSync(full);
1369
- if (!stat.isFile())
1370
- continue;
1371
- seenSessionIds.add(sessionId);
1372
- result.push({ sessionId, mtime: stat.mtimeMs });
1373
- }
1374
- return result;
1375
- }
1376
- async listSessionSummaries(projectKey) {
1377
- assertSafeSingleSegment(projectKey, "projectKey");
1378
- const dir = projectDir(this.winterHome, projectKey);
1379
- let names;
1380
- try {
1381
- names = readdirSync(dir);
1382
- } catch (err) {
1383
- if (err.code === "ENOENT")
1384
- return [];
1385
- throw err;
1386
- }
1387
- const result = [];
1388
- for (const name of names) {
1389
- if (!name.endsWith(".summary.json"))
1390
- continue;
1391
- const parsed = readJsonIfExists(join3(dir, name));
1392
- if (parsed !== null)
1393
- result.push(parsed);
1394
- }
1395
- return result;
1396
- }
1397
- async delete(key) {
1398
- const { stem } = locateResource(this.winterHome, key);
1399
- if (key.subpath === undefined) {
1400
- rmIfExists(`${stem}.jsonl`);
1401
- rmIfExists(`${stem}.jsonl.tail-quarantine`);
1402
- rmIfExists(`${stem}.lock`);
1403
- rmIfExists(`${stem}.summary.json`);
1404
- rmIfExists(`${stem}.meta.json`);
1405
- rmIfExists(`${stem}${PROVIDER_STATE_FILE_SUFFIX}`);
1406
- rmSync(stem, { recursive: true, force: true });
1407
- } else {
1408
- rmIfExists(`${stem}.jsonl`);
1409
- rmIfExists(`${stem}.jsonl.tail-quarantine`);
1410
- rmIfExists(`${stem}.meta.json`);
1411
- rmIfExists(`${stem}${PROVIDER_STATE_FILE_SUFFIX}`);
1412
- }
1413
- }
1414
- async listSubkeys(key) {
1415
- const sessionDir = sessionStem(this.winterHome, key.projectKey, key.sessionId);
1416
- const results = new Set;
1417
- walkResourceStems(sessionDir, "", results);
1418
- return [...results];
1419
- }
1420
- async listProjectKeys() {
1421
- const dir = join3(this.winterHome, "projects");
1422
- let entries;
1423
- try {
1424
- entries = readdirSync(dir, { withFileTypes: true });
1425
- } catch (err) {
1426
- if (err.code === "ENOENT")
1427
- return [];
1428
- throw err;
1429
- }
1430
- return entries.filter((e) => e.isDirectory()).map((e) => e.name);
1431
- }
1432
- async copyProviderStateForFork(src, dest) {
1433
- const { stem: srcStem } = locateResource(this.winterHome, src);
1434
- const { stem: destStem, dirLevels } = locateResource(this.winterHome, dest);
1435
- let raw;
1436
- try {
1437
- raw = readFileSync2(`${srcStem}${PROVIDER_STATE_FILE_SUFFIX}`, "utf8");
1438
- } catch (err) {
1439
- if (err.code === "ENOENT")
1440
- return 0;
1441
- throw err;
1442
- }
1443
- const lines = [];
1444
- for (const line of raw.split(`
1445
- `)) {
1446
- if (line.length === 0)
1447
- continue;
1448
- let record;
1449
- try {
1450
- record = JSON.parse(line);
1451
- } catch {
1452
- continue;
1453
- }
1454
- if (typeof record !== "object" || record === null || Array.isArray(record))
1455
- continue;
1456
- lines.push(JSON.stringify({ ...record, uuid: randomUUID2(), sessionId: dest.sessionId }));
1457
- }
1458
- if (lines.length === 0)
1459
- return 0;
1460
- for (const level of dirLevels)
1461
- ensureSecureDir(level);
1462
- appendLinesAtomically(`${destStem}${PROVIDER_STATE_FILE_SUFFIX}`, lines);
1463
- return lines.length;
1464
- }
1465
- async readSessionSummary(key) {
1466
- assertSafeSingleSegment(key.projectKey, "projectKey");
1467
- assertSafeSingleSegment(key.sessionId, "sessionId");
1468
- return readJsonIfExists(`${sessionStem(this.winterHome, key.projectKey, key.sessionId)}.summary.json`);
1469
- }
1470
- async mergeSessionMetadata(key, patch) {
1471
- const stem = sessionStem(this.winterHome, key.projectKey, key.sessionId);
1472
- const lockPath = `${stem}.lock`;
1473
- acquireLease(lockPath);
1474
- chmodSync(lockPath, 384);
1475
- const summaryPath = `${stem}.summary.json`;
1476
- const previous = readJsonIfExists(summaryPath) ?? {};
1477
- const updated = {
1478
- ...previous,
1479
- ...patch,
1480
- sessionId: key.sessionId,
1481
- mtime: Date.now()
1482
- };
1483
- writeJsonAtomically(summaryPath, updated);
1484
- }
1485
- async acquireSessionLease(key) {
1486
- const { dirLevels } = locateResource(this.winterHome, key);
1487
- for (const level of dirLevels)
1488
- ensureSecureDir(level);
1489
- const lockPath = `${sessionStem(this.winterHome, key.projectKey, key.sessionId)}.lock`;
1490
- acquireLease(lockPath);
1491
- chmodSync(lockPath, 384);
1492
- }
1493
- }
1494
1025
  // src/store/fork-session.ts
1495
- import { randomUUID as randomUUID3 } from "node:crypto";
1026
+ import { randomUUID as randomUUID2 } from "node:crypto";
1496
1027
  var IDENTITY_FIELDS = ["providerId", "modelKey", "adapterId", "adapterVersion", "catalogVersion", "authRef", "classifierPin"];
1497
1028
  async function forkSessionByKey(store, src) {
1498
1029
  const entries = await store.load(src);
1499
1030
  if (entries === null) {
1500
1031
  throw new SessionNotFoundError("not_found", `forkSession: source session not found: ${JSON.stringify(src)}`);
1501
1032
  }
1502
- const newSessionId = randomUUID3();
1033
+ const newSessionId = randomUUID2();
1503
1034
  const rewritten = entries.map((e) => typeof e.sessionId === "string" ? { ...e, sessionId: newSessionId } : e);
1504
1035
  const destKey = { projectKey: src.projectKey, sessionId: newSessionId, ...src.subpath !== undefined ? { subpath: src.subpath } : {} };
1505
1036
  await store.append(destKey, rewritten);
@@ -1508,7 +1039,7 @@ async function forkSessionByKey(store, src) {
1508
1039
  await carry.copyProviderStateForFork?.(src, destKey);
1509
1040
  const summary = destKey.subpath === undefined && carry.readSessionSummary !== undefined ? await carry.readSessionSummary({ projectKey: src.projectKey, sessionId: src.sessionId }) : null;
1510
1041
  if (summary !== null && typeof summary.providerId === "string" && typeof summary.modelKey === "string") {
1511
- const identity = { type: DIALECT_RECORD_ENTRY_TYPE };
1042
+ const identity = { type: DIALECT_RECORD_ENTRY_TYPE2 };
1512
1043
  for (const field of IDENTITY_FIELDS) {
1513
1044
  const value = summary[field];
1514
1045
  if (typeof value === "string")
@@ -1524,14 +1055,14 @@ function resolveHome(winterHome, brand) {
1524
1055
  if (winterHome !== undefined)
1525
1056
  return winterHome;
1526
1057
  if (brand === undefined)
1527
- return resolveWinterHome();
1528
- const resolved = resolveBrand(brand);
1058
+ return resolveWinterHome2();
1059
+ const resolved = resolveBrand2(brand);
1529
1060
  if (!resolved.ok)
1530
1061
  throw new TypeError(`sessions: invalid brand profile -- ${resolved.reason}`);
1531
- return resolveWinterHome(undefined, resolved.brand);
1062
+ return resolveWinterHome2(undefined, resolved.brand);
1532
1063
  }
1533
1064
  function openStore(opts) {
1534
- return new WinterCompatibilitySessionStore({ winterHome: resolveHome(opts?.winterHome, opts?.brand) });
1065
+ return new WinterCompatibilitySessionStore2({ winterHome: resolveHome(opts?.winterHome, opts?.brand) });
1535
1066
  }
1536
1067
  async function findInProject(store, projectKey, sessionId) {
1537
1068
  const sessions = await store.listSessions(projectKey);
@@ -1646,16 +1177,16 @@ async function getSubagentMessages(sessionId, agentId, opts) {
1646
1177
  }
1647
1178
  // src/settings/sources.ts
1648
1179
  import { readFile } from "node:fs/promises";
1649
- import { join as join4 } from "node:path";
1180
+ import { join as join2 } from "node:path";
1650
1181
  function settingsPathFor(source, opts) {
1651
- const brand = opts.brand ?? WINTER_BRAND;
1182
+ const brand = opts.brand ?? WINTER_BRAND2;
1652
1183
  switch (source) {
1653
1184
  case "user":
1654
- return join4(opts.winterHome ?? resolveWinterHome(opts.env, brand), "settings.json");
1185
+ return join2(opts.winterHome ?? resolveWinterHome2(opts.env, brand), "settings.json");
1655
1186
  case "project":
1656
- return join4(opts.cwd, brand.projectDirName, "settings.json");
1187
+ return join2(opts.cwd, brand.projectDirName, "settings.json");
1657
1188
  case "local":
1658
- return join4(opts.cwd, brand.projectDirName, "settings.local.json");
1189
+ return join2(opts.cwd, brand.projectDirName, "settings.local.json");
1659
1190
  }
1660
1191
  }
1661
1192
  function isPlainObject(v) {
@@ -2123,7 +1654,7 @@ var HOOK_EVENTS = [
2123
1654
  ];
2124
1655
  export {
2125
1656
  AbortError,
2126
- BRAND_TOKEN_RE,
1657
+ BRAND_TOKEN_RE2 as BRAND_TOKEN_RE,
2127
1658
  CLIConnectionError,
2128
1659
  DEFAULT_COMPACTION_THRESHOLD,
2129
1660
  DEFAULT_CONTEXT_WINDOW_TOKENS,
@@ -2131,61 +1662,81 @@ export {
2131
1662
  DEFAULT_OUTPUT_STYLE,
2132
1663
  DEFAULT_PLANS_DIRECTORY,
2133
1664
  DEFAULT_PROVIDER_STALL_TIMEOUT_MS,
2134
- DIALECT_RECORD_ENTRY_TYPE,
1665
+ DIALECT_RECORD_ENTRY_TYPE2 as DIALECT_RECORD_ENTRY_TYPE,
2135
1666
  ESCALATING_PERMISSION_MODES,
2136
- FIRST_PARTY_ORIGINATORS,
1667
+ FIRST_PARTY_ORIGINATORS2 as FIRST_PARTY_ORIGINATORS,
2137
1668
  HOOK_EVENTS,
2138
1669
  InvalidBrandError,
1670
+ MESSAGING_CONTROL_SUBTYPES,
1671
+ MESSAGING_CONTROL_SUBTYPE_LIST,
1672
+ MESSAGING_HOST_REQUEST_SUBTYPES,
1673
+ MESSAGING_RUNTIME_REQUEST_SUBTYPES,
2139
1674
  OVERLAY_NEVER_KEYS,
2140
1675
  PROJECT_PERMISSIVE_KEYS,
2141
1676
  PROTOCOL_VERSION,
2142
- PROVIDER_STATE_FILE_SUFFIX,
1677
+ PROVIDER_STATE_FILE_SUFFIX2 as PROVIDER_STATE_FILE_SUFFIX,
2143
1678
  ProcessError,
2144
1679
  ProtocolDecodeError,
2145
1680
  ProtocolError,
2146
1681
  ResultError,
1682
+ SDK_VERSION,
2147
1683
  SETTING_SOURCES,
2148
1684
  SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
2149
1685
  SessionNotFoundError,
2150
- WINTER_BRAND,
2151
- WinterCompatibilitySessionStore,
1686
+ TRANSCRIPT_PROJECT_KEY_MAX_LENGTH,
1687
+ WINTER_BRAND2 as WINTER_BRAND,
1688
+ WinterCompatibilitySessionStore2 as WinterCompatibilitySessionStore,
2152
1689
  WinterRpcError,
2153
1690
  WinterRpcTimeoutError,
2154
1691
  WinterSDKError,
2155
- WinterStoreError,
2156
- WinterStoreLeaseError,
1692
+ WinterStoreError2 as WinterStoreError,
1693
+ WinterStoreLeaseError2 as WinterStoreLeaseError,
2157
1694
  applyWorkspaceTrust,
2158
1695
  compatibilityKeys,
2159
1696
  decodeFrame,
2160
1697
  defaultSpawn,
2161
1698
  deleteSession,
2162
1699
  encodeFrame,
2163
- envName,
1700
+ envName2 as envName,
2164
1701
  filterEscalatingDefaultMode,
2165
1702
  forkSession,
2166
1703
  forkSessionByKey,
2167
1704
  getSessionInfo,
2168
1705
  getSessionMessages,
2169
1706
  getSubagentMessages,
2170
- isUnset,
1707
+ isDeliveryOutcome,
1708
+ isGlobalAgentMessage,
1709
+ isListedRuntimeObjectArray,
1710
+ isMessagingChildRequest,
1711
+ isMessagingDeliverRequest,
1712
+ isMessagingIdleNoticePayload,
1713
+ isMessagingNotificationsPage,
1714
+ isMessagingReadNotificationsRequest,
1715
+ isMessagingSubscribeIdleRequest,
1716
+ isNotificationRecord,
1717
+ isPermissionClassLabel,
1718
+ isRuntimeAddress,
1719
+ isUnset2 as isUnset,
1720
+ isVendorCompliantProjectKey,
2171
1721
  isWinterMcpServerInstance,
2172
1722
  listSessions,
2173
1723
  listSubagents,
2174
1724
  loadSettingsFile,
2175
- mcpToolName,
1725
+ mcpToolName2 as mcpToolName,
2176
1726
  providerSettingsFrom,
2177
1727
  query,
2178
1728
  renameSession,
2179
- resolveBrand,
2180
- resolveKeychainServiceForProfile,
1729
+ resolveBrand2 as resolveBrand,
1730
+ resolveFacetTarget,
1731
+ resolveKeychainServiceForProfile2 as resolveKeychainServiceForProfile,
2181
1732
  resolveRuntimeExecutable,
2182
1733
  resolveSettings,
2183
1734
  resolveSettingsDetailed,
2184
- resolveWinterHome,
1735
+ resolveWinterHome2 as resolveWinterHome,
2185
1736
  settingsPathFor,
2186
1737
  splitFrames,
2187
1738
  tagSession,
2188
1739
  transcriptProjectKey,
2189
- userAgent,
1740
+ userAgent2 as userAgent,
2190
1741
  validateModelSlots
2191
1742
  };