@swifty.js/swifty 0.0.22 → 0.0.23

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.
Files changed (35) hide show
  1. package/dist/{agent-5T7KNC7V.js → agent-RABW3Z3R.js} +1 -1
  2. package/dist/anthropic-V22T6E6E.js +4 -0
  3. package/dist/{checker-OJFS2MZY.js → checker-3RWAYF2U.js} +1 -1
  4. package/dist/{chunk-HJIGA37J.js → chunk-5KXBVL2A.js} +1 -1
  5. package/dist/{chunk-NLNH3IRT.js → chunk-CV7OKXYC.js} +1 -1
  6. package/dist/chunk-MJR2C7S7.js +130 -0
  7. package/dist/{chunk-GUXBLUNR.js → chunk-NR62AA5K.js} +1 -1
  8. package/dist/{chunk-NEAR6YPZ.js → chunk-OCQ6TYLT.js} +21 -20
  9. package/dist/chunk-QN27QEFS.js +4 -0
  10. package/dist/{chunk-LX2LK3TF.js → chunk-SIWLMWHH.js} +12 -11
  11. package/dist/chunk-Y43POSIW.js +389 -0
  12. package/dist/lib/agent-GHXYOARN.js +9 -0
  13. package/dist/lib/{anthropic-GFWP3ORB.js → anthropic-7YEN2QTU.js} +6 -6
  14. package/dist/lib/{checker-IIXJXQCB.js → checker-6BW4222R.js} +3 -3
  15. package/dist/lib/{chunk-LUEP4JMF.js → chunk-7IZEK7X5.js} +8 -12
  16. package/dist/lib/{chunk-C7IHCJZ3.js → chunk-BN4Q54G2.js} +259 -12
  17. package/dist/lib/{chunk-RR2CZ6CY.js → chunk-BO76JDFZ.js} +94 -75
  18. package/dist/lib/{chunk-6GOWRPYS.js → chunk-CYDNMEBC.js} +2 -2
  19. package/dist/lib/{chunk-EJLGB2EJ.js → chunk-EY7HE52Q.js} +14 -7
  20. package/dist/lib/{chunk-7URDLWQN.js → chunk-GNI7YX6F.js} +2 -2
  21. package/dist/lib/{chunk-UHVO63Y7.js → chunk-MF3YLQDS.js} +69 -38
  22. package/dist/lib/{chunk-UMFNTXKA.js → chunk-OO2CLOEE.js} +38 -38
  23. package/dist/lib/{chunk-GNBXECZN.js → chunk-PZ42NAFA.js} +2 -3
  24. package/dist/lib/index.d.ts +234 -237
  25. package/dist/lib/index.js +212 -224
  26. package/dist/lib/{openai-HXRMPNB7.js → openai-RDHZFJUT.js} +4 -4
  27. package/dist/main.js +203 -465
  28. package/dist/{openai-TVUUHRG7.js → openai-6NWVJ5LI.js} +15 -15
  29. package/dist/{server-ZTLHJWEQ.js → server-KQTLAXC6.js} +16 -16
  30. package/package.json +5 -5
  31. package/dist/anthropic-P2R4GW6F.js +0 -4
  32. package/dist/chunk-L73IHJF4.js +0 -386
  33. package/dist/chunk-YQQVB6VB.js +0 -127
  34. package/dist/chunk-ZZQE743W.js +0 -4
  35. package/dist/lib/agent-2AGRYN3R.js +0 -9
