copilotkit 4.28.0 → 4.30.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 (97) hide show
  1. package/README.md +317 -36
  2. package/cli-build-info.json +7 -7
  3. package/exporters/claude-sdk/README.md +93 -0
  4. package/exporters/claude-sdk/export_session_store.py +39 -0
  5. package/exporters/claude-sdk/store-export.ts +61 -0
  6. package/index.js +212799 -109146
  7. package/onboarding/index.json +51 -5
  8. package/onboarding/prompts/authenticate/start.md +66 -52
  9. package/onboarding/prompts/conversion/plan.md +3 -3
  10. package/onboarding/prompts/credentials/finalize-plan.md +15 -15
  11. package/onboarding/prompts/credentials/plan.md +25 -29
  12. package/onboarding/prompts/credentials/settle-credentials.md +13 -8
  13. package/onboarding/prompts/credentials/write-plan.md +40 -30
  14. package/onboarding/prompts/deployment/choose-local.md +13 -12
  15. package/onboarding/prompts/deployment/local-evaluation.md +12 -12
  16. package/onboarding/prompts/fallback/best-effort.md +10 -11
  17. package/onboarding/prompts/feature/a2ui/implement.md +7 -5
  18. package/onboarding/prompts/feature/a2ui/plan.md +7 -3
  19. package/onboarding/prompts/feature/a2ui/proof.md +8 -6
  20. package/onboarding/prompts/feature/a2ui/start.md +18 -9
  21. package/onboarding/prompts/feature/channels/implement.md +10 -8
  22. package/onboarding/prompts/feature/channels/plan.md +9 -5
  23. package/onboarding/prompts/feature/channels/proof.md +8 -6
  24. package/onboarding/prompts/feature/channels/start.md +25 -12
  25. package/onboarding/prompts/feature/chat-suggestions/implement.md +7 -5
  26. package/onboarding/prompts/feature/chat-suggestions/plan.md +7 -3
  27. package/onboarding/prompts/feature/chat-suggestions/proof.md +8 -6
  28. package/onboarding/prompts/feature/chat-suggestions/start.md +18 -9
  29. package/onboarding/prompts/feature/complete.md +3 -3
  30. package/onboarding/prompts/feature/learning/implement.md +15 -13
  31. package/onboarding/prompts/feature/learning/plan.md +8 -4
  32. package/onboarding/prompts/feature/learning/proof.md +16 -14
  33. package/onboarding/prompts/feature/learning/start.md +18 -9
  34. package/onboarding/prompts/feature/open-generative-ui/implement.md +7 -5
  35. package/onboarding/prompts/feature/open-generative-ui/plan.md +7 -3
  36. package/onboarding/prompts/feature/open-generative-ui/proof.md +8 -6
  37. package/onboarding/prompts/feature/open-generative-ui/start.md +18 -9
  38. package/onboarding/prompts/feature/realtime-sync/implement.md +8 -6
  39. package/onboarding/prompts/feature/realtime-sync/plan.md +7 -3
  40. package/onboarding/prompts/feature/realtime-sync/proof.md +8 -6
  41. package/onboarding/prompts/feature/realtime-sync/start.md +17 -8
  42. package/onboarding/prompts/feature/rich-threads/implement.md +9 -7
  43. package/onboarding/prompts/feature/rich-threads/plan.md +7 -3
  44. package/onboarding/prompts/feature/rich-threads/proof.md +8 -6
  45. package/onboarding/prompts/feature/rich-threads/start.md +17 -8
  46. package/onboarding/prompts/feature/stop.md +4 -4
  47. package/onboarding/prompts/feature/voice/implement.md +7 -5
  48. package/onboarding/prompts/feature/voice/plan.md +8 -4
  49. package/onboarding/prompts/feature/voice/proof.md +8 -6
  50. package/onboarding/prompts/feature/voice/start.md +18 -9
  51. package/onboarding/prompts/framework/ag2.md +4 -11
  52. package/onboarding/prompts/framework/agno.md +4 -11
  53. package/onboarding/prompts/framework/built-in.md +3 -3
  54. package/onboarding/prompts/framework/claude-sdk-python.md +3 -3
  55. package/onboarding/prompts/framework/claude-sdk-typescript.md +3 -3
  56. package/onboarding/prompts/framework/crewai-flows.md +6 -12
  57. package/onboarding/prompts/framework/custom-ag-ui.md +5 -11
  58. package/onboarding/prompts/framework/deep-agents.md +5 -11
  59. package/onboarding/prompts/framework/google-adk.md +4 -8
  60. package/onboarding/prompts/framework/langgraph-fastapi.md +4 -10
  61. package/onboarding/prompts/framework/langgraph-python.md +4 -10
  62. package/onboarding/prompts/framework/langgraph-typescript.md +5 -11
  63. package/onboarding/prompts/framework/llamaindex.md +4 -10
  64. package/onboarding/prompts/framework/mastra.md +4 -10
  65. package/onboarding/prompts/framework/ms-agent-dotnet.md +6 -13
  66. package/onboarding/prompts/framework/ms-agent-harness-dotnet.md +7 -13
  67. package/onboarding/prompts/framework/ms-agent-python.md +5 -11
  68. package/onboarding/prompts/framework/pydantic-ai.md +4 -10
  69. package/onboarding/prompts/framework/strands-python.md +4 -10
  70. package/onboarding/prompts/framework/strands-typescript.md +4 -10
  71. package/onboarding/prompts/frontend/angular.md +4 -4
  72. package/onboarding/prompts/frontend/nextjs.md +4 -4
  73. package/onboarding/prompts/frontend/plan.md +10 -10
  74. package/onboarding/prompts/frontend/react-native.md +3 -3
  75. package/onboarding/prompts/frontend/react-spa.md +3 -3
  76. package/onboarding/prompts/frontend/vue.md +3 -3
  77. package/onboarding/prompts/implementation/build-and-validate.md +48 -15
  78. package/onboarding/prompts/proof/complete.md +22 -19
  79. package/onboarding/prompts/proof/oss-baseline.md +21 -5
  80. package/onboarding/prompts/proof/round-trip.md +55 -13
  81. package/onboarding/prompts/research/gather.md +60 -43
  82. package/onboarding/prompts/research/merge.md +6 -5
  83. package/onboarding/prompts/research/preflight.md +2 -2
  84. package/onboarding/prompts/research/route.md +5 -5
  85. package/onboarding/prompts/setup/questions.md +11 -9
  86. package/onboarding/prompts/starter/clone.md +78 -76
  87. package/onboarding/prompts/starter/setup.md +111 -0
  88. package/onboarding/prompts/stopped/declined.md +44 -0
  89. package/onboarding/prompts/stopped/run-failed.md +6 -6
  90. package/onboarding/prompts/subagent/create-plan.md +29 -4
  91. package/onboarding/prompts/subagent/implement-and-validate.md +31 -3
  92. package/onboarding/prompts/subagent/inspect-repository.md +17 -4
  93. package/onboarding/prompts/subagent/prove-oss-baseline.md +24 -1
  94. package/onboarding/prompts/subagent/prove-round-trip.md +43 -7
  95. package/onboarding/prompts/unsupported/no-validated-path.md +6 -6
  96. package/package.json +4 -1
  97. package/release/release-tool.js +383 -112
@@ -63,23 +63,120 @@ var require_starter_source_policy = __commonJS({
63
63
  }
64
64
  });
65
65
 
