@gugacoder/agentic-sdk 0.2.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 (129) hide show
  1. package/dist/agent.d.ts +2 -0
  2. package/dist/agent.js +463 -0
  3. package/dist/context/compaction.d.ts +27 -0
  4. package/dist/context/compaction.js +219 -0
  5. package/dist/context/models.d.ts +6 -0
  6. package/dist/context/models.js +41 -0
  7. package/dist/context/tokenizer.d.ts +5 -0
  8. package/dist/context/tokenizer.js +11 -0
  9. package/dist/context/usage.d.ts +11 -0
  10. package/dist/context/usage.js +49 -0
  11. package/dist/display-schemas.d.ts +1865 -0
  12. package/dist/display-schemas.js +219 -0
  13. package/dist/index.d.ts +38 -0
  14. package/dist/index.js +28 -0
  15. package/dist/middleware/logging.d.ts +2 -0
  16. package/dist/middleware/logging.js +32 -0
  17. package/dist/prompts/assembly.d.ts +13 -0
  18. package/dist/prompts/assembly.js +229 -0
  19. package/dist/providers.d.ts +19 -0
  20. package/dist/providers.js +44 -0
  21. package/dist/proxy.d.ts +2 -0
  22. package/dist/proxy.js +103 -0
  23. package/dist/schemas.d.ts +228 -0
  24. package/dist/schemas.js +51 -0
  25. package/dist/session.d.ts +7 -0
  26. package/dist/session.js +102 -0
  27. package/dist/structured.d.ts +18 -0
  28. package/dist/structured.js +38 -0
  29. package/dist/tool-repair.d.ts +21 -0
  30. package/dist/tool-repair.js +72 -0
  31. package/dist/tools/api-spec.d.ts +4 -0
  32. package/dist/tools/api-spec.js +123 -0
  33. package/dist/tools/apply-patch.d.ts +484 -0
  34. package/dist/tools/apply-patch.js +157 -0
  35. package/dist/tools/ask-user.d.ts +14 -0
  36. package/dist/tools/ask-user.js +27 -0
  37. package/dist/tools/bash.d.ts +550 -0
  38. package/dist/tools/bash.js +43 -0
  39. package/dist/tools/batch.d.ts +13 -0
  40. package/dist/tools/batch.js +84 -0
  41. package/dist/tools/brave-search.d.ts +6 -0
  42. package/dist/tools/brave-search.js +19 -0
  43. package/dist/tools/code-search.d.ts +20 -0
  44. package/dist/tools/code-search.js +42 -0
  45. package/dist/tools/diagnostics.d.ts +4 -0
  46. package/dist/tools/diagnostics.js +69 -0
  47. package/dist/tools/display.d.ts +483 -0
  48. package/dist/tools/display.js +77 -0
  49. package/dist/tools/edit.d.ts +682 -0
  50. package/dist/tools/edit.js +47 -0
  51. package/dist/tools/glob.d.ts +4 -0
  52. package/dist/tools/glob.js +42 -0
  53. package/dist/tools/grep.d.ts +6 -0
  54. package/dist/tools/grep.js +69 -0
  55. package/dist/tools/http-request.d.ts +7 -0
  56. package/dist/tools/http-request.js +98 -0
  57. package/dist/tools/index.d.ts +1611 -0
  58. package/dist/tools/index.js +46 -0
  59. package/dist/tools/job-tools.d.ts +24 -0
  60. package/dist/tools/job-tools.js +67 -0
  61. package/dist/tools/list-dir.d.ts +5 -0
  62. package/dist/tools/list-dir.js +79 -0
  63. package/dist/tools/multi-edit.d.ts +814 -0
  64. package/dist/tools/multi-edit.js +57 -0
  65. package/dist/tools/read.d.ts +5 -0
  66. package/dist/tools/read.js +33 -0
  67. package/dist/tools/task.d.ts +21 -0
  68. package/dist/tools/task.js +51 -0
  69. package/dist/tools/todo.d.ts +14 -0
  70. package/dist/tools/todo.js +60 -0
  71. package/dist/tools/web-fetch.d.ts +4 -0
  72. package/dist/tools/web-fetch.js +126 -0
  73. package/dist/tools/web-search.d.ts +22 -0
  74. package/dist/tools/web-search.js +48 -0
  75. package/dist/tools/write.d.ts +550 -0
  76. package/dist/tools/write.js +30 -0
  77. package/dist/types.d.ts +201 -0
  78. package/dist/types.js +1 -0
  79. package/package.json +43 -0
  80. package/src/agent.ts +520 -0
  81. package/src/context/compaction.ts +265 -0
  82. package/src/context/models.ts +42 -0
  83. package/src/context/tokenizer.ts +12 -0
  84. package/src/context/usage.ts +65 -0
  85. package/src/display-schemas.ts +276 -0
  86. package/src/index.ts +43 -0
  87. package/src/middleware/logging.ts +37 -0
  88. package/src/prompts/assembly.ts +263 -0
  89. package/src/prompts/identity.md +10 -0
  90. package/src/prompts/patterns.md +7 -0
  91. package/src/prompts/safety.md +7 -0
  92. package/src/prompts/tool-guide.md +9 -0
  93. package/src/prompts/tools/bash.md +7 -0
  94. package/src/prompts/tools/edit.md +7 -0
  95. package/src/prompts/tools/glob.md +7 -0
  96. package/src/prompts/tools/grep.md +7 -0
  97. package/src/prompts/tools/read.md +7 -0
  98. package/src/prompts/tools/write.md +7 -0
  99. package/src/providers.ts +58 -0
  100. package/src/proxy.ts +101 -0
  101. package/src/schemas.ts +58 -0
  102. package/src/session.ts +110 -0
  103. package/src/structured.ts +65 -0
  104. package/src/tool-repair.ts +92 -0
  105. package/src/tools/api-spec.ts +158 -0
  106. package/src/tools/apply-patch.ts +188 -0
  107. package/src/tools/ask-user.ts +40 -0
  108. package/src/tools/bash.ts +51 -0
  109. package/src/tools/batch.ts +103 -0
  110. package/src/tools/brave-search.ts +24 -0
  111. package/src/tools/code-search.ts +69 -0
  112. package/src/tools/diagnostics.ts +93 -0
  113. package/src/tools/display.ts +105 -0
  114. package/src/tools/edit.ts +55 -0
  115. package/src/tools/glob.ts +46 -0
  116. package/src/tools/grep.ts +68 -0
  117. package/src/tools/http-request.ts +103 -0
  118. package/src/tools/index.ts +48 -0
  119. package/src/tools/job-tools.ts +84 -0
  120. package/src/tools/list-dir.ts +102 -0
  121. package/src/tools/multi-edit.ts +65 -0
  122. package/src/tools/read.ts +40 -0
  123. package/src/tools/task.ts +71 -0
  124. package/src/tools/todo.ts +82 -0
  125. package/src/tools/web-fetch.ts +155 -0
  126. package/src/tools/web-search.ts +75 -0
  127. package/src/tools/write.ts +34 -0
  128. package/src/types.ts +145 -0
  129. package/tsconfig.json +17 -0