@@ -0,0 +1,9 @@
1
+ import {
2
+ Agent
3
+ } from "./chunk-MF3YLQDS.js";
4
+ import "./chunk-BN4Q54G2.js";
5
+ import "./chunk-OO2CLOEE.js";
6
+ import "./chunk-EY7HE52Q.js";
7
+ export {
8
+ Agent
9
+ };
@@ -5,12 +5,12 @@ import {
5
5
  markLastUserTailForCache,
6
6
  markToolsForCache,
7
7
  needsToolSearchBeta
8
- } from "./chunk-LUEP4JMF.js";
9
- import "./chunk-C7IHCJZ3.js";
10
- import "./chunk-6GOWRPYS.js";
11
- import "./chunk-UMFNTXKA.js";
12
- import "./chunk-GNBXECZN.js";
13
- import "./chunk-EJLGB2EJ.js";
8
+ } from "./chunk-7IZEK7X5.js";
9
+ import "./chunk-BN4Q54G2.js";
10
+ import "./chunk-CYDNMEBC.js";
11
+ import "./chunk-OO2CLOEE.js";
12
+ import "./chunk-PZ42NAFA.js";
13
+ import "./chunk-EY7HE52Q.js";
14
14
  import "./chunk-GHF2PSEW.js";
15
15
  export {
16
16
  AnthropicClient,
@@ -5,9 +5,9 @@ import {
5
5
  evaluateRules,
6
6
  extractContent,
7
7
  isSafeCommand
8
- } from "./chunk-7URDLWQN.js";
9
- import "./chunk-GNBXECZN.js";
10
- import "./chunk-EJLGB2EJ.js";
8
+ } from "./chunk-GNI7YX6F.js";
9
+ import "./chunk-PZ42NAFA.js";
10
+ import "./chunk-EY7HE52Q.js";
11
11
  import "./chunk-GHF2PSEW.js";
12
12
  export {
13
13
  PathSandbox,
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  computeCompactThreshold
3
- } from "./chunk-C7IHCJZ3.js";
3
+ } from "./chunk-BN4Q54G2.js";
4
4
  import {
5
5
  getContextWindow,
6
6
  getMaxOutputTokens,
7
7
  resolveAPIKey
8
- } from "./chunk-6GOWRPYS.js";
8
+ } from "./chunk-CYDNMEBC.js";
9
9
  import {
10
10
  AuthenticationError,
11
11
  ContextTooLongError,
@@ -13,20 +13,19 @@ import {
13
13
  NetworkError,
14
14
  RateLimitError,
15
15
  ensureToolPairing
16
- } from "./chunk-UMFNTXKA.js";
16
+ } from "./chunk-OO2CLOEE.js";
17
17
  import {
18
18
  MCP_TOOL_PREFIX,
19
19
  isMcpToolLike
20
- } from "./chunk-GNBXECZN.js";
20
+ } from "./chunk-PZ42NAFA.js";
21
21
  import {
22
- DANGEROUSLY_JSON,
23
22
  asErrorString,
24
23
  asRecord,
25
24
  asString,
26
25
  contentToText,
27
26
  createChildLogger,
28
27
  isRecord
29
- } from "./chunk-EJLGB2EJ.js";
28
+ } from "./chunk-EY7HE52Q.js";
30
29
 
31
30
  // src/llm/anthropic.ts
32
31
  import Anthropic from "@anthropic-ai/sdk";
@@ -206,8 +205,7 @@ function buildAnthropicMessages(messages) {
206
205
  // tool result
207
206
  tool_use_id: tr.toolUseId,
208
207
  is_error: tr.isError,
209
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
210
- content: tr.content
208
+ content: tr.contentBlocks?.length ? tr.contentBlocks : tr.content
211
209
  });
212
210
  }
213
211
  result.push({ role: "user", content: blocks });