66
+ // apps/cli/starter-model-vendors.cjs
67
+ var require_starter_model_vendors = __commonJS({
68
+ "apps/cli/starter-model-vendors.cjs"(exports, module) {
69
+ "use strict";
70
+ init_define_CLI_LOCAL_EVALUATION_SUPPORT();
71
+ var RUNS_ALL = Object.freeze(["openai", "anthropic", "google"]);
72
+ var OPENAI_VENDORS = Object.freeze(["openai", "openai-compatible"]);
73
+ var BUILT_IN_VENDORS = Object.freeze(["openai", "openai-compatible", "anthropic", "google"]);
74
+ var ADK_VENDORS = Object.freeze(["google", "openai", "openai-compatible"]);
75
+ var ALL_VENDORS = BUILT_IN_VENDORS;
76
+ var ADK_ALL_VENDORS = Object.freeze(["google", "openai", "openai-compatible", "anthropic"]);
77
+ var NO_GOOGLE_VENDORS = Object.freeze(["openai", "openai-compatible", "anthropic"]);
78
+ var BEDROCK_ONLY = "runs Amazon Bedrock models only, so it takes no --model-vendor";
79
+ var VENDOR_KEY_VARIABLES = Object.freeze({
80
+ openai: "OPENAI_API_KEY",
81
+ "openai-compatible": "OPENAI_API_KEY",
82
+ anthropic: "ANTHROPIC_API_KEY",
83
+ google: "GOOGLE_API_KEY"
84
+ });
85
+ var row = (row2) => Object.freeze(row2);
86
+ var STARTER_OWN_ROWS = Object.freeze({
87
+ "langgraph-py": row({ onboarding: "langgraph-python", runs: RUNS_ALL, offers: ALL_VENDORS, defaultModel: "openai:gpt-5.4-mini", modelConfig: ".env", clone: { order: 5, name: "LangGraph Python", frontend: "Next.js" } }),
88
+ "langgraph-js": row({ onboarding: "langgraph-typescript", runs: RUNS_ALL, offers: ALL_VENDORS, defaultModel: "openai:gpt-5.4", modelConfig: ".env", clone: { order: 6, name: "LangGraph TypeScript", frontend: "Next.js" } }),
89
+ "langgraph-fastapi": row({ onboarding: "langgraph-fastapi", runs: RUNS_ALL, offers: ALL_VENDORS, defaultModel: "openai:gpt-5.4", modelConfig: ".env" }),
90
+ "claude-sdk-typescript": row({ onboarding: "claude-sdk-typescript", runs: Object.freeze(["anthropic"]), offers: Object.freeze(["anthropic"]), defaultModel: "anthropic:claude-sonnet-5", modelConfig: ".env", clone: { order: 3, name: "Claude Agent SDK TypeScript", frontend: "Next.js" } }),
91
+ "claude-sdk-python": row({ onboarding: "claude-sdk-python", runs: Object.freeze(["anthropic"]), offers: Object.freeze(["anthropic"]), defaultModel: "anthropic:claude-sonnet-5", modelConfig: ".env", clone: { order: 2, name: "Claude Agent SDK Python", frontend: "Next.js" } }),
92
+ flows: row({ onboarding: "crewai-flows", runs: RUNS_ALL, offers: OPENAI_VENDORS, defaultModel: "openai:gpt-5-mini", modelConfig: ".env", clone: { order: 4, name: "CrewAI Flows", frontend: "Next.js" } }),
93
+ mastra: row({ onboarding: "mastra", runs: RUNS_ALL, offers: ALL_VENDORS, defaultModel: "openai:gpt-5-mini", modelConfig: ".env", clone: { order: 12, name: "Mastra", frontend: "Next.js" } }),
94
+ "pydantic-ai": row({ onboarding: "pydantic-ai", runs: RUNS_ALL, offers: ALL_VENDORS, defaultModel: "openai:gpt-5-mini", modelConfig: ".env", clone: { order: 13, name: "Pydantic AI", frontend: "Next.js" } }),
95
+ llamaindex: row({ onboarding: "llamaindex", runs: RUNS_ALL, offers: OPENAI_VENDORS, defaultModel: "openai:gpt-5-mini", modelConfig: ".env", clone: { order: 7, name: "LlamaIndex", frontend: "Next.js" } }),
96
+ agno: row({ onboarding: "agno", runs: RUNS_ALL, offers: ALL_VENDORS, defaultModel: "openai:gpt-4o", modelConfig: ".env", clone: { order: 1, name: "Agno", frontend: "Next.js" } }),
97
+ ag2: row({ onboarding: "ag2", runs: null, offers: OPENAI_VENDORS, defaultModel: null, modelConfig: "hard-coded", noModelFlags: "hard-codes its model and does not read COPILOTKIT_AGENT_MODEL, so it takes no --model-vendor" }),
98
+ adk: row({ onboarding: "google-adk", runs: RUNS_ALL, offers: ADK_ALL_VENDORS, defaultModel: "google:gemini-3.8-flash", modelConfig: ".env", clone: { order: 8, name: "ADK", frontend: "Next.js" } }),
99
+ // Angular + ADK runs the ADK starter's agent code, so it shares its row.
100
+ "aws-strands-py": row({ onboarding: "strands-python", runs: RUNS_ALL, offers: NO_GOOGLE_VENDORS, defaultModel: "openai:gpt-5.4", modelConfig: ".env", clone: { order: 14, name: "Strands Agents Python", frontend: "Next.js" } }),
101
+ "aws-strands-ts": row({ onboarding: "strands-typescript", runs: RUNS_ALL, offers: NO_GOOGLE_VENDORS, defaultModel: "openai:gpt-4o", modelConfig: ".env", clone: { order: 15, name: "Strands Agents TypeScript", frontend: "Next.js" } }),
102
+ a2a: row({ onboarding: null, runs: RUNS_ALL, offers: ADK_VENDORS, defaultModel: "google:gemini-3.8-flash", modelConfig: ".env" }),
103
+ "microsoft-agent-framework-dotnet": row({ onboarding: "ms-agent-dotnet", runs: RUNS_ALL, offers: OPENAI_VENDORS, defaultModel: "openai:gpt-5-mini", modelConfig: "user-secrets", noModelFlags: 'reads its model from dotnet user-secrets, not an env file, so it takes no --model-vendor. After init, run `dotnet user-secrets set COPILOTKIT_AGENT_MODEL "<provider>:<model>"` in its agent folder', clone: { order: 11, name: "Microsoft Agent Framework .NET", frontend: "Next.js" } }),
104
+ "microsoft-agent-framework-py": row({ onboarding: "ms-agent-python", runs: RUNS_ALL, offers: NO_GOOGLE_VENDORS, defaultModel: "openai:gpt-4o-mini", modelConfig: "agent/.env", clone: { order: 10, name: "Microsoft Agent Framework Python", frontend: "Next.js" } }),
105
+ "mcp-apps": row({ onboarding: null, runs: RUNS_ALL, offers: BUILT_IN_VENDORS, defaultModel: "openai:gpt-5-mini", modelConfig: ".env" }),
106
+ "agentcore-langgraph": row({ onboarding: null, runs: Object.freeze([]), offers: Object.freeze([]), defaultModel: null, modelConfig: "none", noModelFlags: BEDROCK_ONLY }),
107
+ "agentcore-strands": row({ onboarding: null, runs: Object.freeze([]), offers: Object.freeze([]), defaultModel: null, modelConfig: "none", noModelFlags: BEDROCK_ONLY })
108
+ });
109
+ var SHARED_ROWS = Object.freeze({
110
+ "adk-angular": "adk",
111
+ a2ui: "langgraph-py",
112
+ opengenui: "langgraph-py"
113
+ });
114
+ var SHARED_CLONE = Object.freeze({
115
+ "adk-angular": Object.freeze({ order: 9, name: "ADK", frontend: "Angular" })
116
+ });
117
+ var STARTER_MODEL_VENDORS2 = Object.freeze({
118
+ ...STARTER_OWN_ROWS,
119
+ ...Object.fromEntries(
120
+ Object.entries(SHARED_ROWS).map(([starter, parent]) => [
121
+ starter,
122
+ row({ ...STARTER_OWN_ROWS[parent], onboarding: null, clone: SHARED_CLONE[starter] })
123
+ ])
124
+ )
125
+ });
126
+ var ONBOARDING_ONLY_MODEL_VENDORS = Object.freeze({
127
+ "built-in": row({ runs: RUNS_ALL, offers: BUILT_IN_VENDORS }),
128
+ "custom-ag-ui": row({ runs: RUNS_ALL, offers: OPENAI_VENDORS }),
129
+ "deep-agents": row({ runs: RUNS_ALL, offers: OPENAI_VENDORS }),
130
+ "ms-agent-harness-dotnet": row({ runs: RUNS_ALL, offers: OPENAI_VENDORS })
131
+ });
132
+ var STARTER_OF_ONBOARDING = new Map(
133
+ Object.values(STARTER_MODEL_VENDORS2).filter((each) => each.onboarding !== null).map((each) => [each.onboarding, each])
134
+ );
135
+ function onboardingRow(framework) {
136
+ const found = STARTER_OF_ONBOARDING.get(framework) ?? ONBOARDING_ONLY_MODEL_VENDORS[framework];
137
+ if (found === void 0)
138
+ throw new Error(`No model vendor row for ${framework}.`);
139
+ return found;
140
+ }
141
+ var ONBOARDING_FRAMEWORK_MODEL_VENDORS = Object.freeze(
142
+ Object.fromEntries(
143
+ [...STARTER_OF_ONBOARDING.keys(), ...Object.keys(ONBOARDING_ONLY_MODEL_VENDORS)].map(
144
+ (framework) => [framework, onboardingRow(framework).offers]
145
+ )
146
+ )
147
+ );
148
+ function heldBackVendorsOf2(framework) {
149
+ const found = onboardingRow(framework);
150
+ return (found.runs ?? RUNS_ALL).filter((vendor) => !found.offers.includes(vendor));
151
+ }
152
+ module.exports = {
153
+ ONBOARDING_FRAMEWORK_MODEL_VENDORS,
154
+ ONBOARDING_ONLY_MODEL_VENDORS,
155
+ SHARED_ROWS,
156
+ STARTER_MODEL_VENDORS: STARTER_MODEL_VENDORS2,
157
+ VENDOR_KEY_VARIABLES,
158
+ heldBackVendorsOf: heldBackVendorsOf2
159
+ };
160
+ }
161
+ });
162
+
66
163
  // apps/cli/src/release/release-tool.ts
