@avocadostudio-ai/orchestrator-core 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 (196) hide show
  1. package/LICENSE +201 -0
  2. package/dist/agent/agent-context.d.ts +19 -0
  3. package/dist/agent/agent-context.js +67 -0
  4. package/dist/agent/agent-logger.d.ts +5 -0
  5. package/dist/agent/agent-logger.js +22 -0
  6. package/dist/agent/agent-loop-openai.d.ts +8 -0
  7. package/dist/agent/agent-loop-openai.js +172 -0
  8. package/dist/agent/agent-loop.d.ts +56 -0
  9. package/dist/agent/agent-loop.js +167 -0
  10. package/dist/agent/agent-provider.d.ts +28 -0
  11. package/dist/agent/agent-provider.js +63 -0
  12. package/dist/agent/agent-tools.d.ts +28 -0
  13. package/dist/agent/agent-tools.js +899 -0
  14. package/dist/agent/context/editing-guidelines.md +46 -0
  15. package/dist/agent/context/role.md +39 -0
  16. package/dist/agent/integration-prompt.d.ts +9 -0
  17. package/dist/agent/integration-prompt.js +154 -0
  18. package/dist/agent/sites-agent-context.d.ts +12 -0
  19. package/dist/agent/sites-agent-context.js +316 -0
  20. package/dist/agent/sites-agent-shared.d.ts +161 -0
  21. package/dist/agent/sites-agent-shared.js +1101 -0
  22. package/dist/agent/sites-agent-tools.d.ts +18 -0
  23. package/dist/agent/sites-agent-tools.js +1227 -0
  24. package/dist/chat/anthropic-cache.d.ts +20 -0
  25. package/dist/chat/anthropic-cache.js +54 -0
  26. package/dist/chat/anthropic-planner.d.ts +98 -0
  27. package/dist/chat/anthropic-planner.js +1012 -0
  28. package/dist/chat/changelog-coverage-validator.d.ts +37 -0
  29. package/dist/chat/changelog-coverage-validator.js +215 -0
  30. package/dist/chat/chat-pipeline-context.d.ts +211 -0
  31. package/dist/chat/chat-pipeline-context.js +249 -0
  32. package/dist/chat/chat-pipeline-deterministic.d.ts +61 -0
  33. package/dist/chat/chat-pipeline-deterministic.js +407 -0
  34. package/dist/chat/chat-pipeline-image.d.ts +86 -0
  35. package/dist/chat/chat-pipeline-image.js +897 -0
  36. package/dist/chat/chat-pipeline-shared.d.ts +69 -0
  37. package/dist/chat/chat-pipeline-shared.js +212 -0
  38. package/dist/chat/chat-pipeline-translation.d.ts +27 -0
  39. package/dist/chat/chat-pipeline-translation.js +417 -0
  40. package/dist/chat/chat-pipeline-ui.d.ts +14 -0
  41. package/dist/chat/chat-pipeline-ui.js +244 -0
  42. package/dist/chat/chat-pipeline.d.ts +99 -0
  43. package/dist/chat/chat-pipeline.js +3999 -0
  44. package/dist/chat/decomposer.d.ts +21 -0
  45. package/dist/chat/decomposer.js +65 -0
  46. package/dist/chat/gemini-planner.d.ts +70 -0
  47. package/dist/chat/gemini-planner.js +541 -0
  48. package/dist/chat/hallucination-validator.d.ts +36 -0
  49. package/dist/chat/hallucination-validator.js +110 -0
  50. package/dist/chat/locale-strings.d.ts +47 -0
  51. package/dist/chat/locale-strings.js +100 -0
  52. package/dist/chat/plan-json-schema.d.ts +133 -0
  53. package/dist/chat/plan-json-schema.js +112 -0
  54. package/dist/chat/planner-types.d.ts +120 -0
  55. package/dist/chat/planner-types.js +66 -0
  56. package/dist/chat/planner.d.ts +148 -0
  57. package/dist/chat/planner.js +1361 -0
  58. package/dist/chat/prompts.d.ts +67 -0
  59. package/dist/chat/prompts.js +356 -0
  60. package/dist/chat/provider-routing.d.ts +14 -0
  61. package/dist/chat/provider-routing.js +27 -0
  62. package/dist/chat/variation-pipeline.d.ts +135 -0
  63. package/dist/chat/variation-pipeline.js +837 -0
  64. package/dist/chat/vision-alt-generator.d.ts +35 -0
  65. package/dist/chat/vision-alt-generator.js +152 -0
  66. package/dist/cms/adapter.d.ts +62 -0
  67. package/dist/cms/adapter.js +1 -0
  68. package/dist/cms/bootstrap.d.ts +17 -0
  69. package/dist/cms/bootstrap.js +85 -0
  70. package/dist/cms/editor-api-adapter.d.ts +23 -0
  71. package/dist/cms/editor-api-adapter.js +71 -0
  72. package/dist/cms/index.d.ts +4 -0
  73. package/dist/cms/index.js +3 -0
  74. package/dist/cms/json-file-adapter.d.ts +11 -0
  75. package/dist/cms/json-file-adapter.js +62 -0
  76. package/dist/demo-mode.d.ts +59 -0
  77. package/dist/demo-mode.js +201 -0
  78. package/dist/errors.d.ts +67 -0
  79. package/dist/errors.js +129 -0
  80. package/dist/http/chat-stream-resumable.d.ts +108 -0
  81. package/dist/http/chat-stream-resumable.js +290 -0
  82. package/dist/http/chat-stream.d.ts +99 -0
  83. package/dist/http/chat-stream.js +92 -0
  84. package/dist/image/gdrive-client.d.ts +22 -0
  85. package/dist/image/gdrive-client.js +215 -0
  86. package/dist/image/image-helpers.d.ts +95 -0
  87. package/dist/image/image-helpers.js +488 -0
  88. package/dist/index.d.ts +1 -0
  89. package/dist/index.js +1 -0
  90. package/dist/jira/jira-approval.d.ts +22 -0
  91. package/dist/jira/jira-approval.js +51 -0
  92. package/dist/jira/jira-client.d.ts +44 -0
  93. package/dist/jira/jira-client.js +313 -0
  94. package/dist/jira/jira-poller.d.ts +46 -0
  95. package/dist/jira/jira-poller.js +184 -0
  96. package/dist/jira/jira-processor.d.ts +103 -0
  97. package/dist/jira/jira-processor.js +1085 -0
  98. package/dist/jira/jira-types.d.ts +117 -0
  99. package/dist/jira/jira-types.js +38 -0
  100. package/dist/logger.d.ts +12 -0
  101. package/dist/logger.js +28 -0
  102. package/dist/migration/mcp-server-stdio.d.ts +8 -0
  103. package/dist/migration/mcp-server-stdio.js +672 -0
  104. package/dist/migration/migration-prompt.d.ts +7 -0
  105. package/dist/migration/migration-prompt.js +197 -0
  106. package/dist/migration/migration-tools.d.ts +17 -0
  107. package/dist/migration/migration-tools.js +159 -0
  108. package/dist/migration/scrape-cache.d.ts +9 -0
  109. package/dist/migration/scrape-cache.js +19 -0
  110. package/dist/nlp/deterministic-planner-context.d.ts +141 -0
  111. package/dist/nlp/deterministic-planner-context.js +362 -0
  112. package/dist/nlp/deterministic-planner-pages.d.ts +26 -0
  113. package/dist/nlp/deterministic-planner-pages.js +170 -0
  114. package/dist/nlp/deterministic-planner-patches.d.ts +80 -0
  115. package/dist/nlp/deterministic-planner-patches.js +508 -0
  116. package/dist/nlp/deterministic-planner-refs.d.ts +33 -0
  117. package/dist/nlp/deterministic-planner-refs.js +164 -0
  118. package/dist/nlp/deterministic-planner-suggestions.d.ts +49 -0
  119. package/dist/nlp/deterministic-planner-suggestions.js +579 -0
  120. package/dist/nlp/deterministic-planner.d.ts +85 -0
  121. package/dist/nlp/deterministic-planner.js +1631 -0
  122. package/dist/nlp/intent-detection.d.ts +309 -0
  123. package/dist/nlp/intent-detection.js +730 -0
  124. package/dist/nlp/intent-helpers.d.ts +15 -0
  125. package/dist/nlp/intent-helpers.js +243 -0
  126. package/dist/nlp/intent-patterns.d.ts +40 -0
  127. package/dist/nlp/intent-patterns.js +223 -0
  128. package/dist/nlp/plan-normalizer.d.ts +41 -0
  129. package/dist/nlp/plan-normalizer.js +1537 -0
  130. package/dist/ops/destructive-action-gate.d.ts +44 -0
  131. package/dist/ops/destructive-action-gate.js +90 -0
  132. package/dist/ops/ops-engine.d.ts +151 -0
  133. package/dist/ops/ops-engine.js +1394 -0
  134. package/dist/publish/diff-engine.d.ts +18 -0
  135. package/dist/publish/diff-engine.js +305 -0
  136. package/dist/publish/publish-helpers.d.ts +87 -0
  137. package/dist/publish/publish-helpers.js +521 -0
  138. package/dist/publish/publish-target-registry.d.ts +7 -0
  139. package/dist/publish/publish-target-registry.js +61 -0
  140. package/dist/publish/publish-target.d.ts +81 -0
  141. package/dist/publish/publish-target.js +1 -0
  142. package/dist/publish/targets/deploy-hook.d.ts +13 -0
  143. package/dist/publish/targets/deploy-hook.js +123 -0
  144. package/dist/publish/targets/git.d.ts +13 -0
  145. package/dist/publish/targets/git.js +55 -0
  146. package/dist/publish/targets/site-contract.d.ts +19 -0
  147. package/dist/publish/targets/site-contract.js +124 -0
  148. package/dist/state/content-source.d.ts +17 -0
  149. package/dist/state/content-source.js +1 -0
  150. package/dist/state/in-memory-content-source.d.ts +27 -0
  151. package/dist/state/in-memory-content-source.js +51 -0
  152. package/dist/state/session-lock.d.ts +13 -0
  153. package/dist/state/session-lock.js +29 -0
  154. package/dist/state/session-state.d.ts +310 -0
  155. package/dist/state/session-state.js +1083 -0
  156. package/dist/state/sqlite-store-singleton.d.ts +31 -0
  157. package/dist/state/sqlite-store-singleton.js +170 -0
  158. package/dist/state/sqlite-store.d.ts +135 -0
  159. package/dist/state/sqlite-store.js +421 -0
  160. package/dist/telemetry/chat-telemetry.d.ts +105 -0
  161. package/dist/telemetry/chat-telemetry.js +247 -0
  162. package/dist/telemetry/eval-candidate-store.d.ts +50 -0
  163. package/dist/telemetry/eval-candidate-store.js +120 -0
  164. package/dist/telemetry/feedback-store.d.ts +34 -0
  165. package/dist/telemetry/feedback-store.js +76 -0
  166. package/dist/telemetry/jira-telemetry.d.ts +57 -0
  167. package/dist/telemetry/jira-telemetry.js +68 -0
  168. package/dist/telemetry/migration-telemetry.d.ts +35 -0
  169. package/dist/telemetry/migration-telemetry.js +40 -0
  170. package/dist/telemetry/usage.d.ts +24 -0
  171. package/dist/telemetry/usage.js +80 -0
  172. package/dist/tools/builtin-registrations.d.ts +12 -0
  173. package/dist/tools/builtin-registrations.js +33 -0
  174. package/dist/tools/builtins/gdrive-browse.d.ts +3 -0
  175. package/dist/tools/builtins/gdrive-browse.js +68 -0
  176. package/dist/tools/builtins/image-generate.d.ts +3 -0
  177. package/dist/tools/builtins/image-generate.js +211 -0
  178. package/dist/tools/builtins/unsplash-get-by-id.d.ts +23 -0
  179. package/dist/tools/builtins/unsplash-get-by-id.js +119 -0
  180. package/dist/tools/builtins/unsplash-search.d.ts +3 -0
  181. package/dist/tools/builtins/unsplash-search.js +74 -0
  182. package/dist/tools/executor.d.ts +23 -0
  183. package/dist/tools/executor.js +169 -0
  184. package/dist/tools/index.d.ts +5 -0
  185. package/dist/tools/index.js +5 -0
  186. package/dist/tools/registry.d.ts +21 -0
  187. package/dist/tools/registry.js +75 -0
  188. package/dist/tools/runtime.d.ts +27 -0
  189. package/dist/tools/runtime.js +48 -0
  190. package/dist/tools/schema-validator.d.ts +24 -0
  191. package/dist/tools/schema-validator.js +88 -0
  192. package/dist/tools/types.d.ts +86 -0
  193. package/dist/tools/types.js +1 -0
  194. package/dist/variation-images.d.ts +19 -0
  195. package/dist/variation-images.js +12 -0
  196. package/package.json +78 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Agent loop: multi-turn tool-use conversation with an LLM.