@@ -409,12 +407,10 @@ var AnthropicClient = class {
409
407
  if (jsonAccumulate) {
410
408
  try {
411
409
  const parsed = JSON.parse(jsonAccumulate);
412
- args = isRecord(parsed) ? asRecord(parsed) : { [DANGEROUSLY_JSON]: jsonAccumulate };
410
+ args = isRecord(parsed) ? asRecord(parsed) : {};
413
411
  } catch (err) {
414
412
  log.error({ err }, "llm operation failed");
415
- args = {
416
- [DANGEROUSLY_JSON]: jsonAccumulate
417
- };
413
+ args = {};
418
414
  }
419
415
  }
420
416
  yield {
@@ -1,9 +1,12 @@
1
+ import {
2
+ ContextTooLongError
3
+ } from "./chunk-OO2CLOEE.js";
1
4
  import {
2
5
  asErrorString,
3
6
  contentToText,
4
7
  createChildLogger,
5
8
  strArg
6
- } from "./chunk-EJLGB2EJ.js";
9
+ } from "./chunk-EY7HE52Q.js";
7
10
 
8
11
  // src/conversation/conversation.ts
9
12
  var ConversationManager = class {
@@ -38,11 +41,18 @@ var ConversationManager = class {
38
41
  toolUses: toolUses.length > 0 ? toolUses : void 0
39
42
  });
40
43
  }
41
- addToolResultMessage(toolUseId, content, isError) {
44
+ addToolResultMessage(toolUseId, content, isError, contentBlocks) {
42
45
  this.history.push({
43
46
  role: "user",
44
47
  content: "",
45
- toolResults: [{ toolUseId, content, isError }]
48
+ toolResults: [
49
+ {
50
+ toolUseId,
51
+ content,
52
+ ...contentBlocks?.length ? { contentBlocks } : {},
53
+ isError
54
+ }
55
+ ]
46
56
  });
47
57
  }
48
58
  addToolResultsMessage(results) {
@@ -108,6 +118,9 @@ ${body}
108
118
  this.history.unshift({ role: "user", content: wrapped });
109
119
  this.longTermMemoryInjected = true;
110
120
  }
121
+ appendMessages(msgs) {
122
+ this.history.push(...msgs);
123
+ }
111
124
  len() {
112
125
  return this.history.length;
113
126
  }
@@ -168,6 +181,137 @@ ${body}
168
181
  }
169
182
  };
170
183
 
