@steel-dev/atlas 0.1.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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/dist/agent.d.ts +34 -0
  4. package/dist/agent.js +133 -0
  5. package/dist/async.d.ts +19 -0
  6. package/dist/async.js +172 -0
  7. package/dist/atlas.d.ts +19 -0
  8. package/dist/atlas.js +69 -0
  9. package/dist/budget.d.ts +64 -0
  10. package/dist/budget.js +336 -0
  11. package/dist/checklist.d.ts +115 -0
  12. package/dist/checklist.js +297 -0
  13. package/dist/cli.js +38700 -0
  14. package/dist/config.d.ts +80 -0
  15. package/dist/config.js +109 -0
  16. package/dist/context.d.ts +26 -0
  17. package/dist/context.js +250 -0
  18. package/dist/custom-tools.d.ts +26 -0
  19. package/dist/custom-tools.js +33 -0
  20. package/dist/defaults.d.ts +10 -0
  21. package/dist/defaults.js +37 -0
  22. package/dist/economy.d.ts +12 -0
  23. package/dist/economy.js +6 -0
  24. package/dist/env.d.ts +1 -0
  25. package/dist/env.js +8 -0
  26. package/dist/errors.d.ts +6 -0
  27. package/dist/errors.js +11 -0
  28. package/dist/event-hub.d.ts +11 -0
  29. package/dist/event-hub.js +83 -0
  30. package/dist/events.d.ts +105 -0
  31. package/dist/events.js +1 -0
  32. package/dist/html-extract.d.ts +21 -0
  33. package/dist/html-extract.js +459 -0
  34. package/dist/index.d.ts +59 -0
  35. package/dist/index.js +26 -0
  36. package/dist/memory.d.ts +2 -0
  37. package/dist/memory.js +38 -0
  38. package/dist/model.d.ts +49 -0
  39. package/dist/model.js +630 -0
  40. package/dist/orchestrate.d.ts +5 -0
  41. package/dist/orchestrate.js +277 -0
  42. package/dist/pdf-extract.d.ts +5 -0
  43. package/dist/pdf-extract.js +20 -0
  44. package/dist/prompts.d.ts +2 -0
  45. package/dist/prompts.js +6 -0
  46. package/dist/providers/domain/arxiv.d.ts +6 -0
  47. package/dist/providers/domain/arxiv.js +83 -0
  48. package/dist/providers/domain/clinicaltrials.d.ts +6 -0
  49. package/dist/providers/domain/clinicaltrials.js +104 -0
  50. package/dist/providers/domain/edgar.d.ts +10 -0
  51. package/dist/providers/domain/edgar.js +92 -0
  52. package/dist/providers/domain/index.d.ts +14 -0
  53. package/dist/providers/domain/index.js +7 -0
  54. package/dist/providers/domain/openalex.d.ts +7 -0
  55. package/dist/providers/domain/openalex.js +128 -0
  56. package/dist/providers/domain/pubmed.d.ts +8 -0
  57. package/dist/providers/domain/pubmed.js +123 -0
  58. package/dist/providers/domain/semantic-scholar.d.ts +6 -0
  59. package/dist/providers/domain/semantic-scholar.js +112 -0
  60. package/dist/providers/domain/shared.d.ts +12 -0
  61. package/dist/providers/domain/shared.js +39 -0
  62. package/dist/providers/domain/wikipedia.d.ts +6 -0
  63. package/dist/providers/domain/wikipedia.js +71 -0
  64. package/dist/providers/exa-agent.d.ts +9 -0
  65. package/dist/providers/exa-agent.js +67 -0
  66. package/dist/providers/fetch.d.ts +66 -0
  67. package/dist/providers/fetch.js +675 -0
  68. package/dist/providers/parallel-agent.d.ts +11 -0
  69. package/dist/providers/parallel-agent.js +100 -0
  70. package/dist/providers/perplexity-agent.d.ts +17 -0
  71. package/dist/providers/perplexity-agent.js +86 -0
  72. package/dist/providers/search.d.ts +65 -0
  73. package/dist/providers/search.js +433 -0
  74. package/dist/providers/store.d.ts +48 -0
  75. package/dist/providers/store.js +217 -0
  76. package/dist/researcher.d.ts +20 -0
  77. package/dist/researcher.js +3 -0
  78. package/dist/robots.d.ts +16 -0
  79. package/dist/robots.js +146 -0
  80. package/dist/roles.d.ts +6 -0
  81. package/dist/roles.js +4 -0
  82. package/dist/run.d.ts +65 -0
  83. package/dist/run.js +371 -0
  84. package/dist/safe-dispatcher.d.ts +16 -0
  85. package/dist/safe-dispatcher.js +32 -0
  86. package/dist/safety.d.ts +23 -0
  87. package/dist/safety.js +206 -0
  88. package/dist/sandbox.d.ts +22 -0
  89. package/dist/sandbox.js +228 -0
  90. package/dist/search-normalize.d.ts +2 -0
  91. package/dist/search-normalize.js +13 -0
  92. package/dist/source-documents.d.ts +77 -0
  93. package/dist/source-documents.js +421 -0
  94. package/dist/sources.d.ts +57 -0
  95. package/dist/sources.js +1 -0
  96. package/dist/spine.d.ts +19 -0
  97. package/dist/spine.js +722 -0
  98. package/dist/state.d.ts +90 -0
  99. package/dist/state.js +27 -0
  100. package/dist/structured.d.ts +7 -0
  101. package/dist/structured.js +18 -0
  102. package/dist/tools.d.ts +33 -0
  103. package/dist/tools.js +1187 -0
  104. package/dist/trace-digest.d.ts +11 -0
  105. package/dist/trace-digest.js +309 -0
  106. package/dist/trace.d.ts +225 -0
  107. package/dist/trace.js +278 -0
  108. package/dist/trail.d.ts +15 -0
  109. package/dist/trail.js +74 -0
  110. package/dist/url.d.ts +1 -0
  111. package/dist/url.js +25 -0
  112. package/package.json +107 -0