3
+ *
4
+ * Dispatches to provider-specific implementations (Anthropic / OpenAI) based on
5
+ * the `provider` field in options (required — routes validate before calling).
6
+ */
7
+ import Anthropic from "@anthropic-ai/sdk";
8
+ import { AGENT_MAX_TOOL_CALLS, AGENT_MAX_TOKENS, shouldUseThinking } from "./agent-provider.js";
9
+ import { runOpenAIAgentLoop } from "./agent-loop-openai.js";
10
+ import { anthropicSystemPromptWithCache, anthropicToolWithCache, ANTHROPIC_FINE_GRAINED_STREAM_HEADERS } from "../chat/anthropic-cache.js";
11
+ export const consoleAgentLogger = {
12
+ info: (obj, msg) => msg ? console.log(msg, obj) : console.log(obj),
13
+ warn: (obj, msg) => msg ? console.warn(msg, obj) : console.warn(obj),
14
+ error: (obj, msg) => msg ? console.error(msg, obj) : console.error(obj),
15
+ };
16
+ /** Provider-agnostic entry point — dispatches to Anthropic or OpenAI loop. */
17
+ export async function* runAgentLoop(options) {
18
+ if (_runAgentLoopOverride) {
19
+ yield* _runAgentLoopOverride(options);
20
+ return;
21
+ }
22
+ if (options.provider === "openai") {
23
+ yield* runOpenAIAgentLoop(options);
24
+ return;
25
+ }
26
+ yield* runAnthropicAgentLoop(options);
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Test injection point (follows setGeneratePlanWithOpenAIForTests pattern)
30
+ // ---------------------------------------------------------------------------
31
+ let _runAgentLoopOverride;
32
+ export function setRunAgentLoopForTests(fn) {
33
+ _runAgentLoopOverride = fn;
34
+ }
35
+ async function* runAnthropicAgentLoop(options) {
36
+ const { apiKey, model, systemPrompt, tools, userMessage, maxToolCalls = AGENT_MAX_TOOL_CALLS, signal, logger, } = options;
37
+ const log = logger ?? consoleAgentLogger;
38
+ const client = new Anthropic({ apiKey });
39
+ // Apply prompt caching to system prompt and the *first* tool. Caching the
40
+ // first tool (rather than rotating to the last) keeps the cached tool prefix
41
+ // stable when callers pass tools in a different order or subset.
42
+ const cachedSystem = anthropicSystemPromptWithCache(systemPrompt);
43
+ const toolDefs = tools.map((t, i) => i === 0 ? anthropicToolWithCache(t.definition) : t.definition);
44
+ const handlerMap = new Map(tools.map((t) => [t.definition.name, t.handler]));
45
+ const messages = [
46
+ { role: "user", content: userMessage },
47
+ ];
48
+ let toolCallCount = 0;
49
+ let fullSummary = "";
50
+ const totalUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationTokens: 0 };
51
+ // Tool-use loop
52
+ while (toolCallCount < maxToolCalls) {
53
+ if (signal?.aborted) {
54
+ yield { type: "error", message: "Canceled" };
55
+ return;
56
+ }
57
+ let response;
58
+ const textParts = [];
59
+ const toolUseBlocks = [];
60
+ try {
61
+ // Enable thinking on first turn only for complex requests
62
+ const useThinking = toolCallCount === 0 && shouldUseThinking(userMessage);
63
+ if (useThinking) {
64
+ log.info(`[agent-loop] Adaptive thinking enabled (effort: high)`);
65
+ }
66
+ log.info(`[agent-loop] Calling Anthropic API (streaming), turn ${toolCallCount + 1}`);
67
+ // No `temperature`: it is rejected (400) on Opus 4.8 / Sonnet 5. Adaptive
68
+ // thinking + output_config.effort replaces the legacy budget_tokens shape.
69
+ // Effort is capped at "high" (not "max") to stay cost-efficient on the
70
+ // token-heavier agentic loop; thinking blocks are not surfaced, so the
71
+ // default "omitted" display is fine.
72
+ const stream = client.messages.stream({
73
+ model,
74
+ max_tokens: AGENT_MAX_TOKENS,
75
+ system: cachedSystem,
76
+ tools: toolDefs,
77
+ messages,
78
+ ...(useThinking ? { thinking: { type: "adaptive" }, output_config: { effort: "high" } } : {}),
79
+ }, { headers: ANTHROPIC_FINE_GRAINED_STREAM_HEADERS });
80
+ const emittedToolStarts = new Set();
81
+ for await (const event of stream) {
82
+ // Skip thinking blocks (internal reasoning — not shown to user)
83
+ if (event.type === "content_block_start" && event.content_block?.type === "thinking")
84
+ continue;
85
+ if (event.type === "content_block_delta" && event.delta?.type === "thinking_delta")
86
+ continue;
87
+ if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
88
+ const { id, name } = event.content_block;
89
+ if (!emittedToolStarts.has(id)) {
90
+ emittedToolStarts.add(id);
91
+ yield { type: "tool_start", toolName: name, toolUseId: id };
92
+ }
93
+ }
94
+ if (event.type === "content_block_delta" && event.delta?.type === "text_delta") {
95
+ const { text } = event.delta;
96
+ textParts.push(text);
97
+ yield { type: "text_delta", text };
98
+ }
99
+ }
100
+ response = await stream.finalMessage();
101
+ for (const block of response.content) {
102
+ if (block.type === "tool_use") {
103
+ toolUseBlocks.push({ id: block.id, name: block.name, input: block.input });
104
+ // Fallback for non-fine-grained: emit tool_start if not already emitted
105
+ if (!emittedToolStarts.has(block.id)) {
106
+ yield { type: "tool_start", toolName: block.name, toolUseId: block.id };
107
+ }
108
+ }
109
+ else if (block.type === "text" && !textParts.length) {
110
+ textParts.push(block.text);
111
+ }
112
+ }
113
+ // Accumulate token usage
114
+ const u = response.usage;
115
+ if (u) {
116
+ totalUsage.inputTokens += u.input_tokens ?? 0;
117
+ totalUsage.outputTokens += u.output_tokens ?? 0;
118
+ totalUsage.cacheReadTokens += u.cache_read_input_tokens ?? 0;
119
+ totalUsage.cacheCreationTokens += u.cache_creation_input_tokens ?? 0;
120
+ }
121
+ log.info(`[agent-loop] Stream complete, stop_reason: ${response.stop_reason} content blocks: ${response.content.length} tools: ${toolUseBlocks.map(b => b.name).join(",")}`);
122
+ }
123
+ catch (err) {
124
+ const msg = err instanceof Error ? err.message : String(err);
125
+ log.error(`[agent-loop] API error: ${msg}`);
126
+ yield { type: "error", message: msg };
127
+ return;
128
+ }
129
+ messages.push({ role: "assistant", content: response.content });
130
+ if (response.stop_reason === "end_turn" || toolUseBlocks.length === 0) {
131
+ fullSummary += textParts.join("");
132
+ yield { type: "done", summary: fullSummary, toolCallCount, usage: totalUsage };
133
+ return;
134
+ }
135
+ // Execute tool calls
136
+ const toolResults = [];
137
+ for (const toolUse of toolUseBlocks) {
138
+ toolCallCount++;
139
+ log.info(`[agent-loop] Executing tool: ${toolUse.name} input: ${JSON.stringify(toolUse.input).slice(0, 200)}`);
140
+ const handler = handlerMap.get(toolUse.name);
141
+ if (!handler) {
142
+ const errorResult = `Unknown tool: ${toolUse.name}`;
143
+ toolResults.push({
144
+ type: "tool_result",
145
+ tool_use_id: toolUse.id,
146
+ content: errorResult,
147
+ is_error: true,
148
+ });
149
+ yield { type: "tool_done", toolName: toolUse.name, toolUseId: toolUse.id, result: errorResult, isError: true };
150
+ continue;
151
+ }
152
+ const { result, isError } = await handler(toolUse.input);
153
+ toolResults.push({
154
+ type: "tool_result",
155
+ tool_use_id: toolUse.id,
156
+ content: result,
157
+ ...(isError ? { is_error: true } : {}),
158
+ });
159
+ yield { type: "tool_done", toolName: toolUse.name, toolUseId: toolUse.id, result, isError };
160
+ }
161
+ if (textParts.length > 0) {
162
+ fullSummary += textParts.join("");
163
+ }
164
+ messages.push({ role: "user", content: toolResults });
165
+ }
166
+ yield { type: "done", summary: `Completed with ${toolCallCount} tool calls (limit reached).`, toolCallCount, usage: totalUsage };
167
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Agent provider detection and configuration.
3
+ * Strict prefix matching — no async probing, no fallback.
4
+ *
5
+ * All AGENT_* env vars configure agent mode specifically (user-supplied API key).
6
+ * They do NOT affect the regular chat pipeline.
7
+ */
8
+ import type { AIProvider } from "../state/session-state.ts";
9
+ /** Providers currently supported in agent mode. */
10
+ export type AgentProvider = Extract<AIProvider, "anthropic" | "openai">;
11
+ /**
12
+ * Detect AI provider from API key prefix.
13
+ * Returns null for unrecognized formats — caller should reject with a descriptive error.
14
+ */
15
+ export declare function detectProviderFromKey(key: string): AgentProvider | null;
16
+ /** Max tool calls before the agent loop stops. */
17
+ export declare const AGENT_MAX_TOOL_CALLS: number;
18
+ /** Max tokens for agent responses. Higher allows longer reasoning and multi-step summaries. */
19
+ export declare const AGENT_MAX_TOKENS: number;
20
+ /** Adaptive-thinking gate for agent mode. 0 = thinking disabled entirely. */
21
+ export declare const AGENT_THINKING_BUDGET: number;
22
+ /** Resolve a concrete model ID for the given provider, falling back to provider default. */
23
+ export declare function resolveAgentModel(provider: AgentProvider, requestedModel?: string): string;
24
+ /**
25
+ * Detect whether a user message is complex enough to benefit from extended thinking.
26
+ * Returns true for multi-step structural edits, false for simple field updates.
27
+ */
28
+ export declare function shouldUseThinking(message: string): boolean;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Agent provider detection and configuration.
3
+ * Strict prefix matching — no async probing, no fallback.
4
+ *
5
+ * All AGENT_* env vars configure agent mode specifically (user-supplied API key).
6
+ * They do NOT affect the regular chat pipeline.
7
+ */
8
+ /**
9
+ * Detect AI provider from API key prefix.
10
+ * Returns null for unrecognized formats — caller should reject with a descriptive error.
11
+ */
12
+ export function detectProviderFromKey(key) {
13
+ if (key.startsWith("sk-ant-"))
14
+ return "anthropic";
15
+ if (key.startsWith("sk-"))
16
+ return "openai";
17
+ return null;
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // Agent mode defaults (env-configurable)
21
+ // ---------------------------------------------------------------------------
22
+ const DEFAULT_MODELS = {
23
+ anthropic: process.env.AGENT_ANTHROPIC_MODEL ?? "claude-sonnet-5",
24
+ openai: process.env.AGENT_OPENAI_MODEL ?? "gpt-4o",
25
+ };
26
+ /** Max tool calls before the agent loop stops. */
27
+ export const AGENT_MAX_TOOL_CALLS = Number(process.env.AGENT_MAX_TOOL_CALLS) || 20;
28
+ /** Max tokens for agent responses. Higher allows longer reasoning and multi-step summaries. */
29
+ export const AGENT_MAX_TOKENS = Number(process.env.AGENT_MAX_TOKENS) || 16384;
30
+ // NOTE: A former AGENT_TEMPERATURE knob was removed — `temperature` is rejected
31
+ // (400) on Opus 4.8 / Sonnet 5, and the OpenAI agent path never consumed it.
32
+ // Steer agent behavior via prompting and adaptive-thinking effort instead.
33
+ /** Adaptive-thinking gate for agent mode. 0 = thinking disabled entirely. */
34
+ export const AGENT_THINKING_BUDGET = Number(process.env.AGENT_THINKING_BUDGET) || 10000;
35
+ /** Resolve a concrete model ID for the given provider, falling back to provider default. */
36
+ export function resolveAgentModel(provider, requestedModel) {
37
+ if (requestedModel?.trim())
38
+ return requestedModel.trim();
39
+ return DEFAULT_MODELS[provider];
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Complexity detection for extended thinking
43
+ // ---------------------------------------------------------------------------
44
+ const STRUCTURAL_KEYWORDS = /\b(redesign|restructure|rewrite\s+all|create\s+(?:a\s+)?(?:new\s+)?page|build\s+(?:a\s+)?(?:new\s+)?page|add\s+\w+\s+sections?|overhaul|rework|redo\s+the)\b/i;
45
+ const MULTI_BLOCK_HINTS = /\b(hero\s+and\s+\w+|all\s+(?:the\s+)?(?:sections?|blocks?|pages?)|every\s+(?:section|block|page)|each\s+(?:section|block|page)|multiple\s+(?:sections?|blocks?)|across\s+(?:the\s+)?(?:site|page))\b/i;
46
+ const STRUCTURAL_VERBS = /\b(add|create|move|reorder|replace|remove|duplicate|insert)\b/i;
47
+ /**
48
+ * Detect whether a user message is complex enough to benefit from extended thinking.
49
+ * Returns true for multi-step structural edits, false for simple field updates.
50
+ */
51
+ export function shouldUseThinking(message) {
52
+ if (AGENT_THINKING_BUDGET <= 0)
53
+ return false;
54
+ // Extract just the user request part (after "User request:" if present)
55
+ const userPart = message.includes("User request:") ? message.split("User request:").pop() : message;
56
+ if (STRUCTURAL_KEYWORDS.test(userPart))
57
+ return true;
58
+ if (MULTI_BLOCK_HINTS.test(userPart))
59
+ return true;
60
+ if (userPart.length > 120 && STRUCTURAL_VERBS.test(userPart))
61
+ return true;
62
+ return false;
63
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Agent tool definitions for Anthropic tool-use.
3
+ * These are the tools Claude can call to modify the website.
4
+ *
5
+ * Three categories:
6
+ * 1. Compound tools (edit_page, batch_update_props, add_block_with_content)
7
+ * 2. Atomic tools (remove_block, move_block, create_page, etc.)
8
+ * 3. Read-only context tools (get_page, list_pages, get_block_schema)
9
+ */
10
+ import type Anthropic from "@anthropic-ai/sdk";
11
+ import { type BlockManifest } from "@avocadostudio-ai/shared";
12
+ import { type AgentLogger } from "./agent-loop.ts";
13
+ type ToolHandler = (input: Record<string, unknown>) => Promise<{
14
+ result: string;
15
+ isError?: boolean;
16
+ }>;
17
+ export type AgentTool = {
18
+ definition: Anthropic.Messages.Tool;
19
+ handler: ToolHandler;
20
+ };
21
+ /**
22
+ * Create all agent tools bound to a specific session.
23
+ */
24
+ export declare function createAgentTools(session: string, options?: {
25
+ manifest?: BlockManifest;
26
+ logger?: AgentLogger;
27
+ }): AgentTool[];
28
+ export {};