@strands-agents/sdk 1.9.0 → 1.11.0

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 (169) hide show
  1. package/README.md +1 -1
  2. package/dist/src/agent/agent.d.ts +22 -42
  3. package/dist/src/agent/agent.d.ts.map +1 -1
  4. package/dist/src/agent/agent.js +73 -426
  5. package/dist/src/agent/agent.js.map +1 -1
  6. package/dist/src/context-manager/modes/agentic/agentic-context.d.ts +2 -2
  7. package/dist/src/errors.d.ts +15 -0
  8. package/dist/src/errors.d.ts.map +1 -1
  9. package/dist/src/errors.js +18 -0
  10. package/dist/src/errors.js.map +1 -1
  11. package/dist/src/hooks/events.d.ts +5 -4
  12. package/dist/src/hooks/events.d.ts.map +1 -1
  13. package/dist/src/hooks/events.js +3 -3
  14. package/dist/src/hooks/events.js.map +1 -1
  15. package/dist/src/index.d.ts +4 -1
  16. package/dist/src/index.d.ts.map +1 -1
  17. package/dist/src/index.js +4 -1
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/index.node.d.ts.map +1 -1
  20. package/dist/src/index.node.js +2 -6
  21. package/dist/src/index.node.js.map +1 -1
  22. package/dist/src/middleware/interrupt.d.ts +18 -0
  23. package/dist/src/middleware/interrupt.d.ts.map +1 -0
  24. package/dist/src/middleware/interrupt.js +33 -0
  25. package/dist/src/middleware/interrupt.js.map +1 -0
  26. package/dist/src/models/bedrock.d.ts.map +1 -1
  27. package/dist/src/models/bedrock.js +23 -1
  28. package/dist/src/models/bedrock.js.map +1 -1
  29. package/dist/src/models/openai/errors.d.ts.map +1 -1
  30. package/dist/src/models/openai/errors.js +1 -0
  31. package/dist/src/models/openai/errors.js.map +1 -1
  32. package/dist/src/models/openai/mantle.d.ts +8 -3
  33. package/dist/src/models/openai/mantle.d.ts.map +1 -1
  34. package/dist/src/models/openai/mantle.js +41 -6
  35. package/dist/src/models/openai/mantle.js.map +1 -1
  36. package/dist/src/models/openai/model.d.ts.map +1 -1
  37. package/dist/src/models/openai/model.js +4 -3
  38. package/dist/src/models/openai/model.js.map +1 -1
  39. package/dist/src/models/openai/responses-adapter.d.ts.map +1 -1
  40. package/dist/src/models/openai/responses-adapter.js +41 -9
  41. package/dist/src/models/openai/responses-adapter.js.map +1 -1
  42. package/dist/src/models/vercel.d.ts.map +1 -1
  43. package/dist/src/models/vercel.js +28 -1
  44. package/dist/src/models/vercel.js.map +1 -1
  45. package/dist/src/multiagent/graph.d.ts.map +1 -1
  46. package/dist/src/multiagent/graph.js +1 -1
  47. package/dist/src/multiagent/graph.js.map +1 -1
  48. package/dist/src/{multiagent/queue.d.ts → queue.d.ts} +12 -27
  49. package/dist/src/queue.d.ts.map +1 -0
  50. package/dist/src/{multiagent/queue.js → queue.js} +4 -2
  51. package/dist/src/queue.js.map +1 -0
  52. package/dist/src/register-node-defaults.d.ts +3 -0
  53. package/dist/src/register-node-defaults.d.ts.map +1 -0
  54. package/dist/src/register-node-defaults.js +10 -0
  55. package/dist/src/register-node-defaults.js.map +1 -0
  56. package/dist/src/sandbox/register-node-defaults.d.ts +3 -0
  57. package/dist/src/sandbox/register-node-defaults.d.ts.map +1 -0
  58. package/dist/src/sandbox/register-node-defaults.js +8 -0
  59. package/dist/src/sandbox/register-node-defaults.js.map +1 -0
  60. package/dist/src/session/file-storage.d.ts +3 -0
  61. package/dist/src/session/file-storage.d.ts.map +1 -1
  62. package/dist/src/session/file-storage.js +3 -0
  63. package/dist/src/session/file-storage.js.map +1 -1
  64. package/dist/src/session/s3-storage.d.ts +3 -0
  65. package/dist/src/session/s3-storage.d.ts.map +1 -1
  66. package/dist/src/session/s3-storage.js +3 -0
  67. package/dist/src/session/s3-storage.js.map +1 -1
  68. package/dist/src/session/session-manager.d.ts +11 -2
  69. package/dist/src/session/session-manager.d.ts.map +1 -1
  70. package/dist/src/session/session-manager.js +19 -8
  71. package/dist/src/session/session-manager.js.map +1 -1
  72. package/dist/src/session/snapshot-storage-adapter.d.ts +93 -0
  73. package/dist/src/session/snapshot-storage-adapter.d.ts.map +1 -0
  74. package/dist/src/session/snapshot-storage-adapter.js +157 -0
  75. package/dist/src/session/snapshot-storage-adapter.js.map +1 -0
  76. package/dist/src/session/storage.d.ts +3 -6
  77. package/dist/src/session/storage.d.ts.map +1 -1
  78. package/dist/src/storage/in-memory-storage.d.ts +64 -0
  79. package/dist/src/storage/in-memory-storage.d.ts.map +1 -0
  80. package/dist/src/storage/in-memory-storage.js +85 -0
  81. package/dist/src/storage/in-memory-storage.js.map +1 -0
  82. package/dist/src/storage/index.d.ts +20 -0
  83. package/dist/src/storage/index.d.ts.map +1 -0
  84. package/dist/src/storage/index.js +18 -0
  85. package/dist/src/storage/index.js.map +1 -0
  86. package/dist/src/storage/local-file-storage.d.ts +81 -0
  87. package/dist/src/storage/local-file-storage.d.ts.map +1 -0
  88. package/dist/src/storage/local-file-storage.js +244 -0
  89. package/dist/src/storage/local-file-storage.js.map +1 -0
  90. package/dist/src/storage/s3-storage.d.ts +73 -0
  91. package/dist/src/storage/s3-storage.d.ts.map +1 -0
  92. package/dist/src/storage/s3-storage.js +146 -0
  93. package/dist/src/storage/s3-storage.js.map +1 -0
  94. package/dist/src/storage/storage.d.ts +102 -0
  95. package/dist/src/storage/storage.d.ts.map +1 -0
  96. package/dist/src/storage/storage.js +68 -0
  97. package/dist/src/storage/storage.js.map +1 -0
  98. package/dist/src/telemetry/tracer.d.ts +18 -0
  99. package/dist/src/telemetry/tracer.d.ts.map +1 -1
  100. package/dist/src/telemetry/tracer.js +31 -11
  101. package/dist/src/telemetry/tracer.js.map +1 -1
  102. package/dist/src/tools/executors/concurrent.d.ts +32 -0
  103. package/dist/src/tools/executors/concurrent.d.ts.map +1 -0
  104. package/dist/src/tools/executors/concurrent.js +128 -0
  105. package/dist/src/tools/executors/concurrent.js.map +1 -0
  106. package/dist/src/tools/executors/executor.d.ts +61 -0
  107. package/dist/src/tools/executors/executor.d.ts.map +1 -0
  108. package/dist/src/tools/executors/executor.js +190 -0
  109. package/dist/src/tools/executors/executor.js.map +1 -0
  110. package/dist/src/tools/executors/sequential.d.ts +30 -0
  111. package/dist/src/tools/executors/sequential.d.ts.map +1 -0
  112. package/dist/src/tools/executors/sequential.js +67 -0
  113. package/dist/src/tools/executors/sequential.js.map +1 -0
  114. package/dist/src/tsconfig.tsbuildinfo +1 -1
  115. package/dist/src/types/agent.d.ts +5 -4
  116. package/dist/src/types/agent.d.ts.map +1 -1
  117. package/dist/src/types/agent.js.map +1 -1
  118. package/dist/src/vended-memory-stores/test-memory-store/store.d.ts +32 -24
  119. package/dist/src/vended-memory-stores/test-memory-store/store.d.ts.map +1 -1
  120. package/dist/src/vended-memory-stores/test-memory-store/store.js +84 -91
  121. package/dist/src/vended-memory-stores/test-memory-store/store.js.map +1 -1
  122. package/dist/src/vended-plugins/context-offloader/plugin.d.ts +37 -5
  123. package/dist/src/vended-plugins/context-offloader/plugin.d.ts.map +1 -1
  124. package/dist/src/vended-plugins/context-offloader/plugin.js +116 -17
  125. package/dist/src/vended-plugins/context-offloader/plugin.js.map +1 -1
  126. package/dist/src/vended-plugins/context-offloader/storage.d.ts +23 -9
  127. package/dist/src/vended-plugins/context-offloader/storage.d.ts.map +1 -1
  128. package/dist/src/vended-plugins/context-offloader/storage.js +21 -6
  129. package/dist/src/vended-plugins/context-offloader/storage.js.map +1 -1
  130. package/dist/src/vended-tools/index.d.ts +3 -1
  131. package/dist/src/vended-tools/index.d.ts.map +1 -1
  132. package/dist/src/vended-tools/index.js +3 -1
  133. package/dist/src/vended-tools/index.js.map +1 -1
  134. package/dist/src/vended-tools/notebook/notebook.d.ts +1 -1
  135. package/dist/src/vended-tools/sleep/index.d.ts +9 -0
  136. package/dist/src/vended-tools/sleep/index.d.ts.map +1 -0
  137. package/dist/src/vended-tools/sleep/index.js +7 -0
  138. package/dist/src/vended-tools/sleep/index.js.map +1 -0
  139. package/dist/src/vended-tools/sleep/make-sleep.d.ts +48 -0
  140. package/dist/src/vended-tools/sleep/make-sleep.d.ts.map +1 -0
  141. package/dist/src/vended-tools/sleep/make-sleep.js +81 -0
  142. package/dist/src/vended-tools/sleep/make-sleep.js.map +1 -0
  143. package/dist/src/vended-tools/sleep/sleep.d.ts +19 -0
  144. package/dist/src/vended-tools/sleep/sleep.d.ts.map +1 -0
  145. package/dist/src/vended-tools/sleep/sleep.js +20 -0
  146. package/dist/src/vended-tools/sleep/sleep.js.map +1 -0
  147. package/dist/src/vended-tools/sleep/types.d.ts +31 -0
  148. package/dist/src/vended-tools/sleep/types.d.ts.map +1 -0
  149. package/dist/src/vended-tools/sleep/types.js +22 -0
  150. package/dist/src/vended-tools/sleep/types.js.map +1 -0
  151. package/dist/src/vended-tools/stop/index.d.ts +8 -0
  152. package/dist/src/vended-tools/stop/index.d.ts.map +1 -0
  153. package/dist/src/vended-tools/stop/index.js +6 -0
  154. package/dist/src/vended-tools/stop/index.js.map +1 -0
  155. package/dist/src/vended-tools/stop/stop.d.ts +47 -0
  156. package/dist/src/vended-tools/stop/stop.d.ts.map +1 -0
  157. package/dist/src/vended-tools/stop/stop.js +85 -0
  158. package/dist/src/vended-tools/stop/stop.js.map +1 -0
  159. package/dist/src/vended-tools/stop/types.d.ts +54 -0
  160. package/dist/src/vended-tools/stop/types.d.ts.map +1 -0
  161. package/dist/src/vended-tools/stop/types.js +58 -0
  162. package/dist/src/vended-tools/stop/types.js.map +1 -0
  163. package/package.json +13 -2
  164. package/dist/src/conversation-manager/index.d.ts +0 -10
  165. package/dist/src/conversation-manager/index.d.ts.map +0 -1
  166. package/dist/src/conversation-manager/index.js +0 -10
  167. package/dist/src/conversation-manager/index.js.map +0 -1
  168. package/dist/src/multiagent/queue.d.ts.map +0 -1
  169. package/dist/src/multiagent/queue.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-storage.js","sourceRoot":"","sources":["../../../src/storage/in-memory-storage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEvE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,eAAe;IACT,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAA;IAEvD;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,IAAgB;QACvC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;IAClD,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;QAChD,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAA;QACpC,OAAO,KAAK,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;IACvC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;QAC1C,MAAM,IAAI,GAAa,EAAE,CAAA;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACrC,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChD,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;IACpB,CAAC;IAED,6EAA6E;IAC7E,SAAS,CAAC,MAAc;QACtB,OAAO,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAChC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IACrB,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Unified storage module.