package/dist/proxy.js ADDED
@@ -0,0 +1,103 @@
1
+ import { AgentRunOptionsSchema } from "./schemas.js";
2
+ import { runAiAgent } from "./agent.js";
3
+ import { braveSearch } from "./tools/brave-search.js";
4
+ /**
5
+ * DuckDuckGo HTML search scraper — no API key needed.
6
+ */
7
+ async function duckDuckGoSearch(query, numResults = 5) {
8
+ const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
9
+ const res = await fetch(url, {
10
+ headers: {
11
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
12
+ },
13
+ });
14
+ if (!res.ok)
15
+ return [];
16
+ const html = await res.text();
17
+ const results = [];
18
+ const resultPattern = /<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g;
19
+ let match;
20
+ while ((match = resultPattern.exec(html)) !== null && results.length < numResults) {
21
+ const rawUrl = match[1];
22
+ const title = match[2].replace(/<[^>]+>/g, "").trim();
23
+ const snippet = match[3].replace(/<[^>]+>/g, "").trim();
24
+ // DuckDuckGo uses redirect URLs — extract the real URL
25
+ const realUrl = new URL(rawUrl, "https://duckduckgo.com").searchParams.get("uddg") ?? rawUrl;
26
+ if (title && snippet) {
27
+ results.push({ title, url: realUrl, snippet });
28
+ }
29
+ }
30
+ return results;
31
+ }
32
+ /**
33
+ * Resolve web search provider from providerConfig.
34
+ * Returns undefined when search is disabled ("none").
35
+ */
36
+ function resolveSearchProvider(providerConfig) {
37
+ const provider = providerConfig?.webSearch ?? "duckduckgo";
38
+ if (provider === "none")
39
+ return undefined;
40
+ if (provider === "brave" && providerConfig?.braveApiKey) {
41
+ return (q, n) => braveSearch(q, n, providerConfig.braveApiKey);
42
+ }
43
+ return duckDuckGoSearch;
44
+ }
45
+ export async function* runAgent(raw) {
46
+ const options = AgentRunOptionsSchema.parse(raw);
47
+ const startMs = Date.now();
48
+ const onWebSearch = resolveSearchProvider(options.providerConfig);
49
+ console.log(`[proxy] model=${options.model} role=${options.role ?? "conversation"} webSearch=${options.providerConfig?.webSearch ?? "duckduckgo"}`);
50
+ for await (const event of runAiAgent(options.prompt, {
51
+ model: options.model,
52
+ apiKey: options.apiKey,
53
+ provider: options.provider,
54
+ providers: options.providers,
55
+ sessionId: options.sessionId,
56
+ sessionDir: options.sessionDir,
57
+ messageMeta: options.messageMeta,
58
+ maxSteps: options.maxTurns ?? 100,
59
+ ...(onWebSearch ? { onWebSearch } : {}),
60
+ ...(options.tools ? { tools: options.tools } : {}),
61
+ ...(options.system ? { system: { append: options.system } } : {}),
62
+ ...(options.contentParts ? { contentParts: options.contentParts } : {}),
63
+ })) {
64
+ if (event.type === "init") {
65
+ yield { type: "init", sessionId: event.sessionId };
66
+ }
67
+ else if (event.type === "text") {
68
+ yield { type: "text", content: event.content };
69
+ }
70
+ else if (event.type === "result") {
71
+ yield { type: "result", content: event.content };
72
+ }
73
+ else if (event.type === "usage") {
74
+ yield {
75
+ type: "usage",
76
+ usage: {
77
+ inputTokens: event.usage.inputTokens,
78
+ outputTokens: event.usage.outputTokens,
79
+ cacheReadInputTokens: event.usage.cacheReadInputTokens,
80
+ cacheCreationInputTokens: event.usage.cacheCreationInputTokens,
81
+ totalCostUsd: event.usage.totalCostUsd,
82
+ numTurns: event.usage.numTurns,
83
+ durationMs: event.usage.durationMs || (Date.now() - startMs),
84
+ durationApiMs: event.usage.durationApiMs,
85
+ stopReason: event.usage.stopReason,
86
+ },
87
+ };
88
+ }
89
+ else if (event.type === "step_finish") {
90
+ yield { type: "step_finish" };
91
+ }
92
+ else if (event.type === "reasoning") {
93
+ yield { type: "reasoning", content: event.content };
94
+ }
95
+ else if (event.type === "tool-call") {
96
+ yield { type: "tool-call", toolCallId: event.toolCallId, toolName: event.toolName, args: event.args };
97
+ }
98
+ else if (event.type === "tool-result") {
99
+ yield { type: "tool-result", toolCallId: event.toolCallId, toolName: event.toolName, result: event.result };
100
+ }
101
+ // Unknown event types are silently dropped (safe denylist: only known AgentEvent members are forwarded)
102
+ }
103
+ }
@@ -0,0 +1,228 @@
1
+ import { z } from "zod";
2
+ export declare const UsageDataSchema: z.ZodObject<{
3
+ inputTokens: z.ZodNumber;
4
+ outputTokens: z.ZodNumber;
5
+ cacheReadInputTokens: z.ZodDefault<z.ZodNumber>;
6
+ cacheCreationInputTokens: z.ZodDefault<z.ZodNumber>;
7
+ totalCostUsd: z.ZodDefault<z.ZodNumber>;
8
+ numTurns: z.ZodDefault<z.ZodNumber>;
9
+ durationMs: z.ZodDefault<z.ZodNumber>;
10
+ durationApiMs: z.ZodDefault<z.ZodNumber>;
11
+ stopReason: z.ZodDefault<z.ZodString>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ inputTokens: number;
14
+ outputTokens: number;
15
+ cacheReadInputTokens: number;
16
+ cacheCreationInputTokens: number;
17
+ totalCostUsd: number;
18
+ numTurns: number;
19
+ durationMs: number;
20
+ durationApiMs: number;
21
+ stopReason: string;
22
+ }, {
23
+ inputTokens: number;
24
+ outputTokens: number;
25
+ cacheReadInputTokens?: number | undefined;
26
+ cacheCreationInputTokens?: number | undefined;
27
+ totalCostUsd?: number | undefined;
28
+ numTurns?: number | undefined;
29
+ durationMs?: number | undefined;
30
+ durationApiMs?: number | undefined;
31
+ stopReason?: string | undefined;
32
+ }>;
33
+ export declare const AgentEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
34
+ type: z.ZodLiteral<"init">;
35
+ sessionId: z.ZodOptional<z.ZodString>;
36
+ }, "strip", z.ZodTypeAny, {
37
+ type: "init";
38
+ sessionId?: string | undefined;
39
+ }, {
40
+ type: "init";
41
+ sessionId?: string | undefined;
42
+ }>, z.ZodObject<{
43
+ type: z.ZodLiteral<"text">;
44
+ content: z.ZodString;
45
+ }, "strip", z.ZodTypeAny, {
46
+ type: "text";
47
+ content: string;
48
+ }, {
49
+ type: "text";
50
+ content: string;
51
+ }>, z.ZodObject<{
52
+ type: z.ZodLiteral<"step_finish">;
53
+ }, "strip", z.ZodTypeAny, {
54
+ type: "step_finish";
55
+ }, {
56
+ type: "step_finish";
57
+ }>, z.ZodObject<{
58
+ type: z.ZodLiteral<"result">;
59
+ content: z.ZodString;
60
+ }, "strip", z.ZodTypeAny, {
61
+ type: "result";
62
+ content: string;
63
+ }, {
64
+ type: "result";
65
+ content: string;
66
+ }>, z.ZodObject<{
67
+ type: z.ZodLiteral<"usage">;
68
+ usage: z.ZodObject<{
69
+ inputTokens: z.ZodNumber;
70
+ outputTokens: z.ZodNumber;
71
+ cacheReadInputTokens: z.ZodDefault<z.ZodNumber>;
72
+ cacheCreationInputTokens: z.ZodDefault<z.ZodNumber>;
73
+ totalCostUsd: z.ZodDefault<z.ZodNumber>;
74
+ numTurns: z.ZodDefault<z.ZodNumber>;
75
+ durationMs: z.ZodDefault<z.ZodNumber>;
76
+ durationApiMs: z.ZodDefault<z.ZodNumber>;
77
+ stopReason: z.ZodDefault<z.ZodString>;
78
+ }, "strip", z.ZodTypeAny, {
79
+ inputTokens: number;
80
+ outputTokens: number;
81
+ cacheReadInputTokens: number;
82
+ cacheCreationInputTokens: number;
83
+ totalCostUsd: number;
84
+ numTurns: number;
85
+ durationMs: number;
86
+ durationApiMs: number;
87
+ stopReason: string;
88
+ }, {
89
+ inputTokens: number;
90
+ outputTokens: number;
91
+ cacheReadInputTokens?: number | undefined;
92
+ cacheCreationInputTokens?: number | undefined;
93
+ totalCostUsd?: number | undefined;
94
+ numTurns?: number | undefined;
95
+ durationMs?: number | undefined;
96
+ durationApiMs?: number | undefined;
97
+ stopReason?: string | undefined;
98
+ }>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ type: "usage";
101
+ usage: {
102
+ inputTokens: number;
103
+ outputTokens: number;
104
+ cacheReadInputTokens: number;
105
+ cacheCreationInputTokens: number;
106
+ totalCostUsd: number;
107
+ numTurns: number;
108
+ durationMs: number;
109
+ durationApiMs: number;
110
+ stopReason: string;
111
+ };
112
+ }, {
113
+ type: "usage";
114
+ usage: {
115
+ inputTokens: number;
116
+ outputTokens: number;
117
+ cacheReadInputTokens?: number | undefined;
118
+ cacheCreationInputTokens?: number | undefined;
119
+ totalCostUsd?: number | undefined;
120
+ numTurns?: number | undefined;
121
+ durationMs?: number | undefined;
122
+ durationApiMs?: number | undefined;
123
+ stopReason?: string | undefined;
124
+ };
125
+ }>, z.ZodObject<{
126
+ type: z.ZodLiteral<"reasoning">;
127
+ content: z.ZodString;
128
+ }, "strip", z.ZodTypeAny, {
129
+ type: "reasoning";
130
+ content: string;
131
+ }, {
132
+ type: "reasoning";
133
+ content: string;
134
+ }>, z.ZodObject<{
135
+ type: z.ZodLiteral<"tool-call">;
136
+ toolCallId: z.ZodString;
137
+ toolName: z.ZodString;
138
+ args: z.ZodRecord<z.ZodString, z.ZodUnknown>;
139
+ }, "strip", z.ZodTypeAny, {
140
+ type: "tool-call";
141
+ args: Record<string, unknown>;
142
+ toolCallId: string;
143
+ toolName: string;
144
+ }, {
145
+ type: "tool-call";
146
+ args: Record<string, unknown>;
147
+ toolCallId: string;
148
+ toolName: string;
149
+ }>, z.ZodObject<{
150
+ type: z.ZodLiteral<"tool-result">;
151
+ toolCallId: z.ZodString;
152
+ toolName: z.ZodString;
153
+ result: z.ZodUnknown;
154
+ }, "strip", z.ZodTypeAny, {
155
+ type: "tool-result";
156
+ toolCallId: string;
157
+ toolName: string;
158
+ result?: unknown;
159
+ }, {
160
+ type: "tool-result";
161
+ toolCallId: string;
162
+ toolName: string;
163
+ result?: unknown;
164
+ }>]>;
165
+ export declare const AgentRunOptionsSchema: z.ZodObject<{
166
+ model: z.ZodString;
167
+ apiKey: z.ZodString;
168
+ prompt: z.ZodString;
169
+ sessionId: z.ZodOptional<z.ZodString>;
170
+ sessionDir: z.ZodOptional<z.ZodString>;
171
+ role: z.ZodOptional<z.ZodString>;
172
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
173
+ maxTurns: z.ZodOptional<z.ZodNumber>;
174
+ providerConfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
175
+ system: z.ZodOptional<z.ZodString>;
176
+ messageMeta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
177
+ provider: z.ZodOptional<z.ZodString>;
178
+ providers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
179
+ baseURL: z.ZodString;
180
+ apiKey: z.ZodString;
181
+ }, "strip", z.ZodTypeAny, {
182
+ apiKey: string;
183
+ baseURL: string;
184
+ }, {
185
+ apiKey: string;
186
+ baseURL: string;
187
+ }>>>;
188
+ contentParts: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
189
+ }, "strip", z.ZodTypeAny, {
190
+ apiKey: string;
191
+ prompt: string;
192
+ model: string;
193
+ provider?: string | undefined;
194
+ system?: string | undefined;
195
+ tools?: Record<string, any> | undefined;
196
+ sessionId?: string | undefined;
197
+ sessionDir?: string | undefined;
198
+ role?: string | undefined;
199
+ maxTurns?: number | undefined;
200
+ providerConfig?: Record<string, any> | undefined;
201
+ messageMeta?: Record<string, unknown> | undefined;
202
+ providers?: Record<string, {
203
+ apiKey: string;
204
+ baseURL: string;
205
+ }> | undefined;
206
+ contentParts?: any[] | undefined;
207
+ }, {
208
+ apiKey: string;
209
+ prompt: string;
210
+ model: string;
211
+ provider?: string | undefined;
212
+ system?: string | undefined;
213
+ tools?: Record<string, any> | undefined;
214
+ sessionId?: string | undefined;
215
+ sessionDir?: string | undefined;
216
+ role?: string | undefined;
217
+ maxTurns?: number | undefined;
218
+ providerConfig?: Record<string, any> | undefined;
219
+ messageMeta?: Record<string, unknown> | undefined;
220
+ providers?: Record<string, {
221
+ apiKey: string;
222
+ baseURL: string;
223
+ }> | undefined;
224
+ contentParts?: any[] | undefined;
225
+ }>;
226
+ export type AgentEvent = z.infer<typeof AgentEventSchema>;
227
+ export type UsageData = z.infer<typeof UsageDataSchema>;
228
+ export type AgentRunOptions = z.infer<typeof AgentRunOptionsSchema>;
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ // --- Usage ---
3
+ export const UsageDataSchema = z.object({
4
+ inputTokens: z.number(),
5
+ outputTokens: z.number(),
6
+ cacheReadInputTokens: z.number().default(0),
7
+ cacheCreationInputTokens: z.number().default(0),
8
+ totalCostUsd: z.number().default(0),
9
+ numTurns: z.number().default(0),
10
+ durationMs: z.number().default(0),
11
+ durationApiMs: z.number().default(0),
12
+ stopReason: z.string().default("unknown"),
13
+ });
14
+ // --- Events (o que o proxy emite) ---
15
+ export const AgentEventSchema = z.discriminatedUnion("type", [
16
+ z.object({ type: z.literal("init"), sessionId: z.string().optional() }),
17
+ z.object({ type: z.literal("text"), content: z.string() }),
18
+ z.object({ type: z.literal("step_finish") }),
19
+ z.object({ type: z.literal("result"), content: z.string() }),
20
+ z.object({ type: z.literal("usage"), usage: UsageDataSchema }),
21
+ z.object({ type: z.literal("reasoning"), content: z.string() }),
22
+ z.object({
23
+ type: z.literal("tool-call"),
24
+ toolCallId: z.string(),
25
+ toolName: z.string(),
26
+ args: z.record(z.unknown()),
27
+ }),
28
+ z.object({
29
+ type: z.literal("tool-result"),
30
+ toolCallId: z.string(),
31
+ toolName: z.string(),
32
+ result: z.unknown(),
33
+ }),
34
+ ]);
35
+ // --- Options (o que o backbone passa) ---
36
+ export const AgentRunOptionsSchema = z.object({
37
+ model: z.string(),
38
+ apiKey: z.string(),
39
+ prompt: z.string(),
40
+ sessionId: z.string().optional(),
41
+ sessionDir: z.string().optional(),
42
+ role: z.string().optional(),
43
+ tools: z.record(z.any()).optional(),
44
+ maxTurns: z.number().optional(),
45
+ providerConfig: z.record(z.any()).optional(),
46
+ system: z.string().optional(),
47
+ messageMeta: z.record(z.unknown()).optional(),
48
+ provider: z.string().optional(),
49
+ providers: z.record(z.object({ baseURL: z.string(), apiKey: z.string() })).optional(),
50
+ contentParts: z.array(z.any()).optional(),
51
+ });
@@ -0,0 +1,7 @@
1
+ import type { ModelMessage } from "ai";
2
+ export declare function resolveRefs(content: unknown[], attachmentsDir: string): Promise<unknown[]>;
3
+ export declare function loadSession(dir: string): Promise<ModelMessage[]>;
4
+ export declare function filterOldMedia(messages: ModelMessage[], lastUserIndex: number): ModelMessage[];
5
+ export declare function saveSession(dir: string, messages: (ModelMessage & {
6
+ _meta?: Record<string, unknown>;
7
+ })[]): Promise<void>;
@@ -0,0 +1,102 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { join, dirname, basename } from "node:path";
3
+ function sessionPath(dir) {
4
+ return join(dir, "messages.jsonl");
5
+ }
6
+ export async function resolveRefs(content, attachmentsDir) {
7
+ const resolved = [];
8
+ for (const part of content) {
9
+ if (typeof part !== "object" || part === null) {
10
+ resolved.push(part);
11
+ continue;
12
+ }
13
+ const p = part;
14
+ if (p._ref && (p.type === "image" || p.type === "file")) {
15
+ const filename = basename(p._ref);
16
+ const filePath = join(attachmentsDir, filename);
17
+ try {
18
+ const buffer = await readFile(filePath);
19
+ const base64 = buffer.toString("base64");
20
+ if (p.type === "image") {
21
+ resolved.push({ type: "image", image: base64, mimeType: p.mimeType, _ref: p._ref });
22
+ }
23
+ else {
24
+ resolved.push({ type: "file", data: base64, mimeType: p.mimeType, _ref: p._ref });
25
+ }
26
+ }
27
+ catch {
28
+ resolved.push({ type: "text", text: `[arquivo removido: ${filename}]` });
29
+ }
30
+ }
31
+ else {
32
+ resolved.push(part);
33
+ }
34
+ }
35
+ return resolved;
36
+ }
37
+ export async function loadSession(dir) {
38
+ try {
39
+ const content = await readFile(sessionPath(dir), "utf-8");
40
+ const messages = content
41
+ .split("\n")
42
+ .filter((line) => line.trim())
43
+ .map((line) => {
44
+ const { _meta, ...msg } = JSON.parse(line);
45
+ return msg;
46
+ });
47
+ const attachmentsDir = join(dir, "attachments");
48
+ const result = [];
49
+ for (const msg of messages) {
50
+ if (Array.isArray(msg.content)) {
51
+ const resolvedContent = await resolveRefs(msg.content, attachmentsDir);
52
+ result.push({ ...msg, content: resolvedContent });
53
+ }
54
+ else {
55
+ result.push(msg);
56
+ }
57
+ }
58
+ return result;
59
+ }
60
+ catch {
61
+ return [];
62
+ }
63
+ }
64
+ export function filterOldMedia(messages, lastUserIndex) {
65
+ return messages.map((msg, i) => {
66
+ if (msg.role !== "user" || i === lastUserIndex) {
67
+ return msg;
68
+ }
69
+ if (!Array.isArray(msg.content)) {
70
+ return msg;
71
+ }
72
+ const filtered = msg.content.map((part) => {
73
+ if (typeof part !== "object" || part === null)
74
+ return part;
75
+ const p = part;
76
+ if (p.type === "image") {
77
+ const name = p._ref ?? "imagem";
78
+ return { type: "text", text: `[imagem enviada: ${name}]` };
79
+ }
80
+ if (p.type === "file" && p.data !== undefined) {
81
+ const name = p._ref ?? "arquivo";
82
+ return { type: "text", text: `[arquivo enviado: ${name}]` };
83
+ }
84
+ return part;
85
+ });
86
+ return { ...msg, content: filtered };
87
+ });
88
+ }
89
+ export async function saveSession(dir, messages) {
90
+ const filePath = sessionPath(dir);
91
+ await mkdir(dirname(filePath), { recursive: true });
92
+ const ts = new Date().toISOString();
93
+ const jsonl = messages
94
+ .map((m) => {
95
+ if (!m._meta) {
96
+ return JSON.stringify({ ...m, _meta: { ts } });
97
+ }
98
+ return JSON.stringify(m);
99
+ })
100
+ .join("\n") + "\n";
101
+ await writeFile(filePath, jsonl, "utf-8");
102
+ }
@@ -0,0 +1,18 @@
1
+ import type { z } from "zod";
2
+ import type { createAiProviderRegistry } from "./providers.js";
3
+ export interface AiObjectOptions<T extends z.ZodType> {
4
+ model: string;
5
+ apiKey: string;
6
+ /** Provider name (e.g. "openrouter", "groq"). Default: "openrouter" */
7
+ provider?: string;
8
+ /** Base URL override for the provider */
9
+ baseURL?: string;
10
+ schema: T;
11
+ system?: string;
12
+ prompt: string;
13
+ maxTokens?: number;
14
+ /** Provider registry para reuso. Se nao fornecido, cria um internamente (backward compat). */
15
+ providers?: ReturnType<typeof createAiProviderRegistry>;
16
+ }
17
+ export declare function aiGenerateObject<T extends z.ZodType>(options: AiObjectOptions<T>): Promise<z.infer<T>>;
18
+ export declare function aiStreamObject<T extends z.ZodType>(options: AiObjectOptions<T>): AsyncGenerator<Partial<z.infer<T>>>;
@@ -0,0 +1,38 @@
1
+ import { generateText, streamObject, Output } from "ai";
2
+ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
3
+ export async function aiGenerateObject(options) {
4
+ const model = options.providers
5
+ ? options.providers.model(options.model, options.provider)
6
+ : createOpenAICompatible({
7
+ name: options.provider ?? "openrouter",
8
+ baseURL: options.baseURL ?? "https://openrouter.ai/api/v1",
9
+ apiKey: options.apiKey,
10
+ })(options.model);
11
+ const result = await generateText({
12
+ model,
13
+ output: Output.object({ schema: options.schema }),
14
+ system: options.system,
15
+ prompt: options.prompt,
16
+ maxOutputTokens: options.maxTokens,
17
+ });
18
+ return result.output;
19
+ }
20
+ export async function* aiStreamObject(options) {
21
+ const model = options.providers
22
+ ? options.providers.model(options.model, options.provider)
23
+ : createOpenAICompatible({
24
+ name: options.provider ?? "openrouter",
25
+ baseURL: options.baseURL ?? "https://openrouter.ai/api/v1",
26
+ apiKey: options.apiKey,
27
+ })(options.model);
28
+ const result = streamObject({
29
+ model,
30
+ schema: options.schema,
31
+ system: options.system,
32
+ prompt: options.prompt,
33
+ maxOutputTokens: options.maxTokens,
34
+ });
35
+ for await (const partial of result.partialObjectStream) {
36
+ yield partial;
37
+ }
38
+ }
@@ -0,0 +1,21 @@
1
+ import type { LanguageModel } from "ai";
2
+ import type { LanguageModelV3ToolCall } from "@ai-sdk/provider";
3
+ export interface RepairContext {
4
+ model: LanguageModel;
5
+ maxAttempts: number;
6
+ }
7
+ /**
8
+ * Cria um handler de reparo que pede ao modelo para corrigir a tool call.
9
+ * Primeiro tenta corrigir o nome da tool (case mismatch), depois os args.
10
+ * Tenta N vezes. Se todas falharem, retorna null (deixa o erro original propagar).
11
+ */
12
+ export declare function createToolCallRepairHandler(ctx: RepairContext): (options: {
13
+ toolCall: LanguageModelV3ToolCall;
14
+ tools: Record<string, unknown>;
15
+ inputSchema: (opts: {
16
+ toolName: string;
17
+ }) => unknown;
18
+ error: Error;
19
+ system?: unknown;
20
+ messages?: unknown;
21
+ }) => Promise<LanguageModelV3ToolCall | null>;
@@ -0,0 +1,72 @@
1
+ import { generateText } from "ai";
2
+ /**
3
+ * Try to fix tool name by case-insensitive matching against available tools.
4
+ * Returns the correct name if found, or null.
5
+ */
6
+ function fixToolName(toolName, tools) {
7
+ if (toolName in tools)
8
+ return toolName; // already correct
9
+ const lower = toolName.toLowerCase();
10
+ for (const name of Object.keys(tools)) {
11
+ if (name.toLowerCase() === lower)
12
+ return name;
13
+ }
14
+ return null;
15
+ }
16
+ /**
17
+ * Cria um handler de reparo que pede ao modelo para corrigir a tool call.
18
+ * Primeiro tenta corrigir o nome da tool (case mismatch), depois os args.
19
+ * Tenta N vezes. Se todas falharem, retorna null (deixa o erro original propagar).
20
+ */
21
+ export function createToolCallRepairHandler(ctx) {
22
+ const attempts = new Map();
23
+ return async (options) => {
24
+ const { toolCall, tools, inputSchema, error } = options;
25
+ // Fix tool name case mismatch (e.g. "Email_send" → "email_send")
26
+ const correctedName = fixToolName(toolCall.toolName, tools);
27
+ if (correctedName && correctedName !== toolCall.toolName) {
28
+ return {
29
+ type: "tool-call",
30
+ toolCallId: toolCall.toolCallId,
31
+ toolName: correctedName,
32
+ input: toolCall.input,
33
+ };
34
+ }
35
+ const key = `${toolCall.toolName}:${toolCall.input}`;
36
+ const current = attempts.get(key) ?? 0;
37
+ if (current >= ctx.maxAttempts) {
38
+ return null; // desiste — erro original propaga
39
+ }
40
+ attempts.set(key, current + 1);
41
+ // If tool name is completely wrong, can't repair args
42
+ if (!correctedName)
43
+ return null;
44
+ try {
45
+ const schema = await Promise.resolve(inputSchema({ toolName: toolCall.toolName }));
46
+ const result = await generateText({
47
+ model: ctx.model,
48
+ system: [
49
+ "You generated an invalid tool call. Fix the JSON arguments to match the schema.",
50
+ "Return ONLY the corrected JSON object — no explanation, no markdown.",
51
+ ].join("\n"),
52
+ prompt: [
53
+ `Tool: ${toolCall.toolName}`,
54
+ `Schema: ${JSON.stringify(schema)}`,
55
+ `Invalid args: ${toolCall.input}`,
56
+ `Error: ${error.message}`,
57
+ ].join("\n"),
58
+ maxOutputTokens: 1000,
59
+ });
60
+ const repaired = (result.text ?? toolCall.input).trim();
61
+ return {
62
+ type: "tool-call",
63
+ toolCallId: toolCall.toolCallId,
64
+ toolName: toolCall.toolName,
65
+ input: repaired,
66
+ };
67
+ }
68
+ catch {
69
+ return null; // reparo falhou — erro original propaga
70
+ }
71
+ };
72
+ }
@@ -0,0 +1,4 @@
1
+ export declare const apiSpecTool: import("ai").Tool<{
2
+ url: string;
3
+ format: "auto" | "openapi";
4
+ }, string>;