184
+ // src/tools/types.ts
185
+ function isRecord(value) {
186
+ return typeof value === "object" && value !== null && !Array.isArray(value);
187
+ }
188
+ var IMAGE_MEDIA_TYPES = /* @__PURE__ */ new Set([
189
+ "image/jpeg",
190
+ "image/png",
191
+ "image/gif",
192
+ "image/webp"
193
+ ]);
194
+ function isImageMediaType(value) {
195
+ return IMAGE_MEDIA_TYPES.has(value);
196
+ }
197
+ function normalizeTextBlock(value) {
198
+ return isRecord(value) && value.type === "text" && typeof value.text === "string" ? { type: "text", text: value.text } : null;
199
+ }
200
+ function normalizeImageBlock(value) {
201
+ if (!isRecord(value) || value.type !== "image" || !isRecord(value.source)) {
202
+ return null;
203
+ }
204
+ if (value.source.type === "url" && typeof value.source.url === "string") {
205
+ return { type: "image", source: { type: "url", url: value.source.url } };
206
+ }
207
+ if (value.source.type === "base64" && typeof value.source.media_type === "string" && isImageMediaType(value.source.media_type) && typeof value.source.data === "string") {
208
+ return {
209
+ type: "image",
210
+ source: {
211
+ type: "base64",
212
+ media_type: value.source.media_type,
213
+ data: value.source.data
214
+ }
215
+ };
216
+ }
217
+ return null;
218
+ }
219
+ function normalizeDocumentBlock(value) {
220
+ if (value.type !== "document" || !isRecord(value.source)) {
221
+ return null;
222
+ }
223
+ let source = null;
224
+ if (value.source.type === "url" && typeof value.source.url === "string") {
225
+ source = { type: "url", url: value.source.url };
226
+ } else if (value.source.type === "base64" && value.source.media_type === "application/pdf" && typeof value.source.data === "string") {
227
+ source = { type: "base64", media_type: "application/pdf", data: value.source.data };
228
+ } else if (value.source.type === "text" && value.source.media_type === "text/plain" && typeof value.source.data === "string") {
229
+ source = { type: "text", media_type: "text/plain", data: value.source.data };
230
+ } else if (value.source.type === "content") {
231
+ if (typeof value.source.content === "string") {
232
+ source = { type: "content", content: value.source.content };
233
+ } else if (Array.isArray(value.source.content)) {
234
+ const content = [];
235
+ for (const raw of value.source.content) {
236
+ const block = normalizeTextBlock(raw) ?? normalizeImageBlock(raw);
237
+ if (!block) {
238
+ return null;
239
+ }
240
+ content.push(block);
241
+ }
242
+ source = { type: "content", content };
243
+ }
244
+ }
245
+ if (!source) {
246
+ return null;
247
+ }
248
+ return {
249
+ type: "document",
250
+ source,
251
+ ...typeof value.title === "string" || value.title === null ? { title: value.title } : {},
252
+ ...typeof value.context === "string" || value.context === null ? { context: value.context } : {}
253
+ };
254
+ }
255
+ function normalizeToolResultContentBlock(value) {
256
+ const text = normalizeTextBlock(value);
257
+ if (text) {
258
+ return text;
259
+ }
260
+ const image = normalizeImageBlock(value);
261
+ if (image) {
262
+ return image;
263
+ }
264
+ if (!isRecord(value)) {
265
+ return null;
266
+ }
267
+ if (value.type === "tool_reference" && typeof value.tool_name === "string") {
268
+ return { type: "tool_reference", tool_name: value.tool_name };
269
+ }
270
+ if (value.type === "search_result" && typeof value.source === "string" && typeof value.title === "string" && Array.isArray(value.content)) {
271
+ const content = [];
272
+ for (const raw of value.content) {
273
+ const block = normalizeTextBlock(raw);
274
+ if (!block) {
275
+ return null;
276
+ }
277
+ content.push(block);
278
+ }
279
+ return { type: "search_result", source: value.source, title: value.title, content };
280
+ }
281
+ return normalizeDocumentBlock(value);
282
+ }
283
+ function isToolResultContentBlock(value) {
284
+ return normalizeToolResultContentBlock(value) !== null;
285
+ }
286
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
287
+ ".claude",
288
+ // Claude Code
289
+ ".git",
290
+ // Git
291
+ ".swifty",
292
+ // Swifty
293
+ ".next",
294
+ // Next.js
295
+ ".venv",
296
+ // Python venv
297
+ ".mypy_cache",
298
+ // Python mypy
299
+ ".tox",
300
+ // Python tox
301
+ "__pycache__",
302
+ // Python
303
+ "build",
304
+ // C++
305
+ "dist",
306
+ // Webpack, Vite
307
+ "node_modules",
308
+ // Node.js
309
+ "vendor",
310
+ // Go
311
+ "venv"
312
+ // Python venv
313
+ ]);
314
+
171
315
  // src/session/session.ts
172
316
  import { randomBytes } from "crypto";
