@mastra/code-sdk 1.4.1-alpha.2 → 1.5.0-alpha.7

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 (43) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/dist/agents/context-audit.d.ts +84 -0
  3. package/dist/agents/context-audit.d.ts.map +1 -0
  4. package/dist/agents/context-audit.js +118 -0
  5. package/dist/agents/context-audit.js.map +1 -0
  6. package/dist/agents/instructions.d.ts +12 -1
  7. package/dist/agents/instructions.d.ts.map +1 -1
  8. package/dist/agents/instructions.js +23 -5
  9. package/dist/agents/instructions.js.map +1 -1
  10. package/dist/agents/model.d.ts +11 -4
  11. package/dist/agents/model.d.ts.map +1 -1
  12. package/dist/agents/model.js +2 -1
  13. package/dist/agents/model.js.map +1 -1
  14. package/dist/agents/prompts/agent-instructions.d.ts +9 -0
  15. package/dist/agents/prompts/agent-instructions.d.ts.map +1 -1
  16. package/dist/agents/prompts/agent-instructions.js +14 -4
  17. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  18. package/dist/agents/prompts/index.d.ts +28 -0
  19. package/dist/agents/prompts/index.d.ts.map +1 -1
  20. package/dist/agents/prompts/index.js +49 -7
  21. package/dist/agents/prompts/index.js.map +1 -1
  22. package/dist/agents/tools.js +1 -1
  23. package/dist/agents/workspace.d.ts.map +1 -1
  24. package/dist/agents/workspace.js +12 -9
  25. package/dist/agents/workspace.js.map +1 -1
  26. package/dist/onboarding/settings.d.ts +9 -7
  27. package/dist/onboarding/settings.d.ts.map +1 -1
  28. package/dist/onboarding/settings.js +27 -25
  29. package/dist/onboarding/settings.js.map +1 -1
  30. package/dist/providers/openai-codex.d.ts +3 -4
  31. package/dist/providers/openai-codex.d.ts.map +1 -1
  32. package/dist/providers/openai-codex.js +1 -9
  33. package/dist/providers/openai-codex.js.map +1 -1
  34. package/dist/schema.d.ts +4 -3
  35. package/dist/schema.d.ts.map +1 -1
  36. package/dist/schema.js +2 -8
  37. package/dist/schema.js.map +1 -1
  38. package/dist/thinking.d.ts +33 -0
  39. package/dist/thinking.d.ts.map +1 -0
  40. package/dist/thinking.js +58 -0
  41. package/dist/thinking.js.map +1 -0
  42. package/dist/workflows/register-primitives.js +1 -1
  43. package/package.json +10 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,77 @@
1
1
  # @mastra/code-sdk
2
2
 