67
164
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
68
165
 
69
166
  // apps/cli/src/release/cli-release.ts
70
167
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
71
168
  import { execFileSync as execFileSync2 } from "node:child_process";
72
- import * as fs6 from "node:fs";
73
- import * as path6 from "node:path";
169
+ import * as fs7 from "node:fs";
170
+ import * as path7 from "node:path";
74
171
 
75
172
  // apps/cli/src/starter-source-catalog.ts
76
173
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
77
174
  var import_starter_source_policy = __toESM(require_starter_source_policy(), 1);
78
- function copilotKitStarter(path7) {
175
+ function copilotKitStarter(path8) {
79
176
  return {
80
177
  owner: "CopilotKit",
81
178
  repo: "CopilotKit",
82
- path: path7,
179
+ path: path8,
83
180
  mode: "sparse",
84
181
  ownership: "first-party"
85
182
  };
@@ -938,10 +1035,10 @@ function mergeDefs(...defs) {
938
1035
  function cloneDef(schema) {
939
1036
  return mergeDefs(schema._zod.def);
940
1037
  }
941
- function getElementAtPath(obj, path7) {
942
- if (!path7)
1038
+ function getElementAtPath(obj, path8) {
1039
+ if (!path8)
943
1040
  return obj;
944
- return path7.reduce((acc, key) => acc?.[key], obj);
1041
+ return path8.reduce((acc, key) => acc?.[key], obj);
945
1042
  }
946
1043
  function promiseAllObject(promisesObj) {
947
1044
  const keys = Object.keys(promisesObj);
@@ -1324,11 +1421,11 @@ function aborted(x, startIndex = 0) {
1324
1421
  }
1325
1422
  return false;
1326
1423
  }
1327
- function prefixIssues(path7, issues) {
1424
+ function prefixIssues(path8, issues) {
1328
1425
  return issues.map((iss) => {
1329
1426
  var _a2;
1330
1427
  (_a2 = iss).path ?? (_a2.path = []);
1331
- iss.path.unshift(path7);
1428
+ iss.path.unshift(path8);
1332
1429
  return iss;
1333
1430
  });
1334
1431
  }
@@ -1511,7 +1608,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
1511
1608
  }
1512
1609
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
1513
1610
  const result = { errors: [] };
1514
- const processError = (error49, path7 = []) => {
1611
+ const processError = (error49, path8 = []) => {
1515
1612
  var _a2, _b;
1516
1613
  for (const issue2 of error49.issues) {
1517
1614
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -1521,7 +1618,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1521
1618
  } else if (issue2.code === "invalid_element") {
1522
1619
  processError({ issues: issue2.issues }, issue2.path);
1523
1620
  } else {
1524
- const fullpath = [...path7, ...issue2.path];
1621
+ const fullpath = [...path8, ...issue2.path];
1525
1622
  if (fullpath.length === 0) {
1526
1623
  result.errors.push(mapper(issue2));
1527
1624
  continue;
@@ -1553,8 +1650,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1553
1650
  }
1554
1651
  function toDotPath(_path) {
1555
1652
  const segs = [];
1556
- const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1557
- for (const seg of path7) {
1653
+ const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1654
+ for (const seg of path8) {
1558
1655
  if (typeof seg === "number")
1559
1656
  segs.push(`[${seg}]`);
1560
1657
  else if (typeof seg === "symbol")
@@ -13608,13 +13705,13 @@ function resolveRef(ref, ctx) {
13608
13705
  if (!ref.startsWith("#")) {
13609
13706
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
13610
13707
  }
13611
- const path7 = ref.slice(1).split("/").filter(Boolean);
13612
- if (path7.length === 0) {
13708
+ const path8 = ref.slice(1).split("/").filter(Boolean);
13709
+ if (path8.length === 0) {
13613
13710
  return ctx.rootSchema;
13614
13711
  }
13615
13712
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
13616
- if (path7[0] === defsKey) {
13617
- const key = path7[1];
13713
+ if (path8[0] === defsKey) {
13714
+ const key = path8[1];
13618
13715
  if (!key || !ctx.defs[key]) {
13619
13716
  throw new Error(`Reference not found: ${ref}`);
13620
13717
  }
@@ -14542,11 +14639,11 @@ async function resolveCopilotKitSource(options) {
14542
14639
  }
14543
14640
  }
14544
14641
  const uniquePaths = options.validateStarterPaths === false ? [] : [...new Set(options.starterPaths)];
14545
- for (const path7 of uniquePaths) {
14642
+ for (const path8 of uniquePaths) {
14546
14643
  const content = await requestGitHub(
14547
- `${apiRoot}/contents/${encodeURIComponent(path7)}?ref=${canonicalCommit}`,
14644
+ `${apiRoot}/contents/${encodeURIComponent(path8)}?ref=${canonicalCommit}`,
14548
14645
  "contents",
14549
- { path: path7, canonicalCommit },
14646
+ { path: path8, canonicalCommit },
14550
14647
  fetchImpl,
14551
14648
  options.githubToken,
14552
14649
  options.requestTimeoutMs
@@ -14557,14 +14654,14 @@ async function resolveCopilotKitSource(options) {
14557
14654
  if (content !== null && typeof content === "object" && !Array.isArray(content) && "type" in content && content.type === "file") {
14558
14655
  throw new ReleasePreflightError(
14559
14656
  "STARTER_PATH_NOT_DIRECTORY",
14560
- `The CopilotKit starter path ${path7} is not a directory`,
14561
- { path: path7, canonicalCommit }
14657
+ `The CopilotKit starter path ${path8} is not a directory`,
14658
+ { path: path8, canonicalCommit }
14562
14659
  );
14563
14660
  }
14564
14661
  throw new ReleasePreflightError(
14565
14662
  "GITHUB_RESPONSE_INVALID",
14566
- `GitHub returned invalid contents metadata for ${path7}`,
14567
- { path: path7, canonicalCommit }
14663
+ `GitHub returned invalid contents metadata for ${path8}`,
14664
+ { path: path8, canonicalCommit }
14568
14665
  );
14569
14666
  }
14570
14667
  return {
@@ -14809,10 +14906,86 @@ function planReleaseReconciliation(options) {
14809
14906
 
14810
14907
  // apps/cli/src/release/smoke-starters.ts
14811
14908
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
14909
+
14910
+ // apps/cli/src/release/starter-vendor-drift.ts
14911
+ init_define_CLI_LOCAL_EVALUATION_SUPPORT();
14912
+ import fs from "node:fs";
14913
+ import path from "node:path";
14914
+
14915
+ // apps/cli/src/services/starter-model-vendors.ts
14916
+ init_define_CLI_LOCAL_EVALUATION_SUPPORT();
14917
+ var import_starter_model_vendors = __toESM(require_starter_model_vendors(), 1);
14918
+ var STARTER_MODEL_VENDORS = import_starter_model_vendors.STARTER_MODEL_VENDORS;
14919
+
14920
+ // apps/cli/src/release/starter-vendor-drift.ts
14921
+ var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", ".venv", ".next", "dist", "build", "__pycache__", ".git"]);
14922
+ var CODE_FILE = /\.(?:py|ts|tsx|mts|cts|js|mjs|cjs|cs)$/u;
14923
+ var TEST_FILE = /(?:^|[/\\])(?:tests?|__tests__|e2e)[/\\]|(?:^|[/\\])test_|[._-](?:test|spec)\.[a-z]+$/u;
14924
+ var PROVIDER_LITERAL = /["'](openai|anthropic|google|gemini)["']/gu;
14925
+ var COMMENT_LINE = /^\s*(?:\/\/|#|\*|\/\*)/u;
14926
+ var IMPORT_LINE = /^\s*(?:import\b|from\s+\S+\s+import\b|using\b)|\bfrom\s+["'][^"']*["']|\brequire\(\s*["']/u;
14927
+ var TYPE_ONLY_VENDOR = /(?:["'](?:openai|anthropic|google|gemini)["']\s*\|\s*)+["'](?:openai|anthropic|google|gemini)["']|Literal\[[^\]]*\]/gu;
14928
+ function codeLines(source) {
14929
+ return source.split(/\r?\n/u).filter((line) => !COMMENT_LINE.test(line) && !IMPORT_LINE.test(line)).map((line) => line.replace(TYPE_ONLY_VENDOR, ""));
14930
+ }
14931
+ function codeFiles(root) {
14932
+ const found = [];
14933
+ const walk = (dir) => {
14934
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
14935
+ if (entry.isDirectory()) {
14936
+ if (!SKIPPED_DIRECTORIES.has(entry.name))
14937
+ walk(path.join(dir, entry.name));
14938
+ } else if (CODE_FILE.test(entry.name)) {
14939
+ const file2 = path.join(dir, entry.name);
14940
+ if (!TEST_FILE.test(path.relative(root, file2)))
14941
+ found.push(file2);
14942
+ }
14943
+ }
14944
+ };
14945
+ walk(root);
14946
+ return found;
14947
+ }
14948
+ function readStarterModelFacts(projectDir) {
14949
+ const envExample = path.join(projectDir, ".env.example");
14950
+ const line = fs.existsSync(envExample) ? fs.readFileSync(envExample, "utf8").split(/\r?\n/u).find((each) => /^\s*COPILOTKIT_AGENT_MODEL=/u.test(each)) : void 0;
14951
+ const value = line?.slice(line.indexOf("=") + 1).trim() ?? "";
14952
+ const providers = /* @__PURE__ */ new Set();
14953
+ for (const file2 of codeFiles(projectDir)) {
14954
+ const lines = codeLines(fs.readFileSync(file2, "utf8"));
14955
+ if (!lines.some((line2) => line2.includes("COPILOTKIT_AGENT_MODEL")))
14956
+ continue;
14957
+ for (const line2 of lines) {
14958
+ for (const [, name] of line2.matchAll(PROVIDER_LITERAL)) {
14959
+ providers.add(name === "gemini" ? "google" : name);
14960
+ }
14961
+ }
14962
+ }
14963
+ return { defaultModel: value === "" ? null : value, providers: [...providers].sort() };
14964
+ }
14965
+ function compareStarterModelFacts(framework, facts) {
14966
+ const row = STARTER_MODEL_VENDORS[framework];
14967
+ const problems = [];
14968
+ if (facts.defaultModel !== row.defaultModel) {
14969
+ problems.push(
14970
+ `COPILOTKIT_AGENT_MODEL in .env.example is ${facts.defaultModel ?? "unset"}; the table says ${row.defaultModel ?? "unset"}.`
14971
+ );
14972
+ }
14973
+ if (row.runs !== null) {
14974
+ const expected = [...row.runs].sort();
14975
+ if (expected.join(",") !== facts.providers.join(",")) {
14976
+ problems.push(
14977
+ `The model code handles ${facts.providers.join(", ") || "no vendor"}; the table says ${expected.join(", ") || "no vendor"}.`
14978
+ );
14979
+ }
14980
+ }
14981
+ return problems;
14982
+ }
14983
+
14984
+ // apps/cli/src/release/smoke-starters.ts
14812
14985
  import { execFile } from "node:child_process";
14813
- import * as fs5 from "node:fs";
14986
+ import * as fs6 from "node:fs";
14814
14987
  import * as os2 from "node:os";
14815
- import * as path5 from "node:path";
14988
+ import * as path6 from "node:path";
14816
14989
 
14817
14990
  // apps/cli/src/types.ts
14818
14991
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
@@ -14834,6 +15007,23 @@ function defineFlags(defs) {
14834
15007
  );
14835
15008
  }
14836
15009
  var FLAG_DEFINITIONS = defineFlags({
15010
+ "ops.billing-usage": {
15011
+ purpose: "Keep the Ops usage, billing and deployments previews dark, and the ops-api deployments routes (PE-972) unmounted, until the PAYG and deployments APIs are ready.",
15012
+ owner: "ops",
15013
+ createdAt: "2026-10-20",
15014
+ status: "rollout",
15015
+ surfaces: ["ops-frontend", "ops-api"],
15016
+ defaultByEnv: { dev: true, ci: true, prod: false }
15017
+ },
15018
+ "threads.bounded-history": {
15019
+ purpose: "Limit runtime messages and PostgreSQL connect replay to recent complete runs.",
15020
+ owner: "threads",
15021
+ createdAt: "2026-10-16",
15022
+ status: "rollout",
15023
+ surfaces: ["app-api", "realtime-gateway"],
15024
+ // Requires completed schema/backfill and replay readiness in every environment.
15025
+ defaultByEnv: { dev: false, ci: false, prod: false }
15026
+ },
14837
15027
  // Keep all environments dark until the CLI reader ships.
14838
15028
  // EULA tests opt in explicitly; production also needs approved terms.
14839
15029
  "self-hosted.local-evaluation-eula": {
@@ -14876,6 +15066,52 @@ var FLAG_DEFINITIONS = defineFlags({
14876
15066
  defaultByEnv: { dev: true, ci: true, prod: false },
14877
15067
  envVar: "REALTIME_GATEWAY_BOUNDED_REPLAY_ENABLED"
14878
15068
  },
15069
+ // The gateway mirrors this default in config/runtime.exs and reads the derived
15070
+ // FF_THREADS_RUN_USAGE_TELEMETRY override. It stays off in prod until the OTLP
15071
+ // receiver allowlists eip.thread.run_usage and the hash secret is in place.
15072
+ "threads.run-usage-telemetry": {
15073
+ purpose: "Gates the eip.thread.run_usage product event: one AG-UI event and byte count per completed run, sent by the gateway analytics projector to the OTLP product-event receiver for the Ops Usage tab.",
15074
+ owner: "realtime",
15075
+ createdAt: "2026-10-16",
15076
+ status: "rollout",
15077
+ surfaces: ["realtime-gateway"],
15078
+ defaultByEnv: { dev: true, ci: true, prod: false }
15079
+ },
15080
+ // `active`: an operational kill switch, default-on in every env because it
15081
+ // fixes app-api heap exhaustion (PE-803). Set
15082
+ // FF_THREADS_MESSAGES_COALESCED_READS=false to send every raw run event to
15083
+ // app-api again. Remove it with the raw path once the merged reads have run
15084
+ // cleanly in production.
15085
+ "threads.messages-coalesced-reads": {
15086
+ purpose: "Merge adjacent streamed text and tool-argument deltas in Postgres before app-api rebuilds thread messages.",
15087
+ owner: "threads",
15088
+ createdAt: "2026-10-13",
15089
+ status: "active",
15090
+ surfaces: ["app-api"],
15091
+ defaultByEnv: { dev: true, ci: true, prod: true }
15092
+ },
15093
+ // `active` (not `rollout`): an operational kill-switch for the incident fix
15094
+ // in PE-811, default-on in every env. Set FF_THREADS_TRANSCRIPT_CACHE=false
15095
+ // to stop reading and writing stored transcripts without a new build.
15096
+ "threads.transcript-cache": {
15097
+ purpose: "Serve finished thread transcripts from object storage instead of rebuilding them on every read; operational kill-switch.",
15098
+ owner: "platform",
15099
+ createdAt: "2026-10-14",
15100
+ status: "active",
15101
+ surfaces: ["app-api"],
15102
+ defaultByEnv: { dev: true, ci: true, prod: true }
15103
+ },
15104
+ // `active` (not `rollout`): an operational kill-switch for the PE-811 rebuild
15105
+ // storm, default-on in every env. Set FF_THREADS_TRANSCRIPT_REBUILD_LEASE=false
15106
+ // to let every pod rebuild a thread on its own again without a new build.
15107
+ "threads.transcript-rebuild-lease": {
15108
+ purpose: "Let one app-api pod at a time rebuild a thread transcript while the others wait for its stored result; operational kill-switch.",
15109
+ owner: "platform",
15110
+ createdAt: "2026-10-16",
15111
+ status: "active",
15112
+ surfaces: ["app-api"],
15113
+ defaultByEnv: { dev: true, ci: true, prod: true }
15114
+ },
14879
15115
  // `active` (not `rollout`): a long-lived operational kill-switch, default-on
14880
15116
  // in every env; `envVar` adopts the pre-existing INSPECT_ROUTES_ENABLED name.
14881
15117
  "inspect.routes": {
@@ -14954,6 +15190,17 @@ var FLAG_DEFINITIONS = defineFlags({
14954
15190
  surfaces: ["app-api", "realtime-gateway", "app-frontend"],
14955
15191
  defaultByEnv: { dev: false, ci: true, prod: false }
14956
15192
  },
15193
+ // Hosted PAYG early access (PE-929): a placeholder until hosted pay as you go
15194
+ // exists. On in prod: it stays inert until someone follows the website's
15195
+ // hosted PAYG link, because the callout shows only for a waitlist row.
15196
+ "hosted-payg.waitlist": {
15197
+ purpose: "Gates the hosted pay-as-you-go early-access waitlist routes in app-api; the web app shows its callout only when they answer.",
15198
+ owner: "payg",
15199
+ createdAt: "2026-10-20",
15200
+ status: "rollout",
15201
+ surfaces: ["app-api"],
15202
+ defaultByEnv: { dev: true, ci: true, prod: true }
15203
+ },
14957
15204
  "analytics.pipeline": {
14958
15205
  purpose: "Gates project-scoped analytics reads and realtime projection while the durable pipeline rolls out.",
14959
15206
  owner: "analytics",
@@ -14963,6 +15210,17 @@ var FLAG_DEFINITIONS = defineFlags({
14963
15210
  defaultByEnv: { dev: false, ci: false, prod: false },
14964
15211
  envVar: "ANALYTICS_ENABLED"
14965
15212
  },
15213
+ // PE-962: shows usage against the free hosted monthly interaction cap.
15214
+ // Interaction counts are fixtures (APP_FREE_CAP_FIXTURE_INTERACTIONS) until
15215
+ // PE-931 meters real interactions; keep production dark until then.
15216
+ "hosted-payg.free-cap": {
15217
+ purpose: "Enables free hosted interaction usage and the cap check for manual Learning starts in app-api; the web app shows the cap card only when the metric is available.",
15218
+ owner: "payg",
15219
+ createdAt: "2026-10-21",
15220
+ status: "rollout",
15221
+ surfaces: ["app-api"],
15222
+ defaultByEnv: { dev: true, ci: true, prod: false }
15223
+ },
14966
15224
  "ops.stripe-billing-v1": {
14967
15225
  purpose: "Gates the direct Stripe Checkout, Portal, projection, and provider-aware billing API during rollout.",
14968
15226
  owner: "ops",
@@ -14984,25 +15242,25 @@ init_define_CLI_LOCAL_EVALUATION_SUPPORT();
14984
15242
 
14985
15243
  // apps/cli/src/config.ts
14986
15244
  function getTemplateRef() {
14987
- return true ? "c616389550105d5a96d74501f77c6921aa79ecee" : "main";
15245
+ return true ? "7e8e10bdd3f032fdda93a66aecea99e711aa37db" : "main";
14988
15246
  }
14989
15247
 
14990
15248
  // apps/cli/src/services/agentcore-config.ts
14991
15249
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
14992
- import * as fs from "node:fs";
14993
- import * as path from "node:path";
15250
+ import * as fs2 from "node:fs";
15251
+ import * as path2 from "node:path";
14994
15252
  async function configureAgentCore(projectDir, variant) {
14995
15253
  const isLanggraph = variant === "agentcore-langgraph";
14996
15254
  const pattern = isLanggraph ? "langgraph-single-agent" : "strands-single-agent";
14997
15255
  const suffix = isLanggraph ? "-lg" : "-st";
14998
- const examplePath = path.join(projectDir, "config.yaml.example");
14999
- const configPath = path.join(projectDir, "config.yaml");
15000
- if (!fs.existsSync(examplePath)) {
15256
+ const examplePath = path2.join(projectDir, "config.yaml.example");
15257
+ const configPath = path2.join(projectDir, "config.yaml");
15258
+ if (!fs2.existsSync(examplePath)) {
15001
15259
  throw new Error(
15002
15260
  `config.yaml.example not found in the AgentCore template at "${projectDir}". The downloaded template may be incomplete. Please try again.`
15003
15261
  );
15004
15262
  }
15005
- let content = fs.readFileSync(examplePath, "utf-8");
15263
+ let content = fs2.readFileSync(examplePath, "utf-8");
15006
15264
  const patternRegex = /^(\s*pattern:\s*)\S+(.*)$/m;
15007
15265
  const stackRegex = /^(\s*stack_name_base:\s*)\S+(.*)$/m;
15008
15266
  if (!patternRegex.test(content) || !stackRegex.test(content)) {
@@ -15015,44 +15273,44 @@ async function configureAgentCore(projectDir, variant) {
15015
15273
  stackRegex,
15016
15274
  `$1my-copilotkit-agentcore${suffix}$2`
15017
15275
  );
15018
- fs.writeFileSync(configPath, content, "utf-8");
15276
+ fs2.writeFileSync(configPath, content, "utf-8");
15019
15277
  const removeAgent = isLanggraph ? "strands-single-agent" : "langgraph-single-agent";
15020
15278
  const removeScript = isLanggraph ? "deploy-strands.sh" : "deploy-langgraph.sh";
15021
15279
  const keepScript = isLanggraph ? "deploy-langgraph.sh" : "deploy-strands.sh";
15022
- fs.rmSync(path.join(projectDir, "agents", removeAgent), {
15280
+ fs2.rmSync(path2.join(projectDir, "agents", removeAgent), {
15023
15281
  recursive: true,
15024
15282
  force: true
15025
15283
  });
15026
- fs.rmSync(path.join(projectDir, removeScript), { force: true });
15027
- fs.rmSync(path.join(projectDir, "infra-terraform"), {
15284
+ fs2.rmSync(path2.join(projectDir, removeScript), { force: true });
15285
+ fs2.rmSync(path2.join(projectDir, "infra-terraform"), {
15028
15286
  recursive: true,
15029
15287
  force: true
15030
15288
  });
15031
- const keepScriptPath = path.join(projectDir, keepScript);
15032
- if (fs.existsSync(keepScriptPath)) {
15033
- fs.renameSync(keepScriptPath, path.join(projectDir, "deploy.sh"));
15289
+ const keepScriptPath = path2.join(projectDir, keepScript);
15290
+ if (fs2.existsSync(keepScriptPath)) {
15291
+ fs2.renameSync(keepScriptPath, path2.join(projectDir, "deploy.sh"));
15034
15292
  }
15035
- const deployShPath = path.join(projectDir, "deploy.sh");
15036
- if (fs.existsSync(deployShPath)) {
15037
- let deployContent = fs.readFileSync(deployShPath, "utf-8");
15293
+ const deployShPath = path2.join(projectDir, "deploy.sh");
15294
+ if (fs2.existsSync(deployShPath)) {
15295
+ let deployContent = fs2.readFileSync(deployShPath, "utf-8");
15038
15296
  deployContent = deployContent.replace(/\(isolated from deploy-(?:langgraph|strands)\.sh\)\s*/g, "").replace(/# Using Terraform instead\?.*\n/g, "");
15039
- fs.writeFileSync(deployShPath, deployContent, "utf-8");
15297
+ fs2.writeFileSync(deployShPath, deployContent, "utf-8");
15040
15298
  }
15041
- const configYamlPath = path.join(projectDir, "config.yaml");
15042
- if (fs.existsSync(configYamlPath)) {
15043
- let configContent = fs.readFileSync(configYamlPath, "utf-8");
15299
+ const configYamlPath = path2.join(projectDir, "config.yaml");
15300
+ if (fs2.existsSync(configYamlPath)) {
15301
+ let configContent = fs2.readFileSync(configYamlPath, "utf-8");
15044
15302
  configContent = configContent.replace(
15045
15303
  /# overwritten by deploy-langgraph\.sh \/ deploy-strands\.sh/g,
15046
15304
  "# set by the CLI \u2014 do not change"
15047
15305
  );
15048
- fs.writeFileSync(configYamlPath, configContent, "utf-8");
15306
+ fs2.writeFileSync(configYamlPath, configContent, "utf-8");
15049
15307
  }
15050
15308
  const agentShortName = isLanggraph ? "langgraph" : "strands";
15051
15309
  const otherShortName = isLanggraph ? "strands" : "langgraph";
15052
15310
  for (const relPath of ["docker/docker-compose.yml", "docker/up.sh"]) {
15053
- const filePath = path.join(projectDir, relPath);
15054
- if (fs.existsSync(filePath)) {
15055
- let fileContent = fs.readFileSync(filePath, "utf-8");
15311
+ const filePath = path2.join(projectDir, relPath);
15312
+ if (fs2.existsSync(filePath)) {
15313
+ let fileContent = fs2.readFileSync(filePath, "utf-8");
15056
15314
  fileContent = fileContent.replaceAll(
15057
15315
  `AGENT:-${otherShortName}`,
15058
15316
  `AGENT:-${agentShortName}`
@@ -15061,17 +15319,17 @@ async function configureAgentCore(projectDir, variant) {
15061
15319
  `echo "${otherShortName}"`,
15062
15320
  `echo "${agentShortName}"`
15063
15321
  );
15064
- fs.writeFileSync(filePath, fileContent, "utf-8");
15322
+ fs2.writeFileSync(filePath, fileContent, "utf-8");
15065
15323
  }
15066
15324
  }
15067
- const resolveEnvPath = path.join(projectDir, "docker/resolve-env.py");
15068
- if (fs.existsSync(resolveEnvPath)) {
15069
- let resolveContent = fs.readFileSync(resolveEnvPath, "utf-8");
15325
+ const resolveEnvPath = path2.join(projectDir, "docker/resolve-env.py");
15326
+ if (fs2.existsSync(resolveEnvPath)) {
15327
+ let resolveContent = fs2.readFileSync(resolveEnvPath, "utf-8");
15070
15328
  resolveContent = resolveContent.replaceAll(
15071
15329
  `os.environ.get("AGENT", "${otherShortName}")`,
15072
15330
  `os.environ.get("AGENT", "${agentShortName}")`
15073
15331
  );
15074
- fs.writeFileSync(resolveEnvPath, resolveContent, "utf-8");
15332
+ fs2.writeFileSync(resolveEnvPath, resolveContent, "utf-8");
15075
15333
  }
15076
15334
  const frameworkLabel = isLanggraph ? "LangGraph" : "Strands";
15077
15335
  const stackSuffix = isLanggraph ? "lg" : "st";
@@ -15139,16 +15397,16 @@ cd infra-cdk && npx cdk@latest destroy --all --output ../cdk.out-${stackSuffix}
15139
15397
  - [AWS Bedrock AgentCore](https://aws.amazon.com/bedrock/agentcore/)
15140
15398
  - [AgentCore + CopilotKit Guide](https://docs.copilotkit.ai/agentcore/quickstart)
15141
15399
  `;
15142
- fs.writeFileSync(path.join(projectDir, "README.md"), readme, "utf-8");
15400
+ fs2.writeFileSync(path2.join(projectDir, "README.md"), readme, "utf-8");
15143
15401
  }
15144
15402
 
15145
15403
  // apps/cli/src/services/showcase-config.ts
15146
15404
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
15147
- import * as fs2 from "node:fs";
15148
- import * as path2 from "node:path";
15405
+ import * as fs3 from "node:fs";
15406
+ import * as path3 from "node:path";
15149
15407
  async function writeShowcaseConfig(projectDir, showcase) {
15150
- const configPath = path2.join(projectDir, "showcase.json");
15151
- fs2.writeFileSync(configPath, `${JSON.stringify({ showcase }, null, 2)}
15408
+ const configPath = path3.join(projectDir, "showcase.json");
15409
+ fs3.writeFileSync(configPath, `${JSON.stringify({ showcase }, null, 2)}
15152
15410
  `);
15153
15411
  }
15154
15412
 
@@ -15376,6 +15634,11 @@ var GOOGLE_ENV_KEY = {
15376
15634
  required: true,
15377
15635
  note: "Required by the ADK agents."
15378
15636
  };
15637
+ var A2A_GOOGLE_ENV_KEY = {
15638
+ key: "GOOGLE_API_KEY",
15639
+ required: true,
15640
+ note: "Required by the A2A agents. COPILOTKIT_AGENT_MODEL in .env chooses another provider."
15641
+ };
15379
15642
  function standardTemplate(framework, template, successEmoji) {
15380
15643
  const pythonUvTemplates = /* @__PURE__ */ new Set([
15381
15644
  "langgraph-py",
@@ -15499,7 +15762,7 @@ var FRAMEWORK_TEMPLATES = {
15499
15762
  postInstallCommands: [
15500
15763
  "python3 -m venv agents/.venv && agents/.venv/bin/pip install -r agents/requirements.txt"
15501
15764
  ],
15502
- environment: [OPENAI_ENV_KEY, GOOGLE_ENV_KEY]
15765
+ environment: [A2A_GOOGLE_ENV_KEY]
15503
15766
  },
15504
15767
  "microsoft-agent-framework-dotnet": {
15505
15768
  ...standardTemplate(
@@ -15595,15 +15858,15 @@ var FRAMEWORK_TEMPLATES = {
15595
15858
 
15596
15859
  // apps/cli/src/services/project-scaffold.ts
15597
15860
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
15598
- import * as fs4 from "node:fs";
15599
- import * as path4 from "node:path";
15861
+ import * as fs5 from "node:fs";
15862
+ import * as path5 from "node:path";
15600
15863
  import * as os from "node:os";
15601
15864
  import { execFileSync, spawn } from "node:child_process";
15602
15865
 
15603
15866
  // apps/cli/src/services/project-config.ts
15604
15867
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
15605
- import * as fs3 from "node:fs";
15606
- import * as path3 from "node:path";
15868
+ import * as fs4 from "node:fs";
15869
+ import * as path4 from "node:path";
15607
15870
 
15608
15871
  // apps/cli/src/services/repository-root.ts
15609
15872
  init_define_CLI_LOCAL_EVALUATION_SUPPORT();
@@ -15658,9 +15921,9 @@ var projectConfigSchema = external_exports.object({
15658
15921
  apiKeyDirectory: external_exports.string().trim().min(1).optional()
15659
15922
  }).strict();
15660
15923
  function canonicalizeDir(dir) {
15661
- const resolved = path3.resolve(dir);
15924
+ const resolved = path4.resolve(dir);
15662
15925
  try {
15663
- return fs3.realpathSync(resolved);
15926
+ return fs4.realpathSync(resolved);
15664
15927
  } catch {
15665
15928
  return resolved;
15666
15929
  }
@@ -15739,8 +16002,8 @@ function sharedFolderKind(dir, homeDir) {
15739
16002
  const system = new Set(
15740
16003
  [
15741
16004
  ...SYSTEM_FOLDERS,
15742
- path4.parse(dir).root,
15743
- path4.dirname(home),
16005
+ path5.parse(dir).root,
16006
+ path5.dirname(home),
15744
16007
  os.tmpdir(),
15745
16008
  process.env["SystemRoot"] ?? ""
15746
16009
  ].filter((folder) => folder !== "").map(canonicalizeDir)
@@ -15749,7 +16012,7 @@ function sharedFolderKind(dir, homeDir) {
15749
16012
  }
15750
16013
  function readEntries(dir) {
15751
16014
  try {
15752
- return fs4.readdirSync(dir, { withFileTypes: true });
16015
+ return fs5.readdirSync(dir, { withFileTypes: true });
15753
16016
  } catch {
15754
16017
  return [];
15755
16018
  }
@@ -15763,11 +16026,11 @@ function findProjectsBelow(dir) {
15763
16026
  function readEntriesUpTo(dir, limit) {
15764
16027
  if (limit === Number.POSITIVE_INFINITY) {
15765
16028
  return {
15766
- entries: fs4.readdirSync(dir, { withFileTypes: true }),
16029
+ entries: fs5.readdirSync(dir, { withFileTypes: true }),
15767
16030
  exhausted: false
15768
16031
  };
15769
16032
  }
15770
- const handle = fs4.opendirSync(dir);
16033
+ const handle = fs5.opendirSync(dir);
15771
16034
  const entries = [];
15772
16035
  try {
15773
16036
  for (let entry = handle.readSync(); entry !== null; entry = handle.readSync()) {
@@ -15803,8 +16066,8 @@ function walkProjectsBelow(dir, top, limits) {
15803
16066
  continue;
15804
16067
  if (entry.name.startsWith(".") || entry.name === "node_modules")
15805
16068
  continue;
15806
- const child = path4.join(relative, entry.name);
15807
- const childEntries = readChild(path4.join(dir, child));
16069
+ const child = path5.join(relative, entry.name);
16070
+ const childEntries = readChild(path5.join(dir, child));
15808
16071
  if (exhausted)
15809
16072
  return;
15810
16073
  const names = childEntries.map((e) => e.name);
@@ -15819,7 +16082,7 @@ function walkProjectsBelow(dir, top, limits) {
15819
16082
  return { found, exhausted };
15820
16083
  }
15821
16084
  function readProjectDirContents(projectDir, homeDir = os.homedir()) {
15822
- if (!fs4.existsSync(projectDir))
16085
+ if (!fs5.existsSync(projectDir))
15823
16086
  return { kind: "available" };
15824
16087
  const dir = canonicalizeDir(projectDir);
15825
16088
  const folder = sharedFolderKind(dir, homeDir);
@@ -15869,7 +16132,7 @@ async function scaffoldProject(options) {
15869
16132
  assertProjectDirAvailable(projectDir);
15870
16133
  const localTemplateDir = process.env["COPILOTKIT_TEMPLATE_DIR"];
15871
16134
  if (localTemplateDir !== void 0 && localTemplateDir !== "") {
15872
- if (!fs4.existsSync(localTemplateDir)) {
16135
+ if (!fs5.existsSync(localTemplateDir)) {
15873
16136
  throw tagError(
15874
16137
  new Error(
15875
16138
  `COPILOTKIT_TEMPLATE_DIR points at a path that does not exist: ${localTemplateDir}`
@@ -15878,7 +16141,7 @@ async function scaffoldProject(options) {
15878
16141
  );
15879
16142
  }
15880
16143
  try {
15881
- fs4.mkdirSync(projectDir, { recursive: true });
16144
+ fs5.mkdirSync(projectDir, { recursive: true });
15882
16145
  await copyDirectory(localTemplateDir, projectDir, true);
15883
16146
  } catch (cause) {
15884
16147
  throw wrapStepError(
@@ -15900,7 +16163,7 @@ async function scaffoldProject(options) {
15900
16163
  }
15901
16164
  function pathEntryExists(entryPath) {
15902
16165
  try {
15903
- fs4.lstatSync(entryPath);
16166
+ fs5.lstatSync(entryPath);
15904
16167
  return true;
15905
16168
  } catch (error48) {
15906
16169
  if (error48 instanceof Error && "code" in error48 && error48.code === "ENOENT") {
@@ -15911,7 +16174,7 @@ function pathEntryExists(entryPath) {
15911
16174
  }
15912
16175
  async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15913
16176
  const { owner, repo, revision, subdirectoryPath, mode } = source;
15914
- const tempDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "copilotkit-clone-"));
16177
+ const tempDir = fs5.mkdtempSync(path5.join(os.tmpdir(), "copilotkit-clone-"));
15915
16178
  const isWholeRepo = mode === "whole-repository";
15916
16179
  const destinationExisted = pathEntryExists(destinationPath);
15917
16180
  try {
@@ -15935,8 +16198,8 @@ async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15935
16198
  "sparse_config"
15936
16199
  );
15937
16200
  try {
15938
- fs4.writeFileSync(
15939
- path4.join(tempDir, ".git/info/sparse-checkout"),
16201
+ fs5.writeFileSync(
16202
+ path5.join(tempDir, ".git/info/sparse-checkout"),
15940
16203
  subdirectoryPath
15941
16204
  );
15942
16205
  } catch (cause) {
@@ -15959,8 +16222,8 @@ async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15959
16222
  TELEMETRY_ERROR_CODES.GIT_FAILED,
15960
16223
  "checkout"
15961
16224
  );
15962
- const sourcePath = isWholeRepo ? tempDir : path4.join(tempDir, subdirectoryPath);
15963
- if (!isWholeRepo && !fs4.existsSync(sourcePath)) {
16225
+ const sourcePath = isWholeRepo ? tempDir : path5.join(tempDir, subdirectoryPath);
16226
+ if (!isWholeRepo && !fs5.existsSync(sourcePath)) {
15964
16227
  throw annotateFailure(
15965
16228
  tagError(
15966
16229
  new Error(
@@ -15972,7 +16235,7 @@ async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15972
16235
  );
15973
16236
  }
15974
16237
  try {
15975
- fs4.mkdirSync(destinationPath, { recursive: true });
16238
+ fs5.mkdirSync(destinationPath, { recursive: true });
15976
16239
  await copyDirectory(sourcePath, destinationPath, isWholeRepo);
15977
16240
  } catch (cause) {
15978
16241
  throw wrapStepError(
@@ -15983,7 +16246,7 @@ async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15983
16246
  }
15984
16247
  } catch (cause) {
15985
16248
  if (!destinationExisted) {
15986
- fs4.rmSync(destinationPath, { recursive: true, force: true });
16249
+ fs5.rmSync(destinationPath, { recursive: true, force: true });
15987
16250
  }
15988
16251
  const error48 = cause instanceof Error ? cause : new Error("Starter template checkout failed");
15989
16252
  const code = error48.code;
@@ -15993,26 +16256,26 @@ async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15993
16256
  throw tagError(error48, TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED);
15994
16257
  } finally {
15995
16258
  try {
15996
- fs4.rmSync(tempDir, { recursive: true, force: true });
16259
+ fs5.rmSync(tempDir, { recursive: true, force: true });
15997
16260
  } catch {
15998
16261
  }
15999
16262
  }
16000
16263
  }
16001
16264
  async function copyDirectory(source, destination, excludeGit = false) {
16002
- if (!fs4.existsSync(destination)) {
16003
- fs4.mkdirSync(destination, { recursive: true });
16265
+ if (!fs5.existsSync(destination)) {
16266
+ fs5.mkdirSync(destination, { recursive: true });
16004
16267
  }
16005
- const entries = fs4.readdirSync(source, { withFileTypes: true });
16268
+ const entries = fs5.readdirSync(source, { withFileTypes: true });
16006
16269
  for (const entry of entries) {
16007
16270
  if (excludeGit && entry.name === ".git") {
16008
16271
  continue;
16009
16272
  }
16010
- const srcPath = path4.join(source, entry.name);
16011
- const destPath = path4.join(destination, entry.name);
16273
+ const srcPath = path5.join(source, entry.name);
16274
+ const destPath = path5.join(destination, entry.name);
16012
16275
  if (entry.isDirectory()) {
16013
16276
  await copyDirectory(srcPath, destPath, excludeGit);
16014
16277
  } else {
16015
- fs4.copyFileSync(srcPath, destPath);
16278
+ fs5.copyFileSync(srcPath, destPath);
16016
16279
  }
16017
16280
  }
16018
16281
  }
@@ -16146,10 +16409,10 @@ var StarterSmokeError = class extends Error {
16146
16409
  }
16147
16410
  };
16148
16411
  async function scaffoldStarterForSmoke(input, scaffold = scaffoldProject) {
16149
- const temporaryRoot = fs5.mkdtempSync(
16150
- path5.join(os2.tmpdir(), `copilotkit-smoke-${input.framework}-`)
16412
+ const temporaryRoot = fs6.mkdtempSync(
16413
+ path6.join(os2.tmpdir(), `copilotkit-smoke-${input.framework}-`)
16151
16414
  );
16152
- const projectDir = path5.join(temporaryRoot, "project");
16415
+ const projectDir = path6.join(temporaryRoot, "project");
16153
16416
  try {
16154
16417
  const definition = FRAMEWORK_TEMPLATES[input.framework];
16155
16418
  const configuredTemplate = definition.template;
@@ -16190,8 +16453,8 @@ async function scaffoldStarterForSmoke(input, scaffold = scaffoldProject) {
16190
16453
  const credential = command?.match(
16191
16454
  /dotnet user-secrets set ([A-Za-z0-9_]+)/
16192
16455
  )?.[1];
16193
- const programPath = path5.join(projectDir, "agent", "Program.cs");
16194
- const program = fs5.existsSync(programPath) ? fs5.readFileSync(programPath, "utf8") : "";
16456
+ const programPath = path6.join(projectDir, "agent", "Program.cs");
16457
+ const program = fs6.existsSync(programPath) ? fs6.readFileSync(programPath, "utf8") : "";
16195
16458
  if (!credential || !program.includes(credential)) {
16196
16459
  throw new StarterSmokeError(
16197
16460
  "STARTER_CREDENTIAL_MISMATCH",
@@ -16204,10 +16467,18 @@ async function scaffoldStarterForSmoke(input, scaffold = scaffoldProject) {
16204
16467
  );
16205
16468
  }
16206
16469
  }
16207
- const entries = fs5.readdirSync(projectDir);
16470
+ const problems = compareStarterModelFacts(input.framework, readStarterModelFacts(projectDir));
16471
+ if (problems.length > 0) {
16472
+ throw new StarterSmokeError(
16473
+ "STARTER_VENDOR_MISMATCH",
16474
+ `The vendor table in apps/cli/starter-model-vendors.cjs does not match the bound ${input.framework} starter: ${problems.join(" ")}`,
16475
+ { framework: input.framework, problems, revision: input.template.revision }
16476
+ );
16477
+ }
16478
+ const entries = fs6.readdirSync(projectDir);
16208
16479
  return entries.join("\n");
16209
16480
  } finally {
16210
- fs5.rmSync(temporaryRoot, { recursive: true, force: true });
16481
+ fs6.rmSync(temporaryRoot, { recursive: true, force: true });
16211
16482
  }
16212
16483
  }
16213
16484
  async function executeStarterSmokeChild(command) {
@@ -16242,7 +16513,7 @@ async function runStarterSmokeChild(input, execute = executeStarterSmokeChild, e
16242
16513
  return await execute({
16243
16514
  executable: process.execPath,
16244
16515
  args: [
16245
- path5.resolve(entrypoint),
16516
+ path6.resolve(entrypoint),
16246
16517
  "smoke-one",
16247
16518
  "--framework",
16248
16519
  input.framework,
@@ -16552,7 +16823,7 @@ function parseArguments(args) {
16552
16823
  return { command: releaseCommand, flags };
16553
16824
  }
16554
16825
  function readJsonObject(inputPath) {
16555
- const text = inputPath === "-" ? fs6.readFileSync(0, "utf8") : fs6.readFileSync(inputPath, "utf8");
16826
+ const text = inputPath === "-" ? fs7.readFileSync(0, "utf8") : fs7.readFileSync(inputPath, "utf8");
16556
16827
  const value = JSON.parse(text);
16557
16828
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
16558
16829
  throw new ReleaseCliInputError(`Expected a JSON object in ${inputPath}`);
@@ -16578,8 +16849,8 @@ function emitResult(result, scalarOutputs, flags, stdout) {
16578
16849
  `;
16579
16850
  const outputPath = flags.get("--output");
16580
16851
  if (outputPath !== void 0) {
16581
- fs6.mkdirSync(path6.dirname(path6.resolve(outputPath)), { recursive: true });
16582
- fs6.writeFileSync(outputPath, json2);
16852
+ fs7.mkdirSync(path7.dirname(path7.resolve(outputPath)), { recursive: true });
16853
+ fs7.writeFileSync(outputPath, json2);
16583
16854
  }
16584
16855
  const githubOutputPath = flags.get("--github-output");
16585
16856
  if (githubOutputPath !== void 0) {
@@ -16592,7 +16863,7 @@ function emitResult(result, scalarOutputs, flags, stdout) {
16592
16863
  }
16593
16864
  return `${name}=${serialized}`;
16594
16865
  });
16595
- fs6.appendFileSync(githubOutputPath, `${outputLines.join("\n")}
16866
+ fs7.appendFileSync(githubOutputPath, `${outputLines.join("\n")}
16596
16867
  `);
16597
16868
  }
16598
16869
  stdout(json2);
@@ -16628,7 +16899,7 @@ async function runReleaseCli(args, dependencies = {}) {
16628
16899
  }
16629
16900
  const validateStarterPaths = validateStarterPathsValue === "true";
16630
16901
  const pathsFile = optionalString(flags, "--paths-file");
16631
- const pathsDocument = pathsFile ? JSON.parse(fs6.readFileSync(pathsFile, "utf8")) : getFirstPartyStarterPaths();
16902
+ const pathsDocument = pathsFile ? JSON.parse(fs7.readFileSync(pathsFile, "utf8")) : getFirstPartyStarterPaths();
16632
16903
  const starterPaths = pathsDocument !== null && typeof pathsDocument === "object" && !Array.isArray(pathsDocument) && "starterPaths" in pathsDocument ? pathsDocument.starterPaths : pathsDocument ?? getFirstPartyStarterPaths();
16633
16904
  if (!Array.isArray(starterPaths) || starterPaths.length === 0 || starterPaths.length > 100 || !starterPaths.every(
16634
16905
  (value) => typeof value === "string" && /^[A-Za-z0-9._/-]+$/.test(value) && !value.startsWith("/") && !value.split("/").includes("..")
@@ -16741,7 +17012,7 @@ async function runReleaseCli(args, dependencies = {}) {
16741
17012
  const buildInfoPath = requiredString(flags, "--build-info");
16742
17013
  let result2;
16743
17014
  try {
16744
- result2 = parseBuildInfo(fs6.readFileSync(buildInfoPath, "utf8"));
17015
+ result2 = parseBuildInfo(fs7.readFileSync(buildInfoPath, "utf8"));
16745
17016
  } catch (error48) {
16746
17017
  throw new ReleaseCliInputError(
16747
17018
  `Invalid CLI build information: ${error48 instanceof Error ? error48.message : String(error48)}`
@@ -16783,7 +17054,7 @@ async function runReleaseCli(args, dependencies = {}) {
16783
17054
  }
16784
17055
  if (command === "verify-published") {
16785
17056
  const archivePath = requiredString(flags, "--archive");
16786
- const archive = fs6.readFileSync(archivePath);
17057
+ const archive = fs7.readFileSync(archivePath);
16787
17058
  const result2 = await verifyPublishedPackage({
16788
17059
  archive,
16789
17060
  registryIntegrity: requiredString(flags, "--registry-integrity"),
@@ -16825,8 +17096,8 @@ async function runReleaseCli(args, dependencies = {}) {
16825
17096
  const buildInfoPath = requiredString(flags, "--build-info");
16826
17097
  const archivePath = requiredString(flags, "--archive");
16827
17098
  const result2 = createValidationManifest({
16828
- buildInfo: parseBuildInfo(fs6.readFileSync(buildInfoPath, "utf8")),
16829
- archiveIntegrity: calculatePackageIntegrity(fs6.readFileSync(archivePath))
17099
+ buildInfo: parseBuildInfo(fs7.readFileSync(buildInfoPath, "utf8")),
17100
+ archiveIntegrity: calculatePackageIntegrity(fs7.readFileSync(archivePath))
16830
17101
  });
16831
17102
  emitResult(
16832
17103
  result2,
@@ -16845,7 +17116,7 @@ async function runReleaseCli(args, dependencies = {}) {
16845
17116
  }
16846
17117
  if (command === "manifest") {
16847
17118
  const buildInfoPath = requiredString(flags, "--build-info");
16848
- const buildInfo = parseBuildInfo(fs6.readFileSync(buildInfoPath, "utf8"));
17119
+ const buildInfo = parseBuildInfo(fs7.readFileSync(buildInfoPath, "utf8"));
16849
17120
  const completionRunId = optionalString(flags, "--completion-run-id");
16850
17121
  const completion = completionRunId !== void 0 ? {
16851
17122
  workflowRunId: completionRunId,
@@ -16883,7 +17154,7 @@ async function runReleaseCli(args, dependencies = {}) {
16883
17154
  if (command === "reconcile") {
16884
17155
  const expectedManifestPath = requiredString(flags, "--expected-manifest");
16885
17156
  const expectedManifest = parseReleaseManifest(
16886
- fs6.readFileSync(expectedManifestPath, "utf8")
17157
+ fs7.readFileSync(expectedManifestPath, "utf8")
16887
17158
  );
16888
17159
  const tagTarget = optionalString(flags, "--tag-target");
16889
17160
  const releaseTag = optionalString(flags, "--release-tag");