173
317
  import {
@@ -193,6 +337,7 @@ var ContentSchema = z.union([z.string(), z.array(z.record(z.string(), z.unknown(
193
337
  var ToolResultRecordSchema = z.object({
194
338
  tool_use_id: z.string(),
195
339
  content: ContentSchema,
340
+ content_blocks: z.array(z.unknown()).optional(),
196
341
  is_error: z.boolean().optional()
197
342
  });
198
343
  var SessionMessageSchema = z.object({
@@ -220,6 +365,7 @@ function toolResultsToRecords(toolResults) {
220
365
  return (toolResults ?? []).map((tr) => ({
221
366
  tool_use_id: tr.toolUseId,
222
367
  content: tr.content,
368
+ ...tr.contentBlocks?.length ? { content_blocks: tr.contentBlocks } : {},
223
369
  ...tr.isError ? { is_error: true } : {}
224
370
  }));
225
371
  }
@@ -293,12 +439,30 @@ function recordsToCamelUses(recs) {
293
439
  arguments: tu.arguments
294
440
  }));
295
441
  }
442
+ function validContentBlocks(value) {
443
+ if (!value) {
444
+ return void 0;
445
+ }
446
+ const blocks = [];
447
+ for (const raw of value) {
448
+ const block = normalizeToolResultContentBlock(raw);
449
+ if (block) {
450
+ blocks.push(block);
451
+ }
452
+ }
453
+ return blocks.length > 0 ? blocks : void 0;
454
+ }
296
455
  function recordsToCamelResults(recs) {
297
- return recs?.map((tr) => ({
298
- toolUseId: tr.tool_use_id,
299
- content: tr.content,
300
- isError: tr.is_error
301
- }));
456
+ return recs?.map((tr) => {
457
+ const legacyBlocks = Array.isArray(tr.content) ? validContentBlocks(tr.content) : void 0;
458
+ const contentBlocks = validContentBlocks(tr.content_blocks) ?? legacyBlocks;
459
+ return {
460
+ toolUseId: tr.tool_use_id,
461
+ content: typeof tr.content === "string" ? tr.content : contentToText(tr.content),
462
+ ...contentBlocks ? { contentBlocks } : {},
463
+ isError: tr.is_error ?? false
464
+ };
465
+ });
302
466
  }
303
467
  function rebuildFromSession(saved) {
304
468
  let lastBoundary = -1;
@@ -495,6 +659,35 @@ function contentChars(content) {
495
659
  }
496
660
  return chars;
497
661
  }
662
+ function toolResultBlocksChars(blocks) {
663
+ let textChars = 0;
664
+ let richChars = 0;
665
+ for (const block of blocks) {
666
+ if (block.type === "text") {
667
+ textChars += block.text.length;
668
+ } else if (block.type === "image") {
669
+ richChars += IMAGE_CHAR_EQUIV;
670
+ } else if (block.type === "tool_reference") {
671
+ richChars += block.tool_name.length;
672
+ } else if (block.type === "search_result") {
673
+ richChars += block.source.length + block.title.length;
674
+ richChars += block.content.reduce((sum, content) => sum + content.text.length, 0);
675
+ } else if (block.source.type === "base64") {
676
+ richChars += IMAGE_CHAR_EQUIV;
677
+ } else if (block.source.type === "url") {
678
+ richChars += block.source.url.length;
679
+ } else if (block.source.type === "text") {
680
+ richChars += block.source.data.length;
681
+ } else if (typeof block.source.content === "string") {
682
+ richChars += block.source.content.length;
683
+ } else {
684
+ for (const content of block.source.content) {
685
+ richChars += content.type === "text" ? content.text.length : IMAGE_CHAR_EQUIV;
686
+ }
687
+ }
688
+ }
689
+ return { textChars, richChars };
690
+ }
498
691
  function estimateMessages(messages) {
499
692
  let totalChars = 0;
500
693
  for (const msg of messages) {
@@ -504,7 +697,12 @@ function estimateMessages(messages) {
504
697
  }
505
698
  if (msg.toolResults) {
506
699
  for (const tr of msg.toolResults) {
507
- totalChars += contentChars(tr.content);
700
+ if (tr.contentBlocks?.length) {
701
+ const blockChars = toolResultBlocksChars(tr.contentBlocks);
702
+ totalChars += Math.max(tr.content.length, blockChars.textChars) + blockChars.richChars;
703
+ } else {
704
+ totalChars += tr.content.length;
705
+ }
508
706
  }
509
707
  }
510
708
  if (msg.thinkingBlocks) {
@@ -743,10 +941,49 @@ function serializePrefixText(messages) {
743
941
  if (m.toolUses) {
744
942
  text += `
745
943
  [tools: ${m.toolUses.map((t) => t.toolName).join(", ")}]`;
944
+ }
945
+ if (m.toolResults) {
946
+ text += `
947
+ [tool results]
948
+ ${m.toolResults.map((result) => result.content).join("\n")}`;
746
949
  }
747
950
  return text;
748
951
  }).join("\n\n");
749
952
  }
953
+ function formatCompactSummary(raw) {
954
+ const summaryMatch = /<summary>([\s\S]*?)<\/summary>/.exec(raw);
955
+ if (summaryMatch) {
956
+ return summaryMatch[1].trim();
957
+ }
958
+ const analysisMatch = /<analysis>[\s\S]*?<\/analysis>/.exec(raw);
959
+ if (analysisMatch) {
960
+ return raw.replace(analysisMatch[0], "").trim();
961
+ }
962
+ return raw.trim();
963
+ }
964
+ async function callSummaryWithCacheSharing(client, messages, toolSchemas) {
965
+ let lastAssistant = -1;
966
+ for (let i = messages.length - 1; i >= 0; i--) {
967
+ if (messages[i].role === "assistant") {
968
+ lastAssistant = i;
969
+ break;
970
+ }
971
+ }
972
+ if (lastAssistant < 0) {
973
+ throw new Error("no assistant message found for cache-sharing compact");
974
+ }
975
+ const summaryConv = new ConversationManager();
976
+ summaryConv.appendMessages(messages.slice(0, lastAssistant + 1));
977
+ summaryConv.addUserMessage(SUMMARY_SYSTEM_PROMPT);
978
+ let summaryText = "";
979
+ const stream = client.stream(summaryConv, toolSchemas);
980
+ for await (const event of stream) {
981
+ if (event.type === "text_delta") {
982
+ summaryText += event.text;
983
+ }
984
+ }
985
+ return formatCompactSummary(summaryText);
986
+ }
750
987
  async function requestSummaryWithPTLRetry(client, prefix, toolSchemas) {
751
988
  let currentPrefix = prefix;
752
989
  for (let attempt = 0; ; attempt++) {
@@ -761,8 +998,7 @@ async function requestSummaryWithPTLRetry(client, prefix, toolSchemas) {
761
998
  summaryText += event.text;
762
999
  }
763
1000
  }
764
- const match = /<summary>([\s\S]*?)<\/summary>/.exec(summaryText);
765
- return match ? match[1].trim() : summaryText;
1001
+ return formatCompactSummary(summaryText);
766
1002
  } catch (e) {
767
1003
  const msg = e instanceof Error ? e.message.toLowerCase() : "";
768
1004
  const isPTL = msg.includes("prompt") && msg.includes("long") || msg.includes("too many") || msg.includes("context_length");
@@ -789,7 +1025,15 @@ async function doCompact(conv, client, recoveryState, toolSchemaNames, toolSchem
789
1025
  }
790
1026
  const toSummarize = estimationMessages.slice(0, keepStart);
791
1027
  const toKeep = estimationMessages.slice(keepStart);
792
- const summary = await requestSummaryWithPTLRetry(client, toSummarize, toolSchemas);
1028
+ let summary;
1029
+ try {
1030
+ summary = await callSummaryWithCacheSharing(client, estimationMessages, toolSchemas);
1031
+ } catch (err) {
1032
+ if (!(err instanceof ContextTooLongError)) {
1033
+ throw err;
1034
+ }
1035
+ summary = await requestSummaryWithPTLRetry(client, toSummarize, toolSchemas);
1036
+ }
793
1037
  const recoveryAttachment = recoveryState ? recoveryState.buildRecoveryAttachment(toolSchemaNames) : "";
794
1038
  let summaryContent = "This session continues from a previous conversation, which has been compressed due to context limitations. Here is a summary of the earlier messages:\n\n" + summary;
795
1039
  if (toKeep.length > 0) {
@@ -827,6 +1071,9 @@ ${recoveryAttachment}`;
827
1071
 
828
1072
  export {
829
1073
  ConversationManager,
1074
+ normalizeToolResultContentBlock,
1075
+ isToolResultContentBlock,
1076
+ SKIP_DIRS,
830
1077
  COMPACT_BOUNDARY,
831
1078
  toolUsesToRecords,
832
1079
  toolResultsToRecords,