package/dist/trace.js ADDED
@@ -0,0 +1,278 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ export const TRACE_SCHEMA_VERSION = "1.0";
3
+ const MAX_FIELD_CHARS = 256 * 1024; // per prompt/message/output field
4
+ const MAX_TOTAL_CHARS = 512 * 1024 * 1024; // whole-run verbatim budget
5
+ /** Maps trace sites back to their source locations. */
6
+ export const SITE_SOURCE = {
7
+ research: "src/agent.ts:runAgent",
8
+ write: "src/agent.ts:runAgent",
9
+ synthesize: "src/spine.ts:synthesizeHolistic",
10
+ seed: "src/checklist.ts:seedLedger",
11
+ search: "src/tools.ts:execSearchTool",
12
+ fetch: "src/tools.ts:fetchSourceDocument",
13
+ run_code: "src/tools.ts:run_code",
14
+ };
15
+ const als = new AsyncLocalStorage();
16
+ export function currentFrame() {
17
+ return als.getStore();
18
+ }
19
+ /** Run `fn` under a trace frame merged onto the current one. */
20
+ export function withTraceFrame(recorder, patch, fn) {
21
+ if (!recorder)
22
+ return fn();
23
+ const parent = als.getStore();
24
+ return als.run({ ...parent, ...patch }, fn);
25
+ }
26
+ function clampText(value) {
27
+ if (value.length <= MAX_FIELD_CHARS)
28
+ return { text: value, truncated: false };
29
+ return {
30
+ text: `${value.slice(0, MAX_FIELD_CHARS)}…[truncated]`,
31
+ truncated: true,
32
+ };
33
+ }
34
+ function safeJson(value) {
35
+ let raw;
36
+ try {
37
+ raw = JSON.stringify(value);
38
+ }
39
+ catch {
40
+ return { text: '"[unserializable]"', truncated: true };
41
+ }
42
+ return clampText(raw);
43
+ }
44
+ function systemFromPrompt(prompt) {
45
+ const parts = [];
46
+ for (const message of prompt) {
47
+ if (message.role !== "system")
48
+ continue;
49
+ const content = message.content;
50
+ if (typeof content === "string")
51
+ parts.push(content);
52
+ }
53
+ return clampText(parts.join("\n\n")).text;
54
+ }
55
+ /** Normalize model content blocks into the trace viewer's block vocabulary. */
56
+ export function toAnthropicBlocks(content) {
57
+ if (!content)
58
+ return [];
59
+ const blocks = [];
60
+ for (const part of content) {
61
+ switch (part.type) {
62
+ case "text":
63
+ blocks.push({ type: "text", text: clampText(part.text).text });
64
+ break;
65
+ case "reasoning":
66
+ blocks.push({
67
+ type: "thinking",
68
+ thinking: clampText(part.text).text,
69
+ });
70
+ break;
71
+ case "tool-call":
72
+ blocks.push({
73
+ type: "tool_call",
74
+ name: part.toolName,
75
+ input: parseToolInput(part.input),
76
+ });
77
+ break;
78
+ case "tool-result":
79
+ blocks.push({ type: "tool_result", toolName: part.toolName });
80
+ break;
81
+ default:
82
+ blocks.push({ type: part.type });
83
+ }
84
+ }
85
+ return blocks;
86
+ }
87
+ function parseToolInput(input) {
88
+ const { text } = clampText(input);
89
+ try {
90
+ return JSON.parse(text);
91
+ }
92
+ catch {
93
+ return text;
94
+ }
95
+ }
96
+ export class TraceRecorder {
97
+ mode;
98
+ nowFn;
99
+ startedAt;
100
+ spanList = [];
101
+ stepList = [];
102
+ spanSeq = 0;
103
+ totalChars = 0;
104
+ degradedFlag = false;
105
+ digest;
106
+ sink;
107
+ constructor(opts) {
108
+ this.mode = opts.mode;
109
+ this.nowFn = opts.now;
110
+ this.startedAt = opts.startedAt;
111
+ }
112
+ now() {
113
+ return this.nowFn();
114
+ }
115
+ get spans() {
116
+ return this.spanList;
117
+ }
118
+ get steps() {
119
+ return this.stepList;
120
+ }
121
+ get degraded() {
122
+ return this.degradedFlag;
123
+ }
124
+ mintSpanId() {
125
+ return `span_${++this.spanSeq}`;
126
+ }
127
+ /** Where trace entries are streamed for plain-run journaling (P7). */
128
+ setSink(sink) {
129
+ this.sink = sink;
130
+ }
131
+ addSpan(span) {
132
+ this.spanList.push(span);
133
+ this.sink?.("span", span.id, span);
134
+ }
135
+ recordAgentSpan(rec) {
136
+ this.addSpan({
137
+ id: rec.id,
138
+ ...(rec.parentId ? { parentId: rec.parentId } : {}),
139
+ kind: "agent",
140
+ site: rec.site,
141
+ agentId: rec.agentId,
142
+ ...(rec.logicalAgentId ? { logicalAgentId: rec.logicalAgentId } : {}),
143
+ ...(rec.role ? { role: rec.role } : {}),
144
+ t0: rec.t0,
145
+ t1: rec.t1,
146
+ durationMs: Math.max(0, rec.t1 - rec.t0),
147
+ waitMs: 0,
148
+ ...(rec.costUSD !== undefined ? { costUSD: rec.costUSD } : {}),
149
+ status: rec.status,
150
+ ...(rec.attrs ? { attrs: rec.attrs } : {}),
151
+ });
152
+ }
153
+ recordToolSpan(rec) {
154
+ const id = this.mintSpanId();
155
+ this.addSpan({
156
+ id,
157
+ ...(rec.parentId ? { parentId: rec.parentId } : {}),
158
+ kind: rec.kind,
159
+ site: rec.site,
160
+ ...(rec.agentId ? { agentId: rec.agentId } : {}),
161
+ t0: rec.t0,
162
+ t1: rec.t1,
163
+ durationMs: Math.max(0, rec.t1 - rec.t0),
164
+ waitMs: rec.waitMs,
165
+ computeMs: Math.max(0, rec.t1 - rec.t0 - rec.waitMs),
166
+ status: rec.status,
167
+ ...(rec.attrs ? { attrs: rec.attrs } : {}),
168
+ });
169
+ }
170
+ recordModelCall(rec, frame) {
171
+ const id = this.mintSpanId();
172
+ const site = frame?.site ?? rec.role ?? "unattributed";
173
+ this.addSpan({
174
+ id,
175
+ ...(frame?.parentSpanId ? { parentId: frame.parentSpanId } : {}),
176
+ kind: "model",
177
+ site,
178
+ ...(frame?.agentId ? { agentId: frame.agentId } : {}),
179
+ ...(frame?.logicalAgentId
180
+ ? { logicalAgentId: frame.logicalAgentId }
181
+ : {}),
182
+ role: rec.role,
183
+ t0: rec.t0,
184
+ t1: rec.t1,
185
+ durationMs: Math.max(0, rec.t1 - rec.t0),
186
+ waitMs: rec.waitMs,
187
+ computeMs: rec.computeMs,
188
+ ...(rec.retryDelayMs ? { retryDelayMs: rec.retryDelayMs } : {}),
189
+ ...(rec.tokens ? { tokens: rec.tokens } : {}),
190
+ ...(rec.costUSD !== undefined ? { costUSD: rec.costUSD } : {}),
191
+ status: rec.status,
192
+ attrs: {
193
+ callKey: rec.callKey,
194
+ adapter: `${rec.provider}:${rec.modelId}`,
195
+ ...(rec.finishReason ? { finishReason: rec.finishReason } : {}),
196
+ ...(rec.replayed ? { replayed: true } : {}),
197
+ ...(rec.attempts && rec.attempts > 1 ? { attempts: rec.attempts } : {}),
198
+ },
199
+ });
200
+ if (this.mode === "full" && rec.params) {
201
+ this.recordStep(id, site, rec, frame);
202
+ }
203
+ }
204
+ recordStep(spanId, site, rec, frame) {
205
+ const params = rec.params;
206
+ let truncated = false;
207
+ if (this.degradedFlag) {
208
+ // Past the verbatim budget: keep the span, drop the heavy I/O.
209
+ return;
210
+ }
211
+ const messagesPacked = safeJson(params.prompt);
212
+ truncated = truncated || messagesPacked.truncated;
213
+ const outputBlocks = rec.error ? [] : toAnthropicBlocks(rec.content);
214
+ const outputPacked = safeJson(outputBlocks);
215
+ truncated = truncated || outputPacked.truncated;
216
+ this.totalChars += messagesPacked.text.length + outputPacked.text.length;
217
+ if (this.totalChars > MAX_TOTAL_CHARS) {
218
+ this.degradedFlag = true;
219
+ return;
220
+ }
221
+ const toolNames = params.tools
222
+ ?.map((t) => ("name" in t ? t.name : undefined))
223
+ .filter((n) => Boolean(n));
224
+ const responseFormat = params.responseFormat;
225
+ const outputSchema = responseFormat && responseFormat.type === "json"
226
+ ? safeJson(responseFormat.schema ?? responseFormat.name ?? "json").text
227
+ : undefined;
228
+ const step = {
229
+ seq: this.stepList.length + 1,
230
+ atMs: Math.max(0, rec.t0 - this.startedAt),
231
+ spanId,
232
+ role: rec.role,
233
+ adapter: `${rec.provider}:${rec.modelId}`,
234
+ site,
235
+ ...(frame?.agentId ? { agentId: frame.agentId } : {}),
236
+ durationMs: rec.computeMs,
237
+ waitMs: rec.waitMs,
238
+ system: systemFromPrompt(params.prompt),
239
+ messages: params.prompt,
240
+ ...(toolNames?.length ? { toolNames } : {}),
241
+ maxTokens: params.maxOutputTokens ?? 0,
242
+ ...(outputSchema ? { outputSchema } : {}),
243
+ output: outputBlocks,
244
+ ...(rec.tokens
245
+ ? {
246
+ inputTokens: rec.tokens.input + rec.tokens.cacheRead + rec.tokens.cacheWrite,
247
+ }
248
+ : {}),
249
+ ...(rec.costUSD !== undefined ? { costUSD: rec.costUSD } : {}),
250
+ ...(rec.finishReason ? { finishReason: rec.finishReason } : {}),
251
+ ...(rec.replayed ? { replayed: true } : {}),
252
+ ...(truncated ? { truncated: true } : {}),
253
+ ...(rec.error ? { error: rec.error } : {}),
254
+ };
255
+ this.stepList.push(step);
256
+ this.sink?.("step", spanId, step);
257
+ }
258
+ finalize(digest) {
259
+ this.digest = {
260
+ ...digest,
261
+ ...(this.degradedFlag ? { degraded: true } : {}),
262
+ };
263
+ this.sink?.("digest", "digest", this.digest);
264
+ }
265
+ snapshot() {
266
+ return {
267
+ schemaVersion: TRACE_SCHEMA_VERSION,
268
+ mode: this.mode,
269
+ spans: this.spanList,
270
+ steps: this.stepList,
271
+ ...(this.digest ? { digest: this.digest } : {}),
272
+ degraded: this.degradedFlag,
273
+ };
274
+ }
275
+ }
276
+ export function createTraceRecorder(opts) {
277
+ return new TraceRecorder(opts);
278
+ }
@@ -0,0 +1,15 @@
1
+ export interface TrailRenderOptions {
2
+ maxSearches?: number;
3
+ maxDeadEnds?: number;
4
+ guidance?: string;
5
+ }
6
+ export declare function trailCapsFor(maxSources: number, fraction?: number): Required<Pick<TrailRenderOptions, "maxSearches" | "maxDeadEnds">>;
7
+ export interface Trail {
8
+ readonly searchCount: number;
9
+ readonly deadEndCount: number;
10
+ recordSearch(query: string, results: number): void;
11
+ recordDeadEnd(url: string, reason: string): void;
12
+ isDeadEnd(url: string): string | undefined;
13
+ render(opts?: TrailRenderOptions): string;
14
+ }
15
+ export declare function createTrail(): Trail;
package/dist/trail.js ADDED
@@ -0,0 +1,74 @@
1
+ import { trailKey } from "./search-normalize.js";
2
+ const RENDER_MAX_SEARCHES = 50;
3
+ const RENDER_MAX_DEAD_ENDS = 25;
4
+ const REASON_MAX_CHARS = 120;
5
+ const CAP_FLOOR_SEARCHES = 30;
6
+ const CAP_FLOOR_DEAD_ENDS = 15;
7
+ export function trailCapsFor(maxSources, fraction = 1) {
8
+ const maxSearches = Math.max(CAP_FLOOR_SEARCHES, Math.ceil(maxSources * fraction));
9
+ return {
10
+ maxSearches,
11
+ maxDeadEnds: Math.max(CAP_FLOOR_DEAD_ENDS, Math.ceil(maxSearches / 2)),
12
+ };
13
+ }
14
+ export function createTrail() {
15
+ const searches = new Map();
16
+ const deadEnds = new Map();
17
+ return {
18
+ get searchCount() {
19
+ return searches.size;
20
+ },
21
+ get deadEndCount() {
22
+ return deadEnds.size;
23
+ },
24
+ recordSearch(query, results) {
25
+ const text = query.trim();
26
+ if (!text)
27
+ return;
28
+ const key = trailKey(text);
29
+ const existing = searches.get(key);
30
+ if (existing) {
31
+ existing.results = Math.max(existing.results, results);
32
+ }
33
+ else {
34
+ searches.set(key, { query: text, results });
35
+ }
36
+ },
37
+ recordDeadEnd(url, reason) {
38
+ const target = url.trim();
39
+ if (!target || deadEnds.has(target))
40
+ return;
41
+ deadEnds.set(target, reason.trim().slice(0, REASON_MAX_CHARS));
42
+ },
43
+ isDeadEnd(url) {
44
+ return deadEnds.get(url.trim());
45
+ },
46
+ render(opts = {}) {
47
+ const maxSearches = opts.maxSearches ?? RENDER_MAX_SEARCHES;
48
+ const maxDeadEnds = opts.maxDeadEnds ?? RENDER_MAX_DEAD_ENDS;
49
+ const guidance = opts.guidance ?? "do not repeat them; vary the terms or angle instead";
50
+ const lines = [];
51
+ if (searches.size > 0) {
52
+ lines.push(`Searches already run (${searches.size} — ${guidance}):`);
53
+ const entries = [...searches.values()];
54
+ for (const entry of entries.slice(0, maxSearches)) {
55
+ lines.push(`- "${entry.query}" → ${entry.results} result(s)`);
56
+ }
57
+ if (entries.length > maxSearches) {
58
+ lines.push(`…and ${entries.length - maxSearches} more searches`);
59
+ }
60
+ }
61
+ if (deadEnds.size > 0) {
62
+ lines.push("Dead-end fetches (no usable content came back):");
63
+ const entries = [...deadEnds.entries()];
64
+ for (const [url, reason] of entries.slice(0, maxDeadEnds)) {
65
+ lines.push(`- ${url} — ${reason}`);
66
+ }
67
+ if (entries.length > maxDeadEnds) {
68
+ lines.push(`…and ${entries.length - maxDeadEnds} more dead ends`);
69
+ }
70
+ }
71
+ return lines.join("\n");
72
+ },
73
+ };
74
+ }
package/dist/url.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function normalizeUrlForSource(url: string): string;
package/dist/url.js ADDED
@@ -0,0 +1,25 @@
1
+ const TRACKING_QUERY_PARAMS = new Set([
2
+ "fbclid",
3
+ "gclid",
4
+ "igshid",
5
+ "mc_cid",
6
+ "mc_eid",
7
+ "msclkid",
8
+ ]);
9
+ export function normalizeUrlForSource(url) {
10
+ try {
11
+ const u = new URL(url);
12
+ u.hash = "";
13
+ for (const key of [...u.searchParams.keys()]) {
14
+ const lower = key.toLowerCase();
15
+ if (lower.startsWith("utm_") || TRACKING_QUERY_PARAMS.has(lower)) {
16
+ u.searchParams.delete(key);
17
+ }
18
+ }
19
+ u.searchParams.sort();
20
+ return u.toString();
21
+ }
22
+ catch {
23
+ return url;
24
+ }
25
+ }
package/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@steel-dev/atlas",
3
+ "version": "0.1.0",
4
+ "description": "Deep research from your terminal or your code. Backed by Steel Browser and model providers.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "atlas": "dist/cli.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "scripts": {
26
+ "dev": "tsx examples/cli.ts",
27
+ "eval:browsecomp": "tsx evals/browsecomp.ts",
28
+ "eval:browsecomp:official": "tsx evals/browsecomp.ts --cases https://openaipublic.blob.core.windows.net/simple-evals/browse_comp_test_set.csv",
29
+ "eval:draco": "tsx evals/draco.ts",
30
+ "eval:draco:explore": "tsx examples/eval-explorer/cli.ts",
31
+ "draco:q": "tsx examples/eval-explorer/query.ts",
32
+ "trace": "tsx examples/trace.ts",
33
+ "eval:typecheck": "tsc -p evals/tsconfig.json && tsc -p examples/eval-explorer/tsconfig.client.json",
34
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/bundle-cli.mjs",
35
+ "typecheck": "tsc -p tsconfig.json && tsc -p examples/tsconfig.cli.json",
36
+ "lint": "biome check .",
37
+ "lint:fix": "biome check --write .",
38
+ "format": "biome format --write .",
39
+ "check:exports": "publint --strict && attw --pack . --ignore-rules cjs-resolves-to-esm",
40
+ "test": "vitest",
41
+ "test:run": "vitest run",
42
+ "prepublishOnly": "npm run build"
43
+ },
44
+ "engines": {
45
+ "node": ">=20.16.0"
46
+ },
47
+ "dependencies": {
48
+ "@ai-sdk/provider": "^3.0.0",
49
+ "cheerio": "^1.0.0",
50
+ "exa-js": "^2.14.0",
51
+ "pdf-parse": "^2.4.5",
52
+ "steel-sdk": "^0.18.0",
53
+ "undici": "^7.25.0",
54
+ "zod": "^4.1.8"
55
+ },
56
+ "peerDependencies": {
57
+ "@ai-sdk/anthropic": "^3.0.0",
58
+ "@ai-sdk/google": "^3.0.0",
59
+ "@ai-sdk/openai": "^3.0.0",
60
+ "ai": "^6.0.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@ai-sdk/anthropic": {
64
+ "optional": true
65
+ },
66
+ "@ai-sdk/openai": {
67
+ "optional": true
68
+ },
69
+ "@ai-sdk/google": {
70
+ "optional": true
71
+ }
72
+ },
73
+ "devDependencies": {
74
+ "@ai-sdk/anthropic": "^3.0.81",
75
+ "@ai-sdk/google": "^3.0.80",
76
+ "@ai-sdk/openai": "^3.0.67",
77
+ "@arethetypeswrong/cli": "^0.18.4",
78
+ "@biomejs/biome": "^2.5.1",
79
+ "@types/node": "^22.0.0",
80
+ "ai": "^6.0.194",
81
+ "esbuild": "^0.25.12",
82
+ "publint": "^0.3.21",
83
+ "tsx": "^4.19.2",
84
+ "typescript": "^5.7.2",
85
+ "vitest": "^2.1.8"
86
+ },
87
+ "keywords": [
88
+ "deep-research",
89
+ "research",
90
+ "cli",
91
+ "anthropic",
92
+ "claude",
93
+ "openai",
94
+ "steel",
95
+ "web-search",
96
+ "agent",
97
+ "llm"
98
+ ],
99
+ "license": "MIT",
100
+ "repository": {
101
+ "type": "git",
102
+ "url": "git+https://github.com/steel-dev/atlas.git"
103
+ },
104
+ "optionalDependencies": {
105
+ "isolated-vm": "^6.1.2"
106
+ }
107
+ }