3
+ ## 1.5.0-alpha.7
4
+
5
+ ### Minor Changes
6
+
7
+ - Added browser-safe thinking command helpers so Mastra Code interfaces can share command parsing, model capabilities, and default resolution. ([#22198](https://github.com/mastra-ai/mastra/pull/22198))
8
+
9
+ ```ts
10
+ import { parseThinkCommand, resolveDefaultThinkingLevel } from '@mastra/code-sdk/thinking';
11
+
12
+ const action = parseThinkCommand('high');
13
+ const fallback = resolveDefaultThinkingLevel({ globalDefault: 'medium', modeDefaults: { plan: 'high' } }, 'plan');
14
+ ```
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [[`db6940e`](https://github.com/mastra-ai/mastra/commit/db6940ea63b76df2bc0a7c105a493342b9eaf0ec), [`ae8790c`](https://github.com/mastra-ai/mastra/commit/ae8790c4bfaa088d2ab279d1dcc06f326b9fd109), [`dfb7efa`](https://github.com/mastra-ai/mastra/commit/dfb7efa19e348b5a788be2d954362cbae12379d6), [`ee0c1a0`](https://github.com/mastra-ai/mastra/commit/ee0c1a097de3acebe7dfc8c136479d4cb5b5b451), [`befbfc2`](https://github.com/mastra-ai/mastra/commit/befbfc260d5ec5ece7cdb65a80e94292f428d4c9), [`04a815f`](https://github.com/mastra-ai/mastra/commit/04a815fc8971d29e97fcdcc5008a1eb472fc00ff), [`db6940e`](https://github.com/mastra-ai/mastra/commit/db6940ea63b76df2bc0a7c105a493342b9eaf0ec), [`cced745`](https://github.com/mastra-ai/mastra/commit/cced745a056ec2225c5bc702e32d848847aa8b65)]:
19
+ - @mastra/libsql@1.22.0-alpha.1
20
+ - @mastra/core@1.62.0-alpha.7
21
+ - @mastra/mcp@1.17.2-alpha.2
22
+ - @mastra/memory@1.28.0-alpha.2
23
+
24
+ ## 1.5.0-alpha.6
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [[`c8e4cea`](https://github.com/mastra-ai/mastra/commit/c8e4ceac9a390d78c8327dff3cdb2861dd71957f), [`ed01e9a`](https://github.com/mastra-ai/mastra/commit/ed01e9a807514a904374bf687a7b8f18750f6f78), [`a981e66`](https://github.com/mastra-ai/mastra/commit/a981e662ed8fc476292375d135cb14a2681efedf), [`ae2dc20`](https://github.com/mastra-ai/mastra/commit/ae2dc201dbb48466c3cf77e3d4ef04826132b2db), [`4e9a228`](https://github.com/mastra-ai/mastra/commit/4e9a2283d5fd6ed1b70a2751eb3dc2cbf82ada20), [`997cf5b`](https://github.com/mastra-ai/mastra/commit/997cf5bb3fc600b30aa20e048b663e48e0e1305a), [`63041eb`](https://github.com/mastra-ai/mastra/commit/63041eb4c50b520a0a80e03d4cd6ea99f67715a0)]:
29
+ - @mastra/core@1.62.0-alpha.6
30
+ - @mastra/pg@1.22.0-alpha.3
31
+ - @mastra/mcp@1.17.2-alpha.1
32
+
33
+ ## 1.5.0-alpha.5
34
+
35
+ ### Patch Changes
36
+
37
+ - Add a `/context` command (alias `/ctx`) to Mastra Code that reports what is occupying the context window. ([#22131](https://github.com/mastra-ai/mastra/pull/22131))
38
+
39
+ The report separates the startup context — system prompt, AGENTS.md/CLAUDE.md instructions with their source paths, the skills catalog, and MCP tool definitions rolled up per server — from context that accumulates during the session, namely the conversation itself and any observation memory injected into it. Each line carries an estimated token count and its share of the audited total, so it is possible to see which server, instruction file, or skill set is worth pruning.
40
+
41
+ The audit reports only sizes and labels, never the audited content, and is printed to the terminal without being added to the conversation, so running it does not enlarge the context it describes.
42
+
43
+ To support exact measurement, `@mastra/core` now exports `formatSkillsCatalog`, the pure formatter behind the skills processor's `<available_skills>` block, and `@mastra/code-sdk` exposes the assembled system prompt as labeled sections.
44
+
45
+ - Updated dependencies [[`65edab1`](https://github.com/mastra-ai/mastra/commit/65edab1c233d17b8f163bad12fca410d0e6f16b1), [`ab20a38`](https://github.com/mastra-ai/mastra/commit/ab20a38d0275f8d85e0f3833bd87ef487bcc609f), [`dbbfeb8`](https://github.com/mastra-ai/mastra/commit/dbbfeb85ec949dc9ebc0755e1ad262e4f5eba8db), [`3cc9d00`](https://github.com/mastra-ai/mastra/commit/3cc9d00b2b4333e0377a5e9df5eff92c17ce7630), [`733a537`](https://github.com/mastra-ai/mastra/commit/733a537489a858b5880b2e98809334fba895a221), [`d55807c`](https://github.com/mastra-ai/mastra/commit/d55807cb9f080f3f5d1db06aca02b8fe0992507e), [`9207dfa`](https://github.com/mastra-ai/mastra/commit/9207dfab8062e5fc68b751684797ff86fe0b4e70), [`12c61d2`](https://github.com/mastra-ai/mastra/commit/12c61d280c8cb208bc3c8dbcbe5dcc60cf9d1cd0), [`9a12ef3`](https://github.com/mastra-ai/mastra/commit/9a12ef3fccf3f4186db0f294f4ee1f02cf4d8db2)]:
46
+ - @mastra/core@1.62.0-alpha.5
47
+ - @mastra/memory@1.28.0-alpha.1
48
+
49
+ ## 1.5.0-alpha.4
50
+
51
+ ### Patch Changes
52
+
53
+ - Updated dependencies [[`79f04a7`](https://github.com/mastra-ai/mastra/commit/79f04a7f6c6829da541139f638f2f1d267916e08), [`fd4d5fe`](https://github.com/mastra-ai/mastra/commit/fd4d5fe4f943699b85db5e74404f190d5a6b8c2a), [`f9172b3`](https://github.com/mastra-ai/mastra/commit/f9172b35de085f9101348eeb60d7d4712505ed8f), [`f591643`](https://github.com/mastra-ai/mastra/commit/f591643becdf0be9bddce6ba1748e64bc30d77f1), [`b1ad324`](https://github.com/mastra-ai/mastra/commit/b1ad324d657f3544b0701332aef7eb10e9a36258), [`61c566d`](https://github.com/mastra-ai/mastra/commit/61c566dd2f2cde2b23ed8f139924e530d4202214)]:
54
+ - @mastra/core@1.62.0-alpha.4
55
+ - @mastra/pg@1.22.0-alpha.2
56
+
57
+ ## 1.5.0-alpha.3
58
+
59
+ ### Minor Changes
60
+
61
+ - Made language-server (LSP) support opt-in in Mastra Code. By default Mastra Code no longer checks for LSP dependencies, starts language servers, or offers the lsp_inspect tool to the agent. Turn it on by adding "lsp": true (or an LSP config object) to your settings.json; "lsp": false is now also accepted and preserved. ([#22126](https://github.com/mastra-ai/mastra/pull/22126))
62
+
63
+ ### Patch Changes
64
+
65
+ - Workspace no longer registers the lsp_inspect tool when LSP is not active, so agents are only offered the tool when it can actually run. ([#22126](https://github.com/mastra-ai/mastra/pull/22126))
66
+
67
+ - Updated dependencies [[`c5eaec5`](https://github.com/mastra-ai/mastra/commit/c5eaec5a860d80d0e3805e67db0414b87ac8cbed), [`2c85f42`](https://github.com/mastra-ai/mastra/commit/2c85f428e04ccd63ea31a7ec80b5b327afdad555), [`11bbeb9`](https://github.com/mastra-ai/mastra/commit/11bbeb9b108ef2264e05acefc6dafb9cbb342921), [`1a485f3`](https://github.com/mastra-ai/mastra/commit/1a485f3538f5ec64d58bd8b5e1e99de0c695c87b), [`0d37487`](https://github.com/mastra-ai/mastra/commit/0d37487d9f349388a3f1cef6a536cf9dcc4b6273), [`8661d7d`](https://github.com/mastra-ai/mastra/commit/8661d7d7179f0a024456aabdd8679bcecd09ac28), [`575e343`](https://github.com/mastra-ai/mastra/commit/575e343900451021d96110916497d334af7bc252), [`8661d7d`](https://github.com/mastra-ai/mastra/commit/8661d7d7179f0a024456aabdd8679bcecd09ac28), [`cacb839`](https://github.com/mastra-ai/mastra/commit/cacb8392d9e74189b56d857290b0615f98a2683d), [`b47b26e`](https://github.com/mastra-ai/mastra/commit/b47b26e6fe95cb8a3482be2c5e52de157fe59d0b), [`0d37487`](https://github.com/mastra-ai/mastra/commit/0d37487d9f349388a3f1cef6a536cf9dcc4b6273), [`8661d7d`](https://github.com/mastra-ai/mastra/commit/8661d7d7179f0a024456aabdd8679bcecd09ac28), [`13c2f97`](https://github.com/mastra-ai/mastra/commit/13c2f979a63ee441834ad0d947b40a82010afb59), [`9a3d352`](https://github.com/mastra-ai/mastra/commit/9a3d352a5ba0c2a9e4f7a9cc4f028a393bc74306), [`c46eb09`](https://github.com/mastra-ai/mastra/commit/c46eb09ce4987509af57a0ac582c61241a6dd2f1), [`30ed33e`](https://github.com/mastra-ai/mastra/commit/30ed33ee14084a26019aba15fceadda6d6ddefaf), [`91ad69d`](https://github.com/mastra-ai/mastra/commit/91ad69d64994c89199b0c55399e64ed91c61df2f), [`c4e2364`](https://github.com/mastra-ai/mastra/commit/c4e2364742bc37beebfa995db2d42efce6cfc7b8), [`8dc408d`](https://github.com/mastra-ai/mastra/commit/8dc408d34438f9e13297f792c11a5cfd6cf952e1), [`c92def1`](https://github.com/mastra-ai/mastra/commit/c92def10a13c822972c96f0a4ca6ffc1f4258aed), [`c5eaec5`](https://github.com/mastra-ai/mastra/commit/c5eaec5a860d80d0e3805e67db0414b87ac8cbed), [`e66b2ba`](https://github.com/mastra-ai/mastra/commit/e66b2ba100db63eaeab6e21e1ea34b113f2ec781)]:
68
+ - @mastra/pg@1.22.0-alpha.1
69
+ - @mastra/libsql@1.22.0-alpha.0
70
+ - @mastra/core@1.62.0-alpha.3
71
+ - @mastra/observability@1.17.2-alpha.1
72
+ - @mastra/memory@1.27.1-alpha.0
73
+ - @mastra/mcp@1.17.2-alpha.0
74
+
3
75
  ## 1.4.1-alpha.2
4
76
 
5
77
  ### Patch Changes
@@ -0,0 +1,84 @@
1
+ import type { PromptSection } from './prompts/index.js';
2
+ /** A single measured contributor to the context window. */
3
+ export interface ContextAuditEntry {
4
+ id: string;
5
+ label: string;
6
+ /** Provenance: file path, server name, model id — whatever identifies the source. */
7
+ detail?: string;
8
+ tokens: number;
9
+ characters: number;
10
+ /** Share of the audit total, 0-100. */
11
+ percent: number;
12
+ }
13
+ /** A category of contributors (e.g. all agent instruction files). */
14
+ export interface ContextAuditGroup {
15
+ id: string;
16
+ label: string;
17
+ tokens: number;
18
+ /** Share of the audit total, 0-100. */
19
+ percent: number;
20
+ entries: ContextAuditEntry[];
21
+ /** Shown alongside the group when its numbers need qualifying. */
22
+ note?: string;
23
+ }
24
+ export interface ContextAudit {
25
+ /** Context present before the first message: system prompt, skills, tools. */
26
+ startup: {
27
+ tokens: number;
28
+ percent: number;
29
+ groups: ContextAuditGroup[];
30
+ };
31
+ /** Context accumulated by the session: conversation and observation memory. */
32
+ accumulated: {
33
+ tokens: number;
34
+ percent: number;
35
+ groups: ContextAuditGroup[];
36
+ };
37
+ /** Startup + accumulated. Percentages elsewhere are shares of this. */
38
+ totalTokens: number;
39
+ /** Estimated rather than measured: token counts come from a heuristic estimator. */
40
+ estimated: true;
41
+ }
42
+ /** A tool definition as advertised to the model. */
43
+ export interface ContextAuditTool {
44
+ name: string;
45
+ description?: string;
46
+ /** JSON schema (or any serializable shape) sent with the definition. */
47
+ parameters?: unknown;
48
+ /** MCP server that provides the tool, when it is not built in. */
49
+ server?: string;
50
+ }
51
+ export interface ContextAuditInput {
52
+ /** Labeled sections of the assembled system prompt. */
53
+ promptSections?: PromptSection[];
54
+ /** Labeled sections of the per-request dynamic instructions. */
55
+ instructionSections?: PromptSection[];
56
+ /** The skills catalog exactly as injected into the system message. */
57
+ skillsCatalog?: string;
58
+ /** Tool definitions advertised to the model. */
59
+ tools?: ContextAuditTool[];
60
+ /**
61
+ * Observation memory currently occupying the context window, either as the
62
+ * injected text or as a token count reported by the memory subsystem.
63
+ *
64
+ * Only observations that are actually in the context belong here.
65
+ * Observations that merely sit in storage cost nothing until recalled, and
66
+ * conflating the two is exactly the confusion this audit exists to resolve.
67
+ */
68
+ injectedObservations?: string | {
69
+ tokens: number;
70
+ };
71
+ /** Prompt tokens the provider reported for the most recent request. */
72
+ conversation?: {
73
+ promptTokens?: number;
74
+ };
75
+ }
76
+ /**
77
+ * Build a context audit from already-collected context.
78
+ *
79
+ * Percentages are shares of the audited total, not of the model's context
80
+ * window: window size is not exposed by the model registry, and inventing one
81
+ * would make every number wrong for models that disagree with the guess.
82
+ */
83
+ export declare function buildContextAudit(input: ContextAuditInput): ContextAudit;
84
+ //# sourceMappingURL=context-audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-audit.d.ts","sourceRoot":"","sources":["../../src/agents/context-audit.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAC;IAC1E,+EAA+E;IAC/E,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAC;IAC9E,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,aAAa,EAAE,CAAC;IACtC,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,uEAAuE;IACvE,YAAY,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AA2CD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAsFxE"}
@@ -0,0 +1,118 @@
1
+ import { tokenEstimate } from "../utils/token-estimator.js";
2
+ //#region src/agents/context-audit.ts
3
+ /**
4
+ * Context audit — accounts for what occupies the model's context window.
5
+ *
6
+ * Deliberately pure: callers collect the real strings (prompt sections, the
7
+ * injected skills catalog, tool definitions) and this module only measures and
8
+ * groups them. That keeps the audit honest — it reports on the same text the
9
+ * model receives rather than a description of it — and keeps it testable
10
+ * without a live session.
11
+ *
12
+ * Nothing here reads file contents or secrets: entries carry labels, origins
13
+ * and sizes only, never the underlying text, so an audit can be shown or
14
+ * pasted without leaking whatever the context happens to contain.
15
+ */
16
+ function measure(id, label, content, detail) {
17
+ return {
18
+ id,
19
+ label,
20
+ detail,
21
+ tokens: tokenEstimate(content),
22
+ characters: content.length,
23
+ percent: 0
24
+ };
25
+ }
26
+ function sectionEntries(sections, prefix) {
27
+ return sections.filter((section) => section.content.length > 0).map((section) => measure(`${prefix}:${section.id}`, section.label, section.content, section.detail));
28
+ }
29
+ function group(id, label, entries, note) {
30
+ if (entries.length === 0) return void 0;
31
+ return {
32
+ id,
33
+ label,
34
+ tokens: entries.reduce((sum, entry) => sum + entry.tokens, 0),
35
+ percent: 0,
36
+ entries,
37
+ note
38
+ };
39
+ }
40
+ /**
41
+ * Group tool definitions by their provider so a chatty MCP server is visible as
42
+ * one line rather than fifty. Per-tool entries stay available underneath.
43
+ */
44
+ function toolEntries(tools) {
45
+ return tools.map((tool) => {
46
+ const serialized = [
47
+ tool.name,
48
+ tool.description ?? "",
49
+ tool.parameters ? JSON.stringify(tool.parameters) : ""
50
+ ].join("\n");
51
+ return measure(`tool:${tool.server ?? "built-in"}:${tool.name}`, tool.name, serialized, tool.server);
52
+ });
53
+ }
54
+ function withPercent(items, total) {
55
+ for (const item of items) item.percent = total > 0 ? item.tokens / total * 100 : 0;
56
+ return items;
57
+ }
58
+ function sumTokens(groups) {
59
+ return groups.reduce((sum, entry) => sum + entry.tokens, 0);
60
+ }
61
+ /**
62
+ * Build a context audit from already-collected context.
63
+ *
64
+ * Percentages are shares of the audited total, not of the model's context
65
+ * window: window size is not exposed by the model registry, and inventing one
66
+ * would make every number wrong for models that disagree with the guess.
67
+ */
68
+ function buildContextAudit(input) {
69
+ const startupGroups = [
70
+ group("system-prompt", "System prompt", sectionEntries(input.promptSections ?? [], "prompt")),
71
+ group("dynamic-instructions", "Dynamic instructions", sectionEntries(input.instructionSections ?? [], "dynamic")),
72
+ group("skills", "Skills catalog", input.skillsCatalog ? [measure("skills:catalog", "Available skills", input.skillsCatalog)] : [], "Skill instructions are loaded on demand and are not counted here."),
73
+ group("tools", "Tool definitions", toolEntries(input.tools ?? []))
74
+ ].filter((entry) => entry !== void 0);
75
+ const observationEntries = [];
76
+ if (typeof input.injectedObservations === "string") observationEntries.push(measure("observations:injected", "Injected into context", input.injectedObservations));
77
+ else if (input.injectedObservations && input.injectedObservations.tokens > 0) observationEntries.push({
78
+ id: "observations:injected",
79
+ label: "Injected into context",
80
+ tokens: input.injectedObservations.tokens,
81
+ characters: 0,
82
+ percent: 0
83
+ });
84
+ const startupTokens = sumTokens(startupGroups);
85
+ const injectedObservationTokens = observationEntries.reduce((sum, entry) => sum + entry.tokens, 0);
86
+ const promptTokens = input.conversation?.promptTokens ?? 0;
87
+ const conversationTokens = Math.max(0, promptTokens - startupTokens - injectedObservationTokens);
88
+ const accumulatedGroups = [group("conversation", "Conversation", promptTokens > 0 ? [{
89
+ id: "conversation:messages",
90
+ label: "Messages, tool calls and results",
91
+ tokens: conversationTokens,
92
+ characters: 0,
93
+ percent: 0
94
+ }] : [], `Derived from the provider's last request (~${promptTokens} prompt tokens) minus the startup context measured above.`), group("observations", "Observation memory", observationEntries, "Observations kept only in storage are not counted: they cost nothing until recalled.")].filter((entry) => entry !== void 0);
95
+ const accumulatedTokens = sumTokens(accumulatedGroups);
96
+ const totalTokens = startupTokens + accumulatedTokens;
97
+ for (const entry of [...startupGroups, ...accumulatedGroups]) withPercent(entry.entries, totalTokens);
98
+ withPercent(startupGroups, totalTokens);
99
+ withPercent(accumulatedGroups, totalTokens);
100
+ return {
101
+ startup: {
102
+ tokens: startupTokens,
103
+ percent: totalTokens > 0 ? startupTokens / totalTokens * 100 : 0,
104
+ groups: startupGroups
105
+ },
106
+ accumulated: {
107
+ tokens: accumulatedTokens,
108
+ percent: totalTokens > 0 ? accumulatedTokens / totalTokens * 100 : 0,
109
+ groups: accumulatedGroups
110
+ },
111
+ totalTokens,
112
+ estimated: true
113
+ };
114
+ }
115
+ //#endregion
116
+ export { buildContextAudit };
117
+
118
+ //# sourceMappingURL=context-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-audit.js","names":[],"sources":["../../src/agents/context-audit.ts"],"sourcesContent":["/**\n * Context audit — accounts for what occupies the model's context window.\n *\n * Deliberately pure: callers collect the real strings (prompt sections, the\n * injected skills catalog, tool definitions) and this module only measures and\n * groups them. That keeps the audit honest — it reports on the same text the\n * model receives rather than a description of it — and keeps it testable\n * without a live session.\n *\n * Nothing here reads file contents or secrets: entries carry labels, origins\n * and sizes only, never the underlying text, so an audit can be shown or\n * pasted without leaking whatever the context happens to contain.\n */\nimport { tokenEstimate } from '../utils/token-estimator.js';\nimport type { PromptSection } from './prompts/index.js';\n\n/** A single measured contributor to the context window. */\nexport interface ContextAuditEntry {\n id: string;\n label: string;\n /** Provenance: file path, server name, model id — whatever identifies the source. */\n detail?: string;\n tokens: number;\n characters: number;\n /** Share of the audit total, 0-100. */\n percent: number;\n}\n\n/** A category of contributors (e.g. all agent instruction files). */\nexport interface ContextAuditGroup {\n id: string;\n label: string;\n tokens: number;\n /** Share of the audit total, 0-100. */\n percent: number;\n entries: ContextAuditEntry[];\n /** Shown alongside the group when its numbers need qualifying. */\n note?: string;\n}\n\nexport interface ContextAudit {\n /** Context present before the first message: system prompt, skills, tools. */\n startup: { tokens: number; percent: number; groups: ContextAuditGroup[] };\n /** Context accumulated by the session: conversation and observation memory. */\n accumulated: { tokens: number; percent: number; groups: ContextAuditGroup[] };\n /** Startup + accumulated. Percentages elsewhere are shares of this. */\n totalTokens: number;\n /** Estimated rather than measured: token counts come from a heuristic estimator. */\n estimated: true;\n}\n\n/** A tool definition as advertised to the model. */\nexport interface ContextAuditTool {\n name: string;\n description?: string;\n /** JSON schema (or any serializable shape) sent with the definition. */\n parameters?: unknown;\n /** MCP server that provides the tool, when it is not built in. */\n server?: string;\n}\n\nexport interface ContextAuditInput {\n /** Labeled sections of the assembled system prompt. */\n promptSections?: PromptSection[];\n /** Labeled sections of the per-request dynamic instructions. */\n instructionSections?: PromptSection[];\n /** The skills catalog exactly as injected into the system message. */\n skillsCatalog?: string;\n /** Tool definitions advertised to the model. */\n tools?: ContextAuditTool[];\n /**\n * Observation memory currently occupying the context window, either as the\n * injected text or as a token count reported by the memory subsystem.\n *\n * Only observations that are actually in the context belong here.\n * Observations that merely sit in storage cost nothing until recalled, and\n * conflating the two is exactly the confusion this audit exists to resolve.\n */\n injectedObservations?: string | { tokens: number };\n /** Prompt tokens the provider reported for the most recent request. */\n conversation?: { promptTokens?: number };\n}\n\nfunction measure(id: string, label: string, content: string, detail?: string): ContextAuditEntry {\n return { id, label, detail, tokens: tokenEstimate(content), characters: content.length, percent: 0 };\n}\n\nfunction sectionEntries(sections: PromptSection[], prefix: string): ContextAuditEntry[] {\n return sections\n .filter(section => section.content.length > 0)\n .map(section => measure(`${prefix}:${section.id}`, section.label, section.content, section.detail));\n}\n\nfunction group(id: string, label: string, entries: ContextAuditEntry[], note?: string): ContextAuditGroup | undefined {\n if (entries.length === 0) return undefined;\n return { id, label, tokens: entries.reduce((sum, entry) => sum + entry.tokens, 0), percent: 0, entries, note };\n}\n\n/**\n * Group tool definitions by their provider so a chatty MCP server is visible as\n * one line rather than fifty. Per-tool entries stay available underneath.\n */\nfunction toolEntries(tools: ContextAuditTool[]): ContextAuditEntry[] {\n return tools.map(tool => {\n // Approximates the serialized definition: name, description and schema are\n // what a provider sends, and the exact wire framing is provider-specific.\n const serialized = [tool.name, tool.description ?? '', tool.parameters ? JSON.stringify(tool.parameters) : ''].join(\n '\\n',\n );\n return measure(`tool:${tool.server ?? 'built-in'}:${tool.name}`, tool.name, serialized, tool.server);\n });\n}\n\nfunction withPercent<T extends { tokens: number; percent: number }>(items: T[], total: number): T[] {\n for (const item of items) {\n item.percent = total > 0 ? (item.tokens / total) * 100 : 0;\n }\n return items;\n}\n\nfunction sumTokens(groups: ContextAuditGroup[]): number {\n return groups.reduce((sum, entry) => sum + entry.tokens, 0);\n}\n\n/**\n * Build a context audit from already-collected context.\n *\n * Percentages are shares of the audited total, not of the model's context\n * window: window size is not exposed by the model registry, and inventing one\n * would make every number wrong for models that disagree with the guess.\n */\nexport function buildContextAudit(input: ContextAuditInput): ContextAudit {\n const startupGroups = [\n group('system-prompt', 'System prompt', sectionEntries(input.promptSections ?? [], 'prompt')),\n group('dynamic-instructions', 'Dynamic instructions', sectionEntries(input.instructionSections ?? [], 'dynamic')),\n group(\n 'skills',\n 'Skills catalog',\n input.skillsCatalog ? [measure('skills:catalog', 'Available skills', input.skillsCatalog)] : [],\n 'Skill instructions are loaded on demand and are not counted here.',\n ),\n group('tools', 'Tool definitions', toolEntries(input.tools ?? [])),\n ].filter((entry): entry is ContextAuditGroup => entry !== undefined);\n\n const observationEntries: ContextAuditEntry[] = [];\n if (typeof input.injectedObservations === 'string') {\n observationEntries.push(measure('observations:injected', 'Injected into context', input.injectedObservations));\n } else if (input.injectedObservations && input.injectedObservations.tokens > 0) {\n observationEntries.push({\n id: 'observations:injected',\n label: 'Injected into context',\n tokens: input.injectedObservations.tokens,\n characters: 0,\n percent: 0,\n });\n }\n\n const startupTokens = sumTokens(startupGroups);\n const injectedObservationTokens = observationEntries.reduce((sum, entry) => sum + entry.tokens, 0);\n\n // The provider's prompt token count covers the whole request — startup\n // context and injected observations included — so the conversation's own\n // contribution is what is left after subtracting everything already\n // accounted for. Using the raw prompt count would double-count all of it.\n const promptTokens = input.conversation?.promptTokens ?? 0;\n const conversationTokens = Math.max(0, promptTokens - startupTokens - injectedObservationTokens);\n const conversationEntries: ContextAuditEntry[] =\n promptTokens > 0\n ? [\n {\n id: 'conversation:messages',\n label: 'Messages, tool calls and results',\n tokens: conversationTokens,\n characters: 0,\n percent: 0,\n },\n ]\n : [];\n\n const accumulatedGroups = [\n group(\n 'conversation',\n 'Conversation',\n conversationEntries,\n `Derived from the provider's last request (~${promptTokens} prompt tokens) minus the startup context measured above.`,\n ),\n group(\n 'observations',\n 'Observation memory',\n observationEntries,\n 'Observations kept only in storage are not counted: they cost nothing until recalled.',\n ),\n ].filter((entry): entry is ContextAuditGroup => entry !== undefined);\n\n const accumulatedTokens = sumTokens(accumulatedGroups);\n const totalTokens = startupTokens + accumulatedTokens;\n\n for (const entry of [...startupGroups, ...accumulatedGroups]) {\n withPercent(entry.entries, totalTokens);\n }\n withPercent(startupGroups, totalTokens);\n withPercent(accumulatedGroups, totalTokens);\n\n return {\n startup: {\n tokens: startupTokens,\n percent: totalTokens > 0 ? (startupTokens / totalTokens) * 100 : 0,\n groups: startupGroups,\n },\n accumulated: {\n tokens: accumulatedTokens,\n percent: totalTokens > 0 ? (accumulatedTokens / totalTokens) * 100 : 0,\n groups: accumulatedGroups,\n },\n totalTokens,\n estimated: true,\n };\n}\n"],"mappings":"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"}
@@ -1,6 +1,17 @@
1
- export declare function getDynamicInstructions({ requestContext }: {
1
+ import type { PromptSection } from './prompts/index.js';
2
+ export declare function getDynamicInstructions({ requestContext, }: {
2
3
  requestContext: {
3
4
  get(key: string): unknown;
4
5
  };
5
6
  }): Promise<string>;
7
+ /**
8
+ * The system instructions as labeled sections, so callers that attribute
9
+ * context cost per source (the `/context` audit) measure the same strings that
10
+ * `getDynamicInstructions` sends rather than reconstructing them.
11
+ */
12
+ export declare function getDynamicInstructionSections({ requestContext, }: {
13
+ requestContext: {
14
+ get(key: string): unknown;
15
+ };
16
+ }): Promise<PromptSection[]>;
6
17
  //# sourceMappingURL=instructions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/agents/instructions.ts"],"names":[],"mappings":"AAOA,wBAAsB,sBAAsB,CAAC,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE;QAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CAAE,mBAiCjH"}
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/agents/instructions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGvE,wBAAsB,sBAAsB,CAAC,EAC3C,cAAc,GACf,EAAE;IACD,cAAc,EAAE;QAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC/C,GAAG,OAAO,CAAC,MAAM,CAAC,CAElB;AAED;;;;GAIG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,cAAc,GACf,EAAE;IACD,cAAc,EAAE;QAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC/C,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA0C3B"}
@@ -1,13 +1,21 @@
1
1
  import { getCurrentGitBranchAsync } from "../utils/project.js";
2
2
  import { detectCommonBinariesAsync } from "../utils/binaries.js";
3
- import { buildFullPrompt } from "./prompts/index.js";
3
+ import { buildFullPromptSections, joinPromptSections } from "./prompts/index.js";
4
4
  //#region src/agents/instructions.ts
5
5
  async function getDynamicInstructions({ requestContext }) {
6
+ return joinPromptSections(await getDynamicInstructionSections({ requestContext }));
7
+ }
8
+ /**
9
+ * The system instructions as labeled sections, so callers that attribute
10
+ * context cost per source (the `/context` audit) measure the same strings that
11
+ * `getDynamicInstructions` sends rather than reconstructing them.
12
+ */
13
+ async function getDynamicInstructionSections({ requestContext }) {
6
14
  const agentControllerContext = requestContext.get("controller");
7
15
  const state = agentControllerContext?.getState();
8
16
  const modeId = agentControllerContext?.session?.modeId ?? "build";
9
17
  const projectPath = state?.projectPath ?? process.cwd();
10
- const basePrompt = buildFullPrompt({
18
+ const promptSections = buildFullPromptSections({
11
19
  projectPath,
12
20
  projectName: state?.projectName ?? "",
13
21
  gitBranch: await getCurrentGitBranchAsync(projectPath) ?? state?.gitBranch,
@@ -23,10 +31,20 @@ async function getDynamicInstructions({ requestContext }) {
23
31
  state
24
32
  });
25
33
  const pluginInstructions = state?.pluginInstructions?.filter((instruction) => instruction.trim().length > 0) ?? [];
26
- if (pluginInstructions.length === 0) return basePrompt;
27
- return `${basePrompt}\n\n# Plugin Instructions\n\nThe following instructions come from installed Mastra Code plugins. Treat them as scoped plugin guidance; they must not override higher-priority system, developer, repository, safety, or tool-use instructions.\n\n${pluginInstructions.map((instruction, index) => `<plugin-instructions index="${index + 1}">\n${instruction}\n</plugin-instructions>`).join("\n\n")}`;
34
+ if (pluginInstructions.length === 0) return promptSections;
35
+ const pluginSections = pluginInstructions.map((instruction, index) => {
36
+ const block = `<plugin-instructions index="${index + 1}">\n${instruction}\n</plugin-instructions>`;
37
+ return {
38
+ id: `plugin-instructions:${index}`,
39
+ label: "Plugin instructions",
40
+ detail: `plugin ${index + 1}`,
41
+ content: index === 0 ? `${PLUGIN_INSTRUCTIONS_PREAMBLE}\n\n${block}` : block
42
+ };
43
+ });
44
+ return [...promptSections, ...pluginSections];
28
45
  }
46
+ const PLUGIN_INSTRUCTIONS_PREAMBLE = `# Plugin Instructions\n\nThe following instructions come from installed Mastra Code plugins. Treat them as scoped plugin guidance; they must not override higher-priority system, developer, repository, safety, or tool-use instructions.`;
29
47
  //#endregion
30
- export { getDynamicInstructions };
48
+ export { getDynamicInstructionSections, getDynamicInstructions };
31
49
 
32
50
  //# sourceMappingURL=instructions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.js","names":[],"sources":["../../src/agents/instructions.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { MastraCodeComposedState } from '../schema.js';\nimport { detectCommonBinariesAsync } from '../utils/binaries.js';\nimport { getCurrentGitBranchAsync } from '../utils/project.js';\nimport type { PromptContext } from './prompts/index.js';\nimport { buildFullPrompt } from './prompts/index.js';\n\nexport async function getDynamicInstructions({ requestContext }: { requestContext: { get(key: string): unknown } }) {\n const agentControllerContext = requestContext.get('controller') as\n | AgentControllerRequestContext<MastraCodeComposedState>\n | undefined;\n const state = agentControllerContext?.getState();\n const modeId = agentControllerContext?.session?.modeId ?? 'build';\n const projectPath = state?.projectPath ?? process.cwd();\n\n const promptCtx: PromptContext = {\n projectPath,\n projectName: state?.projectName ?? '',\n gitBranch: (await getCurrentGitBranchAsync(projectPath)) ?? state?.gitBranch,\n platform: process.platform,\n commonBinaries: await detectCommonBinariesAsync(),\n date: new Date().toISOString().split('T')[0]!,\n mode: modeId,\n modelId: agentControllerContext?.session?.modelId || undefined,\n activePlan: state?.activePlan ?? null,\n modeId: modeId,\n currentDate: new Date().toISOString().split('T')[0]!,\n workingDir: state?.projectPath ?? process.cwd(),\n state,\n };\n\n const basePrompt = buildFullPrompt(promptCtx);\n const pluginInstructions = state?.pluginInstructions?.filter(instruction => instruction.trim().length > 0) ?? [];\n if (pluginInstructions.length === 0) return basePrompt;\n\n const formattedPluginInstructions = pluginInstructions\n .map((instruction, index) => `<plugin-instructions index=\"${index + 1}\">\\n${instruction}\\n</plugin-instructions>`)\n .join('\\n\\n');\n\n return `${basePrompt}\\n\\n# Plugin Instructions\\n\\nThe following instructions come from installed Mastra Code plugins. Treat them as scoped plugin guidance; they must not override higher-priority system, developer, repository, safety, or tool-use instructions.\\n\\n${formattedPluginInstructions}`;\n}\n"],"mappings":";;;;AAOA,eAAsB,uBAAuB,EAAE,kBAAqE;CAClH,MAAM,yBAAyB,eAAe,IAAI,YAAY;CAG9D,MAAM,QAAQ,wBAAwB,SAAS;CAC/C,MAAM,SAAS,wBAAwB,SAAS,UAAU;CAC1D,MAAM,cAAc,OAAO,eAAe,QAAQ,IAAI;CAkBtD,MAAM,aAAa,gBAAgB;EAfjC;EACA,aAAa,OAAO,eAAe;EACnC,WAAY,MAAM,yBAAyB,WAAW,KAAM,OAAO;EACnE,UAAU,QAAQ;EAClB,gBAAgB,MAAM,0BAA0B;EAChD,uBAAM,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;EAC1C,MAAM;EACN,SAAS,wBAAwB,SAAS,WAAW,KAAA;EACrD,YAAY,OAAO,cAAc;EACzB;EACR,8BAAa,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;EACjD,YAAY,OAAO,eAAe,QAAQ,IAAI;EAC9C;CAGyC,CAAC;CAC5C,MAAM,qBAAqB,OAAO,oBAAoB,QAAO,gBAAe,YAAY,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC;CAC/G,IAAI,mBAAmB,WAAW,GAAG,OAAO;CAM5C,OAAO,GAAG,WAAW,oPAJe,mBACjC,KAAK,aAAa,UAAU,+BAA+B,QAAQ,EAAE,MAAM,YAAY,yBAAyB,CAAC,CACjH,KAAK,MAE2R;AACrS"}
1
+ {"version":3,"file":"instructions.js","names":[],"sources":["../../src/agents/instructions.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { MastraCodeComposedState } from '../schema.js';\nimport { detectCommonBinariesAsync } from '../utils/binaries.js';\nimport { getCurrentGitBranchAsync } from '../utils/project.js';\nimport type { PromptContext, PromptSection } from './prompts/index.js';\nimport { buildFullPromptSections, joinPromptSections } from './prompts/index.js';\n\nexport async function getDynamicInstructions({\n requestContext,\n}: {\n requestContext: { get(key: string): unknown };\n}): Promise<string> {\n return joinPromptSections(await getDynamicInstructionSections({ requestContext }));\n}\n\n/**\n * The system instructions as labeled sections, so callers that attribute\n * context cost per source (the `/context` audit) measure the same strings that\n * `getDynamicInstructions` sends rather than reconstructing them.\n */\nexport async function getDynamicInstructionSections({\n requestContext,\n}: {\n requestContext: { get(key: string): unknown };\n}): Promise<PromptSection[]> {\n const agentControllerContext = requestContext.get('controller') as\n | AgentControllerRequestContext<MastraCodeComposedState>\n | undefined;\n const state = agentControllerContext?.getState();\n const modeId = agentControllerContext?.session?.modeId ?? 'build';\n const projectPath = state?.projectPath ?? process.cwd();\n\n const promptCtx: PromptContext = {\n projectPath,\n projectName: state?.projectName ?? '',\n gitBranch: (await getCurrentGitBranchAsync(projectPath)) ?? state?.gitBranch,\n platform: process.platform,\n commonBinaries: await detectCommonBinariesAsync(),\n date: new Date().toISOString().split('T')[0]!,\n mode: modeId,\n modelId: agentControllerContext?.session?.modelId || undefined,\n activePlan: state?.activePlan ?? null,\n modeId: modeId,\n currentDate: new Date().toISOString().split('T')[0]!,\n workingDir: state?.projectPath ?? process.cwd(),\n state,\n };\n\n const promptSections = buildFullPromptSections(promptCtx);\n const pluginInstructions: string[] =\n state?.pluginInstructions?.filter((instruction: string) => instruction.trim().length > 0) ?? [];\n if (pluginInstructions.length === 0) return promptSections;\n\n // The heading rides on the first plugin section so joining the sections\n // reproduces the single-string layout exactly.\n const pluginSections: PromptSection[] = pluginInstructions.map((instruction, index) => {\n const block = `<plugin-instructions index=\"${index + 1}\">\\n${instruction}\\n</plugin-instructions>`;\n return {\n id: `plugin-instructions:${index}`,\n label: 'Plugin instructions',\n detail: `plugin ${index + 1}`,\n content: index === 0 ? `${PLUGIN_INSTRUCTIONS_PREAMBLE}\\n\\n${block}` : block,\n };\n });\n\n return [...promptSections, ...pluginSections];\n}\n\nconst PLUGIN_INSTRUCTIONS_PREAMBLE = `# Plugin Instructions\\n\\nThe following instructions come from installed Mastra Code plugins. Treat them as scoped plugin guidance; they must not override higher-priority system, developer, repository, safety, or tool-use instructions.`;\n"],"mappings":";;;;AAOA,eAAsB,uBAAuB,EAC3C,kBAGkB;CAClB,OAAO,mBAAmB,MAAM,8BAA8B,EAAE,eAAe,CAAC,CAAC;AACnF;;;;;;AAOA,eAAsB,8BAA8B,EAClD,kBAG2B;CAC3B,MAAM,yBAAyB,eAAe,IAAI,YAAY;CAG9D,MAAM,QAAQ,wBAAwB,SAAS;CAC/C,MAAM,SAAS,wBAAwB,SAAS,UAAU;CAC1D,MAAM,cAAc,OAAO,eAAe,QAAQ,IAAI;CAkBtD,MAAM,iBAAiB,wBAAwB;EAf7C;EACA,aAAa,OAAO,eAAe;EACnC,WAAY,MAAM,yBAAyB,WAAW,KAAM,OAAO;EACnE,UAAU,QAAQ;EAClB,gBAAgB,MAAM,0BAA0B;EAChD,uBAAM,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;EAC1C,MAAM;EACN,SAAS,wBAAwB,SAAS,WAAW,KAAA;EACrD,YAAY,OAAO,cAAc;EACzB;EACR,8BAAa,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;EACjD,YAAY,OAAO,eAAe,QAAQ,IAAI;EAC9C;CAGqD,CAAC;CACxD,MAAM,qBACJ,OAAO,oBAAoB,QAAQ,gBAAwB,YAAY,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC;CAChG,IAAI,mBAAmB,WAAW,GAAG,OAAO;CAI5C,MAAM,iBAAkC,mBAAmB,KAAK,aAAa,UAAU;EACrF,MAAM,QAAQ,+BAA+B,QAAQ,EAAE,MAAM,YAAY;EACzE,OAAO;GACL,IAAI,uBAAuB;GAC3B,OAAO;GACP,QAAQ,UAAU,QAAQ;GAC1B,SAAS,UAAU,IAAI,GAAG,6BAA6B,MAAM,UAAU;EACzE;CACF,CAAC;CAED,OAAO,CAAC,GAAG,gBAAgB,GAAG,cAAc;AAC9C;AAEA,MAAM,+BAA+B"}
@@ -1,7 +1,6 @@
1
- import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';
2
1
  import type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';
3
2
  import type { RequestContext } from '@mastra/core/request-context';
4
- import type { ThinkingLevel } from '../providers/openai-codex.js';
3
+ import type { ThinkingLevelSetting } from '../thinking.js';
5
4
  import { MastraCodeGateway } from './mastracode-gateway.js';
6
5
  import type { MastraCodeGatewayOptions } from './mastracode-gateway.js';
7
6
  export { getAnthropicApiKey, getOpenAIApiKey, MASTRACODE_GATEWAY_ID, MastraCodeGateway, remapOpenAIModelForCodexOAuth, resolveAuth, } from './mastracode-gateway.js';
@@ -29,10 +28,18 @@ export declare function resolveModelId(modelId: string): string;
29
28
  * - For all other providers: Uses Mastra's model router (models.dev gateway)
30
29
  */
31
30
  export declare function resolveModel(modelId: string, options?: {
32
- thinkingLevel?: ThinkingLevel;
31
+ thinkingLevel?: ThinkingLevelSetting;
33
32
  remapForCodexOAuth?: boolean;
34
33
  requestContext?: RequestContext;
35
34
  }): GatewayLanguageModel;
35
+ export interface ThinkingRequestContext {
36
+ state?: {
37
+ thinkingLevel?: unknown;
38
+ };
39
+ session?: {
40
+ modeId?: string;
41
+ };
42
+ }
36
43
  /**
37
44
  * Resolve the effective thinking level for the current request.
38
45
  *
@@ -46,7 +53,7 @@ export declare function resolveModel(modelId: string, options?: {
46
53
  * apply to the next request of every session — including automated
47
54
  * (rule-driven) Factory runs that nobody ever opens interactively.
48
55
  */
49
- export declare function resolveRequestThinkingLevel(agentControllerContext: AgentControllerRequestContext<any> | undefined, settingsPath?: string): ThinkingLevel;
56
+ export declare function resolveRequestThinkingLevel(agentControllerContext: ThinkingRequestContext | undefined, settingsPath?: string): ThinkingLevelSetting;
50
57
  /**
51
58
  * Dynamic model function that reads the current model from controller state.
52
59
  * This allows runtime model switching via the /models picker.
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agents/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAOnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,EAGL,iBAAiB,EAGlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,6BAA6B,EAC7B,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAa1C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAE5F;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,2BAA2B,6DAIxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,aAAa,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,cAAc,CAAA;CAAE,GACzG,oBAAoB,CA+EtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,sBAAsB,EAAE,6BAA6B,CAAC,GAAG,CAAC,GAAG,SAAS,EACtE,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,CAKf;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,CAoBf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,GAAG,SAAS,CAI3B"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agents/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAQnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3D,OAAO,EAGL,iBAAiB,EAGlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,6BAA6B,EAC7B,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAa1C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAE5F;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,2BAA2B,6DAIxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,cAAc,CAAA;CAAE,GAChH,oBAAoB,CA+EtB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACpC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B;AACD;;;;;;;;;;;;GAYG;AAEH,wBAAgB,2BAA2B,CACzC,sBAAsB,EAAE,sBAAsB,GAAG,SAAS,EAC1D,YAAY,CAAC,EAAE,MAAM,GACpB,oBAAoB,CAKtB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,CAoBf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,GAAG,SAAS,CAI3B"}
@@ -1,3 +1,4 @@
1
+ import { isThinkingLevelSetting } from "../thinking.js";
1
2
  import { loadSettings, resolveDefaultThinkingLevel, stripMastraCodeCustomProviderPrefix } from "../onboarding/settings.js";
2
3
  import { hasCredentialStoreProvider, resolveCredentialStore, resolveTenantFromRequestContext, setCredentialStoreProvider } from "./credential-resolver.js";
3
4
  import { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from "../providers/amazon-bedrock-gateway.js";
@@ -104,7 +105,7 @@ function resolveModel(modelId, options) {
104
105
  */
105
106
  function resolveRequestThinkingLevel(agentControllerContext, settingsPath) {
106
107
  const override = agentControllerContext?.state?.thinkingLevel;
107
- if (override !== void 0) return override;
108
+ if (isThinkingLevelSetting(override)) return override;
108
109
  const modeId = agentControllerContext?.session?.modeId;
109
110
  return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;
110
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","names":[],"sources":["../../src/agents/model.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport {\n loadSettings,\n resolveDefaultThinkingLevel,\n stripMastraCodeCustomProviderPrefix,\n} from '../onboarding/settings.js';\nimport { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from '../providers/amazon-bedrock-gateway.js';\nimport type { ThinkingLevel } from '../providers/openai-codex.js';\nimport { resolveCredentialStore } from './credential-resolver.js';\nimport { resolveCustomProviders } from './custom-provider-source.js';\nimport {\n MASTRA_GATEWAY_PREFIX,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n reloadAuthStorage,\n stripMastraGatewayPrefix,\n} from './mastracode-gateway.js';\nimport type { MastraCodeGatewayOptions } from './mastracode-gateway.js';\n\nexport {\n getAnthropicApiKey,\n getOpenAIApiKey,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n remapOpenAIModelForCodexOAuth,\n resolveAuth,\n} from './mastracode-gateway.js';\nexport type { MastraCodeCustomProvider, MastraCodeGatewayOptions } from './mastracode-gateway.js';\nexport {\n setCredentialStoreProvider,\n hasCredentialStoreProvider,\n resolveTenantFromRequestContext,\n} from './credential-resolver.js';\nexport type { CredentialTenant, CredentialStoreProvider } from './credential-resolver.js';\nexport {\n setCustomProvidersSource,\n hasCustomProvidersSource,\n resolveCustomProviders,\n} from './custom-provider-source.js';\nexport type { CustomProvidersSource } from './custom-provider-source.js';\n\ntype ResolvedModel = GatewayLanguageModel;\ntype ModelRequestHeaders = Record<string, string>;\n\nfunction getAgentControllerHeaders(requestContext?: RequestContext): ModelRequestHeaders | undefined {\n const agentControllerContext = requestContext?.get('controller') as AgentControllerRequestContext<any> | undefined;\n const headers = {\n ...(agentControllerContext?.threadId ? { 'x-thread-id': agentControllerContext.threadId } : {}),\n ...(agentControllerContext?.resourceId ? { 'x-resource-id': agentControllerContext.resourceId } : {}),\n };\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nexport function createMastraCodeGateway(options: MastraCodeGatewayOptions): MastraCodeGateway {\n return new MastraCodeGateway(options);\n}\n\nexport function createMastraCodeModelCatalogProvider(gateway: MastraModelGatewayInterface) {\n return gateway instanceof MastraCodeGateway\n ? gateway.createModelCatalogProvider()\n : MastraCodeGateway.createModelCatalogProvider(gateway);\n}\n\n/**\n * Placeholder for future model ID normalization.\n * Currently returns the input unchanged, but exists as a seam\n * for aliasing, casing fixes, or validation in the future.\n */\nexport function resolveModelId(modelId: string): string {\n return modelId;\n}\n\n/**\n * Resolve a model ID to the correct provider instance.\n * Shared by the main agent, observer, and reflector.\n *\n * - For anthropic/* models: Uses stored OAuth credentials when present, otherwise direct API key\n * - For openai/* models: Uses OAuth when configured, otherwise direct API key from AuthStorage\n * - For moonshotai/* models: Uses Moonshot AI Anthropic-compatible endpoint\n * - For all other providers: Uses Mastra's model router (models.dev gateway)\n */\nexport function resolveModel(\n modelId: string,\n options?: { thinkingLevel?: ThinkingLevel; remapForCodexOAuth?: boolean; requestContext?: RequestContext },\n): GatewayLanguageModel {\n reloadAuthStorage();\n const headers = getAgentControllerHeaders(options?.requestContext);\n const settings = loadSettings();\n // Bedrock was previously cataloged under the MastraCode gateway namespace\n // (`mastracode/amazon-bedrock/<model>`). Normalize any legacy saved ids to the\n // standalone `amazon-bedrock/<model>` form so they resolve through the\n // dedicated Bedrock gateway.\n const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;\n const bedrockNormalizedInput = modelId.startsWith(bedrockLegacyPrefix)\n ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1)\n : modelId;\n // Deployed web registers a custom providers source (DB-backed, tenant\n // scoped); when registered it is authoritative and settings.json custom\n // providers are ignored. Undefined = local settings-based behavior.\n const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;\n // Ids selected from the shared /models catalog were previously persisted in\n // the gateway-qualified `mastracode/<customProviderId>/<model>` form, which\n // parses the provider as `mastracode` and breaks provider config lookup.\n // Normalize at resolution time (in addition to stripping at selection time)\n // so already-saved ids and any surface that persists the raw catalog id\n // still resolve to the custom provider.\n const normalizedInput = stripMastraCodeCustomProviderPrefix(bedrockNormalizedInput, customProviders);\n const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);\n const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);\n const [providerId, ...modelParts] = normalizedModelId.split('/');\n const bareModelId = modelParts.join('/');\n if (!providerId || !bareModelId) {\n throw new Error(`Invalid model id: ${modelId}`);\n }\n\n if (providerId === AMAZON_BEDROCK_GATEWAY_ID) {\n const bedrockGateway = createAmazonBedrockGateway();\n const routerId = `${AMAZON_BEDROCK_GATEWAY_ID}/${bareModelId}`;\n const auth = bedrockGateway.resolveAuth({\n gatewayId: AMAZON_BEDROCK_GATEWAY_ID,\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n routerId,\n });\n return bedrockGateway.resolveLanguageModel({\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n }\n\n const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;\n\n const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();\n const rawGatewayBase =\n settings.memoryGateway?.baseUrl ?? process.env['MASTRA_GATEWAY_URL'] ?? 'https://gateway-api.mastra.ai';\n // Deployed web registers a per-tenant credential store provider; when the\n // request carries an authenticated tenant, resolve credentials through the\n // caller's own store (user > org > env). Undefined = global AuthStorage.\n const credentialStore = resolveCredentialStore(options?.requestContext);\n const gateway = createMastraCodeGateway({\n mastraGatewayBaseUrl: rawGatewayBase.replace(/\\/+$/, '').replace(/\\/v1$/, ''),\n mastraGatewayApiKey: mgApiKey,\n routeThroughMastraGateway: Boolean(mgApiKey && isMastraGatewayModel),\n thinkingLevel: options?.thinkingLevel,\n customProviders,\n credentialStore,\n });\n\n const auth = gateway.resolveAuth({\n gatewayId: MASTRACODE_GATEWAY_ID,\n providerId,\n modelId: bareModelId,\n routerId,\n });\n\n return gateway.resolveLanguageModel({\n providerId,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n}\n\n/**\n * Resolve the effective thinking level for the current request.\n *\n * Precedence:\n * 1. Session override (`state.thinkingLevel`, set via /think or the session\n * settings panel).\n * 2. Per-mode default from settings (`models.modeThinkingDefaults[mode]`).\n * 3. Global default (`preferences.thinkingLevel`).\n *\n * Resolved per-request (not seeded at session start) so configuration changes\n * apply to the next request of every session — including automated\n * (rule-driven) Factory runs that nobody ever opens interactively.\n */\nexport function resolveRequestThinkingLevel(\n agentControllerContext: AgentControllerRequestContext<any> | undefined,\n settingsPath?: string,\n): ThinkingLevel {\n const override = agentControllerContext?.state?.thinkingLevel as ThinkingLevel | undefined;\n if (override !== undefined) return override;\n const modeId = agentControllerContext?.session?.modeId;\n return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;\n}\n\n/**\n * Dynamic model function that reads the current model from controller state.\n * This allows runtime model switching via the /models picker.\n */\nexport function getDynamicModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel {\n const agentControllerContext = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n\n const modelId = agentControllerContext?.session?.modelId;\n if (!modelId) {\n // A missing controller context means the run was started without session\n // request context at all (e.g. a signal delivered to an idle thread) —\n // \"use /models\" would mislead there, the user's selection was never the\n // problem.\n if (!agentControllerContext) {\n throw new Error(\n 'No model available: this run started without a controller session context, so no model selection could be resolved.',\n );\n }\n throw new Error('No model selected. Use /models to select a model first.');\n }\n\n const thinkingLevel = resolveRequestThinkingLevel(agentControllerContext, settingsPath);\n\n return resolveModel(modelId, { thinkingLevel, remapForCodexOAuth: true, requestContext });\n}\n\n/**\n * Goal judge model resolver for the agent's `goal.judge` config. Resolves the\n * configured goal judge model through mastracode's gateway so provider\n * credentials (stored in auth storage, not just env) are injected — a bare model\n * id handed to core's default model router would fail to find the API key.\n *\n * Returns `undefined` when no judge model is configured, which keeps the goal\n * step a complete no-op (the goal mechanism requires a judge to do anything).\n *\n * `settingsPath` must be the same source `createMastraCode()` reads from so the\n * judge model and the goal budget (`goalMaxTurns`) come from one config — with a\n * custom `settingsPath` a bare `loadSettings()` here could read a different file\n * and silently turn the goal step into a no-op.\n */\nexport function getGoalJudgeModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | undefined {\n const judgeModelId = loadSettings(settingsPath).models.goalJudgeModel;\n if (!judgeModelId) return undefined;\n return resolveModel(judgeModelId, { remapForCodexOAuth: true, requestContext });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model.js","names":[],"sources":["../../src/agents/model.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport {\n loadSettings,\n resolveDefaultThinkingLevel,\n stripMastraCodeCustomProviderPrefix,\n} from '../onboarding/settings.js';\nimport { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from '../providers/amazon-bedrock-gateway.js';\nimport { isThinkingLevelSetting } from '../thinking.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nimport { resolveCredentialStore } from './credential-resolver.js';\nimport { resolveCustomProviders } from './custom-provider-source.js';\nimport {\n MASTRA_GATEWAY_PREFIX,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n reloadAuthStorage,\n stripMastraGatewayPrefix,\n} from './mastracode-gateway.js';\nimport type { MastraCodeGatewayOptions } from './mastracode-gateway.js';\n\nexport {\n getAnthropicApiKey,\n getOpenAIApiKey,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n remapOpenAIModelForCodexOAuth,\n resolveAuth,\n} from './mastracode-gateway.js';\nexport type { MastraCodeCustomProvider, MastraCodeGatewayOptions } from './mastracode-gateway.js';\nexport {\n setCredentialStoreProvider,\n hasCredentialStoreProvider,\n resolveTenantFromRequestContext,\n} from './credential-resolver.js';\nexport type { CredentialTenant, CredentialStoreProvider } from './credential-resolver.js';\nexport {\n setCustomProvidersSource,\n hasCustomProvidersSource,\n resolveCustomProviders,\n} from './custom-provider-source.js';\nexport type { CustomProvidersSource } from './custom-provider-source.js';\n\ntype ResolvedModel = GatewayLanguageModel;\ntype ModelRequestHeaders = Record<string, string>;\n\nfunction getAgentControllerHeaders(requestContext?: RequestContext): ModelRequestHeaders | undefined {\n const agentControllerContext = requestContext?.get('controller') as AgentControllerRequestContext<any> | undefined;\n const headers = {\n ...(agentControllerContext?.threadId ? { 'x-thread-id': agentControllerContext.threadId } : {}),\n ...(agentControllerContext?.resourceId ? { 'x-resource-id': agentControllerContext.resourceId } : {}),\n };\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nexport function createMastraCodeGateway(options: MastraCodeGatewayOptions): MastraCodeGateway {\n return new MastraCodeGateway(options);\n}\n\nexport function createMastraCodeModelCatalogProvider(gateway: MastraModelGatewayInterface) {\n return gateway instanceof MastraCodeGateway\n ? gateway.createModelCatalogProvider()\n : MastraCodeGateway.createModelCatalogProvider(gateway);\n}\n\n/**\n * Placeholder for future model ID normalization.\n * Currently returns the input unchanged, but exists as a seam\n * for aliasing, casing fixes, or validation in the future.\n */\nexport function resolveModelId(modelId: string): string {\n return modelId;\n}\n\n/**\n * Resolve a model ID to the correct provider instance.\n * Shared by the main agent, observer, and reflector.\n *\n * - For anthropic/* models: Uses stored OAuth credentials when present, otherwise direct API key\n * - For openai/* models: Uses OAuth when configured, otherwise direct API key from AuthStorage\n * - For moonshotai/* models: Uses Moonshot AI Anthropic-compatible endpoint\n * - For all other providers: Uses Mastra's model router (models.dev gateway)\n */\nexport function resolveModel(\n modelId: string,\n options?: { thinkingLevel?: ThinkingLevelSetting; remapForCodexOAuth?: boolean; requestContext?: RequestContext },\n): GatewayLanguageModel {\n reloadAuthStorage();\n const headers = getAgentControllerHeaders(options?.requestContext);\n const settings = loadSettings();\n // Bedrock was previously cataloged under the MastraCode gateway namespace\n // (`mastracode/amazon-bedrock/<model>`). Normalize any legacy saved ids to the\n // standalone `amazon-bedrock/<model>` form so they resolve through the\n // dedicated Bedrock gateway.\n const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;\n const bedrockNormalizedInput = modelId.startsWith(bedrockLegacyPrefix)\n ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1)\n : modelId;\n // Deployed web registers a custom providers source (DB-backed, tenant\n // scoped); when registered it is authoritative and settings.json custom\n // providers are ignored. Undefined = local settings-based behavior.\n const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;\n // Ids selected from the shared /models catalog were previously persisted in\n // the gateway-qualified `mastracode/<customProviderId>/<model>` form, which\n // parses the provider as `mastracode` and breaks provider config lookup.\n // Normalize at resolution time (in addition to stripping at selection time)\n // so already-saved ids and any surface that persists the raw catalog id\n // still resolve to the custom provider.\n const normalizedInput = stripMastraCodeCustomProviderPrefix(bedrockNormalizedInput, customProviders);\n const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);\n const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);\n const [providerId, ...modelParts] = normalizedModelId.split('/');\n const bareModelId = modelParts.join('/');\n if (!providerId || !bareModelId) {\n throw new Error(`Invalid model id: ${modelId}`);\n }\n\n if (providerId === AMAZON_BEDROCK_GATEWAY_ID) {\n const bedrockGateway = createAmazonBedrockGateway();\n const routerId = `${AMAZON_BEDROCK_GATEWAY_ID}/${bareModelId}`;\n const auth = bedrockGateway.resolveAuth({\n gatewayId: AMAZON_BEDROCK_GATEWAY_ID,\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n routerId,\n });\n return bedrockGateway.resolveLanguageModel({\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n }\n\n const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;\n\n const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();\n const rawGatewayBase =\n settings.memoryGateway?.baseUrl ?? process.env['MASTRA_GATEWAY_URL'] ?? 'https://gateway-api.mastra.ai';\n // Deployed web registers a per-tenant credential store provider; when the\n // request carries an authenticated tenant, resolve credentials through the\n // caller's own store (user > org > env). Undefined = global AuthStorage.\n const credentialStore = resolveCredentialStore(options?.requestContext);\n const gateway = createMastraCodeGateway({\n mastraGatewayBaseUrl: rawGatewayBase.replace(/\\/+$/, '').replace(/\\/v1$/, ''),\n mastraGatewayApiKey: mgApiKey,\n routeThroughMastraGateway: Boolean(mgApiKey && isMastraGatewayModel),\n thinkingLevel: options?.thinkingLevel,\n customProviders,\n credentialStore,\n });\n\n const auth = gateway.resolveAuth({\n gatewayId: MASTRACODE_GATEWAY_ID,\n providerId,\n modelId: bareModelId,\n routerId,\n });\n\n return gateway.resolveLanguageModel({\n providerId,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n}\n\nexport interface ThinkingRequestContext {\n state?: { thinkingLevel?: unknown };\n session?: { modeId?: string };\n}\n/**\n * Resolve the effective thinking level for the current request.\n *\n * Precedence:\n * 1. Session override (`state.thinkingLevel`, set via /think or the session\n * settings panel).\n * 2. Per-mode default from settings (`models.modeThinkingDefaults[mode]`).\n * 3. Global default (`preferences.thinkingLevel`).\n *\n * Resolved per-request (not seeded at session start) so configuration changes\n * apply to the next request of every session — including automated\n * (rule-driven) Factory runs that nobody ever opens interactively.\n */\n\nexport function resolveRequestThinkingLevel(\n agentControllerContext: ThinkingRequestContext | undefined,\n settingsPath?: string,\n): ThinkingLevelSetting {\n const override = agentControllerContext?.state?.thinkingLevel;\n if (isThinkingLevelSetting(override)) return override;\n const modeId = agentControllerContext?.session?.modeId;\n return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;\n}\n\n/**\n * Dynamic model function that reads the current model from controller state.\n * This allows runtime model switching via the /models picker.\n */\nexport function getDynamicModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel {\n const agentControllerContext = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n\n const modelId = agentControllerContext?.session?.modelId;\n if (!modelId) {\n // A missing controller context means the run was started without session\n // request context at all (e.g. a signal delivered to an idle thread) —\n // \"use /models\" would mislead there, the user's selection was never the\n // problem.\n if (!agentControllerContext) {\n throw new Error(\n 'No model available: this run started without a controller session context, so no model selection could be resolved.',\n );\n }\n throw new Error('No model selected. Use /models to select a model first.');\n }\n\n const thinkingLevel = resolveRequestThinkingLevel(agentControllerContext, settingsPath);\n\n return resolveModel(modelId, { thinkingLevel, remapForCodexOAuth: true, requestContext });\n}\n\n/**\n * Goal judge model resolver for the agent's `goal.judge` config. Resolves the\n * configured goal judge model through mastracode's gateway so provider\n * credentials (stored in auth storage, not just env) are injected — a bare model\n * id handed to core's default model router would fail to find the API key.\n *\n * Returns `undefined` when no judge model is configured, which keeps the goal\n * step a complete no-op (the goal mechanism requires a judge to do anything).\n *\n * `settingsPath` must be the same source `createMastraCode()` reads from so the\n * judge model and the goal budget (`goalMaxTurns`) come from one config — with a\n * custom `settingsPath` a bare `loadSettings()` here could read a different file\n * and silently turn the goal step into a no-op.\n */\nexport function getGoalJudgeModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | undefined {\n const judgeModelId = loadSettings(settingsPath).models.goalJudgeModel;\n if (!judgeModelId) return undefined;\n return resolveModel(judgeModelId, { remapForCodexOAuth: true, requestContext });\n}\n"],"mappings":"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"}
@@ -54,6 +54,15 @@ export declare function loadAgentInstructions(projectPath: string, configDirName
54
54
  skipGlobal?: boolean;
55
55
  }): InstructionSource[];
56
56
  export declare function getStaticallyLoadedInstructionPaths(projectPath: string, configDirName?: string, projectReader?: InstructionFileReader): string[];
57
+ /** Heading the agent-instructions block is introduced by in the system prompt. */
58
+ export declare const AGENT_INSTRUCTIONS_HEADING = "# Agent Instructions";
59
+ /**
60
+ * Format a single instruction source as it appears in the system prompt.
61
+ *
62
+ * Exported so callers that attribute prompt cost per source (the `/context`
63
+ * audit) measure the exact block that is sent rather than reconstructing it.
64
+ */
65
+ export declare function formatInstructionSource(source: InstructionSource): string;
57
66
  /**
58
67
  * Format loaded instructions into a string for the system prompt.
59
68
  */
@@ -1 +1 @@
1
- {"version":3,"file":"agent-instructions.d.ts","sourceRoot":"","sources":["../../../src/agents/prompts/agent-instructions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAOD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,qBAAqB,CA+BrG;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACV;IACD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC,CA4CA;AAgBD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,aAAa,SAAqB,EAClC,aAAa,GAAE,qBAA2C,EAC1D,EAAE,UAAkB,EAAE,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACpD,iBAAiB,EAAE,CAwDrB;AAED,wBAAgB,mCAAmC,CACjD,WAAW,EAAE,MAAM,EACnB,aAAa,SAAqB,EAClC,aAAa,CAAC,EAAE,qBAAqB,GACpC,MAAM,EAAE,CAEV;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAU5E"}
1
+ {"version":3,"file":"agent-instructions.d.ts","sourceRoot":"","sources":["../../../src/agents/prompts/agent-instructions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAOD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,qBAAqB,CA+BrG;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACV;IACD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC,CA4CA;AAgBD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,aAAa,SAAqB,EAClC,aAAa,GAAE,qBAA2C,EAC1D,EAAE,UAAkB,EAAE,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACpD,iBAAiB,EAAE,CAwDrB;AAED,wBAAgB,mCAAmC,CACjD,WAAW,EAAE,MAAM,EACnB,aAAa,SAAqB,EAClC,aAAa,CAAC,EAAE,qBAAqB,GACpC,MAAM,EAAE,CAEV;AAED,kFAAkF;AAClF,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAIzE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAM5E"}
@@ -186,16 +186,26 @@ function loadAgentInstructions(projectPath, configDirName = DEFAULT_CONFIG_DIR,
186
186
  function getStaticallyLoadedInstructionPaths(projectPath, configDirName = DEFAULT_CONFIG_DIR, projectReader) {
187
187
  return loadAgentInstructions(projectPath, configDirName, projectReader).map((source) => normalize(source.path));
188
188
  }
189
+ /** Heading the agent-instructions block is introduced by in the system prompt. */
190
+ const AGENT_INSTRUCTIONS_HEADING = "# Agent Instructions";
191
+ /**
192
+ * Format a single instruction source as it appears in the system prompt.
193
+ *
194
+ * Exported so callers that attribute prompt cost per source (the `/context`
195
+ * audit) measure the exact block that is sent rather than reconstructing it.
196
+ */
197
+ function formatInstructionSource(source) {
198
+ return `<!-- ${source.scope === "global" ? "Global" : "Project"} instructions from ${source.ref ? `${source.path} (at ref ${source.ref})` : source.path} -->\n${source.content}`;
199
+ }
189
200
  /**
190
201
  * Format loaded instructions into a string for the system prompt.
191
202
  */
192
203
  function formatAgentInstructions(sources) {
193
204
  if (sources.length === 0) return "";
194
- return `\n# Agent Instructions\n\n${sources.map((source) => {
195
- return `<!-- ${source.scope === "global" ? "Global" : "Project"} instructions from ${source.ref ? `${source.path} (at ref ${source.ref})` : source.path} -->\n${source.content}`;
196
- }).join("\n\n")}\n`;
205
+ const sections = sources.map(formatInstructionSource);
206
+ return `\n${AGENT_INSTRUCTIONS_HEADING}\n\n${sections.join("\n\n")}\n`;
197
207
  }
198
208
  //#endregion
199
- export { createGitRefInstructionReader, createGitRefReminderReader, formatAgentInstructions, getStaticallyLoadedInstructionPaths, loadAgentInstructions };
209
+ export { AGENT_INSTRUCTIONS_HEADING, createGitRefInstructionReader, createGitRefReminderReader, formatAgentInstructions, formatInstructionSource, getStaticallyLoadedInstructionPaths, loadAgentInstructions };
200
210
 
201
211
  //# sourceMappingURL=agent-instructions.js.map