3
+ *
4
+ * Provides the {@link Storage} interface and shipped implementations for persisting
5
+ * raw bytes under string keys. All SDK subsystems that need persistence — sessions,
6
+ * memory, context offloading, transcripts — consume this interface.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { LocalFileStorage, InMemoryStorage } from '@strands-agents/sdk/storage'
11
+ * ```
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ export type { Storage } from './storage.js';
16
+ export { InMemoryStorage } from './in-memory-storage.js';
17
+ export { LocalFileStorage } from './local-file-storage.js';
18
+ export { S3Storage } from './s3-storage.js';
19
+ export type { S3StorageConfig } from './s3-storage.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Unified storage module.
3
+ *
4
+ * Provides the {@link Storage} interface and shipped implementations for persisting
5
+ * raw bytes under string keys. All SDK subsystems that need persistence — sessions,
6
+ * memory, context offloading, transcripts — consume this interface.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { LocalFileStorage, InMemoryStorage } from '@strands-agents/sdk/storage'
11
+ * ```
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ export { InMemoryStorage } from './in-memory-storage.js';
16
+ export { LocalFileStorage } from './local-file-storage.js';
17
+ export { S3Storage } from './s3-storage.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,81 @@
1
+ import type { Sandbox } from '../sandbox/base.js';
2
+ import type { Storage } from './storage.js';
3
+ /**
4
+ * Local-filesystem {@link Storage} backend.
5
+ *
6
+ * Persists each key as a file under a base directory, mapping the key's `/` segments
7
+ * onto directory segments. On the host filesystem, writes are atomic (write to a
8
+ * scratch sibling, then rename) so a crash mid-write never leaves a partially written
9
+ * file. When bound to a {@link Sandbox} via {@link forSandbox}, all I/O is routed
10
+ * through that sandbox instead of the host's `node:fs` (atomicity depends on the
11
+ * sandbox implementation).
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { LocalFileStorage } from '@strands-agents/sdk/storage'
16
+ *
17
+ * const storage = new LocalFileStorage('./.strands/')
18
+ * await storage.write('sessions/abc/snapshot.json', bytes)
19
+ * ```
20
+ */
21
+ export declare class LocalFileStorage implements Storage {
22
+ private readonly _baseDir;
23
+ private readonly _sandbox;
24
+ /**
25
+ * @param baseDir - Root directory under which keys are stored. Defaults to `./.strands/`.
26
+ * @param sandbox - Optional sandbox to route I/O through. Usually set via {@link forSandbox}.
27
+ */
28
+ constructor(baseDir?: string, sandbox?: Sandbox);
29
+ /**
30
+ * Returns a storage instance whose I/O is routed through `sandbox`.
31
+ *
32
+ * Instances already bound to a sandbox return themselves unchanged.
33
+ *
34
+ * @param sandbox - Sandbox to route the returned instance's I/O through
35
+ * @returns A new `LocalFileStorage` with the same base directory, routed through `sandbox`
36
+ */
37
+ forSandbox(sandbox: Sandbox): LocalFileStorage;
38
+ /**
39
+ * Stores `data` under `key`, overwriting any existing value.
40
+ *
41
+ * @param key - Opaque, `/`-separated key identifying the value
42
+ * @param data - Raw bytes to persist
43
+ * @throws {@link StorageError} if the key is invalid or the write fails
44
+ */
45
+ write(key: string, data: Uint8Array): Promise<void>;
46
+ /**
47
+ * Retrieves the bytes previously stored under `key`.
48
+ *
49
+ * @param key - The key to read
50
+ * @returns The stored bytes, or `null` if no value exists for `key`
51
+ * @throws {@link StorageError} if the key is invalid or the read fails
52
+ */
53
+ read(key: string): Promise<Uint8Array | null>;
54
+ /**
55
+ * Deletes the value stored under `key`. A no-op if the key does not exist.
56
+ *
57
+ * @param key - The key to delete
58
+ * @throws {@link StorageError} if the key is invalid or the delete fails
59
+ */
60
+ delete(key: string): Promise<void>;
61
+ /**
62
+ * Lists the keys whose names begin with `prefix`, sorted lexicographically.
63
+ *
64
+ * @param prefix - Key prefix to match. An empty string matches all keys.
65
+ * @returns The matching keys, sorted ascending
66
+ * @throws {@link StorageError} if the prefix is invalid or the listing fails
67
+ */
68
+ list(prefix: string): Promise<string[]>;
69
+ private _pathFor;
70
+ private _listKeysHost;
71
+ private _listKeysSandbox;
72
+ /**
73
+ * Returns a prefixed view of this storage without mutating the original.
74
+ * The returned view preserves `forSandbox` for single-level namespacing;
75
+ * nested `.namespace()` calls on the view do not carry sandbox routing.
76
+ */
77
+ namespace(prefix: string): Storage & {
78
+ forSandbox(sandbox: Sandbox): Storage;
79
+ };
80
+ }
81
+ //# sourceMappingURL=local-file-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-file-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/local-file-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAgB3C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAiB,YAAW,OAAO;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAE9C;;;OAGG;gBACS,OAAO,GAAE,MAAsB,EAAE,OAAO,CAAC,EAAE,OAAO;IAK9D;;;;;;;OAOG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB;IAK9C;;;;;;OAMG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BzD;;;;;;OAMG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAqBnD;;;;;OAKG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxC;;;;;;OAMG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAa7C,OAAO,CAAC,QAAQ;YAKF,aAAa;YA2Bb,gBAAgB;IA2B9B;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG;QAAE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE;CAO/E"}
@@ -0,0 +1,244 @@
1
+ import { StorageError } from '../errors.js';
2
+ import { namespace, normalizeKey, normalizePrefix } from './storage.js';
3
+ /**
4
+ * Returns true if the error represents a missing or non-directory path (ENOENT or ENOTDIR).
5
+ *
6
+ * @param error - The caught error to inspect
7
+ * @returns Whether the error is a filesystem not-found error
8
+ */
9
+ function isNotFoundError(error) {
10
+ if (error === null || typeof error !== 'object' || !('code' in error))
11
+ return false;
12
+ return error.code === 'ENOENT' || error.code === 'ENOTDIR';
13
+ }
14
+ /**
15
+ * Local-filesystem {@link Storage} backend.
16
+ *
17
+ * Persists each key as a file under a base directory, mapping the key's `/` segments
18
+ * onto directory segments. On the host filesystem, writes are atomic (write to a
19
+ * scratch sibling, then rename) so a crash mid-write never leaves a partially written
20
+ * file. When bound to a {@link Sandbox} via {@link forSandbox}, all I/O is routed
21
+ * through that sandbox instead of the host's `node:fs` (atomicity depends on the
22
+ * sandbox implementation).
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { LocalFileStorage } from '@strands-agents/sdk/storage'
27
+ *
28
+ * const storage = new LocalFileStorage('./.strands/')
29
+ * await storage.write('sessions/abc/snapshot.json', bytes)
30
+ * ```
31
+ */
32
+ export class LocalFileStorage {
33
+ _baseDir;
34
+ _sandbox;
35
+ /**
36
+ * @param baseDir - Root directory under which keys are stored. Defaults to `./.strands/`.
37
+ * @param sandbox - Optional sandbox to route I/O through. Usually set via {@link forSandbox}.
38
+ */
39
+ constructor(baseDir = './.strands/', sandbox) {
40
+ this._baseDir = baseDir;
41
+ this._sandbox = sandbox;
42
+ }
43
+ /**
44
+ * Returns a storage instance whose I/O is routed through `sandbox`.
45
+ *
46
+ * Instances already bound to a sandbox return themselves unchanged.
47
+ *
48
+ * @param sandbox - Sandbox to route the returned instance's I/O through
49
+ * @returns A new `LocalFileStorage` with the same base directory, routed through `sandbox`
50
+ */
51
+ forSandbox(sandbox) {
52
+ if (this._sandbox)
53
+ return this;
54
+ return new LocalFileStorage(this._baseDir, sandbox);
55
+ }
56
+ /**
57
+ * Stores `data` under `key`, overwriting any existing value.
58
+ *
59
+ * @param key - Opaque, `/`-separated key identifying the value
60
+ * @param data - Raw bytes to persist
61
+ * @throws {@link StorageError} if the key is invalid or the write fails
62
+ */
63
+ async write(key, data) {
64
+ const normalized = normalizeKey(key);
65
+ const path = this._pathFor(normalized);
66
+ if (this._sandbox) {
67
+ try {
68
+ await this._sandbox.writeFile(path, data);
69
+ }
70
+ catch (error) {
71
+ throw new StorageError(`Failed to write '${normalized}' to sandbox storage`, { cause: error });
72
+ }
73
+ return;
74
+ }
75
+ let tmpPath;
76
+ try {
77
+ const { mkdir, writeFile, rename } = await import('node:fs/promises');
78
+ const { dirname } = await import('node:path');
79
+ await mkdir(dirname(path), { recursive: true });
80
+ const { randomUUID } = await import('node:crypto');
81
+ tmpPath = `${path}.__strands_tmp_${randomUUID()}`;
82
+ await writeFile(tmpPath, data);
83
+ await rename(tmpPath, path);
84
+ }
85
+ catch (error) {
86
+ if (tmpPath) {
87
+ const { rm } = await import('node:fs/promises');
88
+ await rm(tmpPath, { force: true }).catch(() => { });
89
+ }
90
+ throw new StorageError(`Failed to write '${normalized}' to local storage`, { cause: error });
91
+ }
92
+ }
93
+ /**
94
+ * Retrieves the bytes previously stored under `key`.
95
+ *
96
+ * @param key - The key to read
97
+ * @returns The stored bytes, or `null` if no value exists for `key`
98
+ * @throws {@link StorageError} if the key is invalid or the read fails
99
+ */
100
+ async read(key) {
101
+ const normalized = normalizeKey(key);
102
+ const path = this._pathFor(normalized);
103
+ if (this._sandbox) {
104
+ try {
105
+ return await this._sandbox.readFile(path);
106
+ }
107
+ catch (error) {
108
+ if (isNotFoundError(error))
109
+ return null;
110
+ throw new StorageError(`Failed to read '${normalized}' from sandbox storage`, { cause: error });
111
+ }
112
+ }
113
+ try {
114
+ const { readFile } = await import('node:fs/promises');
115
+ const content = await readFile(path);
116
+ return new Uint8Array(content);
117
+ }
118
+ catch (error) {
119
+ if (isNotFoundError(error))
120
+ return null;
121
+ throw new StorageError(`Failed to read '${normalized}' from local storage`, { cause: error });
122
+ }
123
+ }
124
+ /**
125
+ * Deletes the value stored under `key`. A no-op if the key does not exist.
126
+ *
127
+ * @param key - The key to delete
128
+ * @throws {@link StorageError} if the key is invalid or the delete fails
129
+ */
130
+ async delete(key) {
131
+ const normalized = normalizeKey(key);
132
+ const path = this._pathFor(normalized);
133
+ if (this._sandbox) {
134
+ try {
135
+ await this._sandbox.removeFile(path);
136
+ }
137
+ catch (error) {
138
+ if (!isNotFoundError(error)) {
139
+ throw new StorageError(`Failed to delete '${normalized}' from sandbox storage`, { cause: error });
140
+ }
141
+ }
142
+ return;
143
+ }
144
+ try {
145
+ const { rm } = await import('node:fs/promises');
146
+ await rm(path, { force: true });
147
+ }
148
+ catch (error) {
149
+ throw new StorageError(`Failed to delete '${normalized}' from local storage`, { cause: error });
150
+ }
151
+ }
152
+ /**
153
+ * Lists the keys whose names begin with `prefix`, sorted lexicographically.
154
+ *
155
+ * @param prefix - Key prefix to match. An empty string matches all keys.
156
+ * @returns The matching keys, sorted ascending
157
+ * @throws {@link StorageError} if the prefix is invalid or the listing fails
158
+ */
159
+ async list(prefix) {
160
+ const normalized = normalizePrefix(prefix);
161
+ const base = this._baseDir.replace(/\/$/, '');
162
+ // Narrow the walk to the deepest directory the prefix fully specifies
163
+ const lastSlash = normalized.lastIndexOf('/');
164
+ const dirPortion = lastSlash >= 0 ? normalized.slice(0, lastSlash) : '';
165
+ const startDir = dirPortion ? `${base}/${dirPortion}` : base;
166
+ const keys = this._sandbox
167
+ ? await this._listKeysSandbox(startDir, dirPortion)
168
+ : await this._listKeysHost(startDir, dirPortion);
169
+ return keys.filter((key) => key.startsWith(normalized)).sort();
170
+ }
171
+ _pathFor(key) {
172
+ const base = this._baseDir.replace(/\/$/, '');
173
+ return `${base}/${key}`;
174
+ }
175
+ async _listKeysHost(dir, keyPrefix) {
176
+ const { readdir } = await import('node:fs/promises');
177
+ const walk = async (walkDir, walkPrefix) => {
178
+ let entries;
179
+ try {
180
+ entries = await readdir(walkDir, { withFileTypes: true });
181
+ }
182
+ catch (error) {
183
+ if (isNotFoundError(error))
184
+ return [];
185
+ throw new StorageError(`Failed to list local storage under '${walkPrefix}'`, { cause: error });
186
+ }
187
+ const found = [];
188
+ for (const entry of entries) {
189
+ if (!entry.isDirectory() && entry.name.includes('.__strands_tmp'))
190
+ continue;
191
+ const childKey = walkPrefix ? `${walkPrefix}/${entry.name}` : entry.name;
192
+ if (entry.isDirectory()) {
193
+ found.push(...(await walk(`${walkDir}/${entry.name}`, childKey)));
194
+ }
195
+ else {
196
+ found.push(childKey);
197
+ }
198
+ }
199
+ return found;
200
+ };
201
+ return walk(dir, keyPrefix);
202
+ }
203
+ async _listKeysSandbox(dir, keyPrefix) {
204
+ const sandbox = this._sandbox;
205
+ const walk = async (walkDir, walkPrefix) => {
206
+ let entries;
207
+ try {
208
+ entries = await sandbox.listFiles(walkDir);
209
+ }
210
+ catch (error) {
211
+ if (isNotFoundError(error))
212
+ return [];
213
+ throw new StorageError(`Failed to list sandbox storage under '${walkPrefix}'`, { cause: error });
214
+ }
215
+ const found = [];
216
+ for (const entry of entries) {
217
+ if (!entry.isDir && entry.name.includes('.__strands_tmp'))
218
+ continue;
219
+ const childKey = walkPrefix ? `${walkPrefix}/${entry.name}` : entry.name;
220
+ if (entry.isDir) {
221
+ found.push(...(await walk(`${walkDir}/${entry.name}`, childKey)));
222
+ }
223
+ else {
224
+ found.push(childKey);
225
+ }
226
+ }
227
+ return found;
228
+ };
229
+ return walk(dir, keyPrefix);
230
+ }
231
+ /**
232
+ * Returns a prefixed view of this storage without mutating the original.
233
+ * The returned view preserves `forSandbox` for single-level namespacing;
234
+ * nested `.namespace()` calls on the view do not carry sandbox routing.
235
+ */
236
+ namespace(prefix) {
237
+ const view = namespace(this, prefix);
238
+ return {
239
+ ...view,
240
+ forSandbox: (sandbox) => namespace(this.forSandbox(sandbox), prefix),
241
+ };
242
+ }
243
+ }
244
+ //# sourceMappingURL=local-file-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-file-storage.js","sourceRoot":"","sources":["../../../src/storage/local-file-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import type { Storage } from './storage.js';
2
+ /** Configuration for {@link S3Storage}. */
3
+ export interface S3StorageConfig {
4
+ /** Optional key prefix prepended to every key (a leading namespace within the bucket). */
5
+ prefix?: string;
6
+ /** AWS region override. When omitted, the SDK's standard resolution chain applies. Cannot be combined with `s3Client`. */
7
+ region?: string;
8
+ /** Pre-configured S3 client. Cannot be combined with `region`. */
9
+ s3Client?: import('@aws-sdk/client-s3').S3Client;
10
+ }
11
+ /**
12
+ * Amazon S3 {@link Storage} backend.
13
+ *
14
+ * Stores each key as an S3 object under an optional prefix. The AWS SDK is loaded
15
+ * lazily on first use and declared as an optional peer dependency, so consumers that
16
+ * never construct an `S3Storage` are not required to install `@aws-sdk/client-s3`.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { S3Storage } from '@strands-agents/sdk/storage'
21
+ *
22
+ * const storage = new S3Storage('my-bucket', { prefix: 'agents/' })
23
+ * await storage.write('sessions/abc/snapshot.json', bytes)
24
+ * ```
25
+ */
26
+ export declare class S3Storage implements Storage {
27
+ private readonly _bucket;
28
+ private readonly _prefix;
29
+ private readonly _region;
30
+ private _client;
31
+ /**
32
+ * @param bucket - Target S3 bucket name
33
+ * @param config - Optional prefix, region, or pre-configured client
34
+ * @throws {@link StorageError} if both `region` and `s3Client` are provided
35
+ */
36
+ constructor(bucket: string, config?: S3StorageConfig);
37
+ /**
38
+ * Stores `data` under `key`, overwriting any existing value.
39
+ *
40
+ * @param key - Opaque, `/`-separated key identifying the value
41
+ * @param data - Raw bytes to persist
42
+ * @throws {@link StorageError} if the key is invalid or the upload fails
43
+ */
44
+ write(key: string, data: Uint8Array): Promise<void>;
45
+ /**
46
+ * Retrieves the bytes previously stored under `key`.
47
+ *
48
+ * @param key - The key to read
49
+ * @returns The stored bytes, or `null` if no value exists for `key`
50
+ * @throws {@link StorageError} if the key is invalid or the download fails
51
+ */
52
+ read(key: string): Promise<Uint8Array | null>;
53
+ /**
54
+ * Deletes the value stored under `key`. A no-op if the key does not exist.
55
+ *
56
+ * @param key - The key to delete
57
+ * @throws {@link StorageError} if the key is invalid or the delete request fails
58
+ */
59
+ delete(key: string): Promise<void>;
60
+ /**
61
+ * Lists the keys whose names begin with `prefix`, sorted lexicographically.
62
+ *
63
+ * @param prefix - Key prefix to match. An empty string matches all keys.
64
+ * @returns The matching keys, sorted ascending
65
+ * @throws {@link StorageError} if the prefix is invalid or the list request fails
66
+ */
67
+ list(prefix: string): Promise<string[]>;
68
+ private _getClient;
69
+ /** Returns a prefixed view of this storage without mutating the original. */
70
+ namespace(prefix: string): Storage;
71
+ private _objectKey;
72
+ }
73
+ //# sourceMappingURL=s3-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/s3-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0HAA0H;IAC1H,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,oBAAoB,EAAE,QAAQ,CAAA;CACjD;AAID;;;;;;;;;;;;;;GAcG;AACH,qBAAa,SAAU,YAAW,OAAO;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,OAAO,CAAmD;IAElE;;;;OAIG;gBACS,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe;IAUpD;;;;;;OAMG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzD;;;;;;OAMG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAkBnD;;;;;OAKG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC;;;;;;OAMG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YA6B/B,UAAU;IAOxB,6EAA6E;IAC7E,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIlC,OAAO,CAAC,UAAU;CAGnB"}
@@ -0,0 +1,146 @@
1
+ import { StorageError } from '../errors.js';
2
+ import { namespace, normalizeKey, normalizePrefix } from './storage.js';
3
+ const S3_PAGE_SIZE = 1000;
4
+ /**
5
+ * Amazon S3 {@link Storage} backend.
6
+ *
7
+ * Stores each key as an S3 object under an optional prefix. The AWS SDK is loaded
8
+ * lazily on first use and declared as an optional peer dependency, so consumers that
9
+ * never construct an `S3Storage` are not required to install `@aws-sdk/client-s3`.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { S3Storage } from '@strands-agents/sdk/storage'
14
+ *
15
+ * const storage = new S3Storage('my-bucket', { prefix: 'agents/' })
16
+ * await storage.write('sessions/abc/snapshot.json', bytes)
17
+ * ```
18
+ */
19
+ export class S3Storage {
20
+ _bucket;
21
+ _prefix;
22
+ _region;
23
+ _client;
24
+ /**
25
+ * @param bucket - Target S3 bucket name
26
+ * @param config - Optional prefix, region, or pre-configured client
27
+ * @throws {@link StorageError} if both `region` and `s3Client` are provided
28
+ */
29
+ constructor(bucket, config) {
30
+ if (config?.s3Client && config.region) {
31
+ throw new StorageError('Cannot specify both s3Client and region. Configure the region on the S3Client instead.');
32
+ }
33
+ this._bucket = bucket;
34
+ this._prefix = config?.prefix ? config.prefix.split('/').filter(Boolean).join('/') + '/' : '';
35
+ this._region = config?.region;
36
+ this._client = config?.s3Client;
37
+ }
38
+ /**
39
+ * Stores `data` under `key`, overwriting any existing value.
40
+ *
41
+ * @param key - Opaque, `/`-separated key identifying the value
42
+ * @param data - Raw bytes to persist
43
+ * @throws {@link StorageError} if the key is invalid or the upload fails
44
+ */
45
+ async write(key, data) {
46
+ const normalized = normalizeKey(key);
47
+ const client = await this._getClient();
48
+ const { PutObjectCommand } = await import('@aws-sdk/client-s3');
49
+ try {
50
+ await client.send(new PutObjectCommand({ Bucket: this._bucket, Key: this._objectKey(normalized), Body: data }));
51
+ }
52
+ catch (error) {
53
+ throw new StorageError(`Failed to write '${normalized}' to S3 bucket '${this._bucket}'`, { cause: error });
54
+ }
55
+ }
56
+ /**
57
+ * Retrieves the bytes previously stored under `key`.
58
+ *
59
+ * @param key - The key to read
60
+ * @returns The stored bytes, or `null` if no value exists for `key`
61
+ * @throws {@link StorageError} if the key is invalid or the download fails
62
+ */
63
+ async read(key) {
64
+ const normalized = normalizeKey(key);
65
+ const client = await this._getClient();
66
+ const { GetObjectCommand } = await import('@aws-sdk/client-s3');
67
+ try {
68
+ const response = await client.send(new GetObjectCommand({ Bucket: this._bucket, Key: this._objectKey(normalized) }));
69
+ const body = await response.Body?.transformToByteArray();
70
+ return body ? new Uint8Array(body) : null;
71
+ }
72
+ catch (error) {
73
+ if (error instanceof Error && (error.name === 'NoSuchKey' || error.name === 'NotFound')) {
74
+ return null;
75
+ }
76
+ throw new StorageError(`Failed to read '${normalized}' from S3 bucket '${this._bucket}'`, { cause: error });
77
+ }
78
+ }
79
+ /**
80
+ * Deletes the value stored under `key`. A no-op if the key does not exist.
81
+ *
82
+ * @param key - The key to delete
83
+ * @throws {@link StorageError} if the key is invalid or the delete request fails
84
+ */
85
+ async delete(key) {
86
+ const normalized = normalizeKey(key);
87
+ const client = await this._getClient();
88
+ const { DeleteObjectCommand } = await import('@aws-sdk/client-s3');
89
+ try {
90
+ await client.send(new DeleteObjectCommand({ Bucket: this._bucket, Key: this._objectKey(normalized) }));
91
+ }
92
+ catch (error) {
93
+ throw new StorageError(`Failed to delete '${normalized}' from S3 bucket '${this._bucket}'`, { cause: error });
94
+ }
95
+ }
96
+ /**
97
+ * Lists the keys whose names begin with `prefix`, sorted lexicographically.
98
+ *
99
+ * @param prefix - Key prefix to match. An empty string matches all keys.
100
+ * @returns The matching keys, sorted ascending
101
+ * @throws {@link StorageError} if the prefix is invalid or the list request fails
102
+ */
103
+ async list(prefix) {
104
+ const normalized = normalizePrefix(prefix);
105
+ const client = await this._getClient();
106
+ const { ListObjectsV2Command } = await import('@aws-sdk/client-s3');
107
+ const listPrefix = `${this._prefix}${normalized}`;
108
+ const keys = [];
109
+ let continuationToken;
110
+ try {
111
+ do {
112
+ const response = await client.send(new ListObjectsV2Command({
113
+ Bucket: this._bucket,
114
+ Prefix: listPrefix,
115
+ MaxKeys: S3_PAGE_SIZE,
116
+ ContinuationToken: continuationToken,
117
+ }));
118
+ for (const object of response.Contents ?? []) {
119
+ if (object.Key === undefined)
120
+ continue;
121
+ keys.push(this._prefix ? object.Key.slice(this._prefix.length) : object.Key);
122
+ }
123
+ continuationToken = response.IsTruncated ? response.NextContinuationToken : undefined;
124
+ } while (continuationToken);
125
+ }
126
+ catch (error) {
127
+ throw new StorageError(`Failed to list S3 bucket '${this._bucket}' under '${normalized}'`, { cause: error });
128
+ }
129
+ return keys.sort();
130
+ }
131
+ async _getClient() {
132
+ if (this._client)
133
+ return this._client;
134
+ const { S3Client } = await import('@aws-sdk/client-s3');
135
+ this._client = new S3Client(this._region ? { region: this._region } : {});
136
+ return this._client;
137
+ }
138
+ /** Returns a prefixed view of this storage without mutating the original. */
139
+ namespace(prefix) {
140
+ return namespace(this, prefix);
141
+ }
142
+ _objectKey(key) {
143
+ return `${this._prefix}${key}`;
144
+ }
145
+ }
146
+ //# sourceMappingURL=s3-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-storage.js","sourceRoot":"","sources":["../../../src/storage/s3-storage.ts"],"names":[],"mappings":"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"}