@standardagents/builder 0.36.3 → 0.37.1

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 (40) hide show
  1. package/dist/built-in-routes.js +1333 -1034
  2. package/dist/built-in-routes.js.map +1 -1
  3. package/dist/client/{ApiKeysView-CxelZw61.js → ApiKeysView-BhuT3pIF.js} +1 -1
  4. package/dist/client/{CenteredContentView-CeQNRQH8.js → CenteredContentView-CfgX3Ao3.js} +1 -1
  5. package/dist/client/{CompositionView-YO0nHsYV.js → CompositionView-B9FfWMHd.js} +1 -1
  6. package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-_Y_F2vcO.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-BqwwsXWJ.js} +1 -1
  7. package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-CtC06f6H.js → CopyButton.vue_vue_type_script_setup_true_lang-Cqm3Vt3E.js} +1 -1
  8. package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-CqaWkS63.js → DataTable.vue_vue_type_script_setup_true_lang-CA5qgsty.js} +1 -1
  9. package/dist/client/{JsonViewer-71rdOpyq.js → JsonViewer-ByQKCShF.js} +1 -1
  10. package/dist/client/{LoginView-CkDpPh8U.js → LoginView-J4qtHbQK.js} +1 -1
  11. package/dist/client/{MarketplaceView-UYrMBLon.js → MarketplaceView-CshdWDqp.js} +1 -1
  12. package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-B1HPGo8o.js → Modal.vue_vue_type_script_setup_true_lang-DKdB9A8Z.js} +1 -1
  13. package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-DejoTM9W.js → ModelModal.vue_vue_type_script_setup_true_lang-BAxaBZsx.js} +1 -1
  14. package/dist/client/{ModelsView-DKYzp2fJ.js → ModelsView-B_n306yk.js} +1 -1
  15. package/dist/client/{PromptEditView-BlYHZ0ao.js → PromptEditView-C85qRgsE.js} +1 -1
  16. package/dist/client/{PromptModal-B1neRzSc.js → PromptModal-PNpoJfqD.js} +1 -1
  17. package/dist/client/{PromptsView-C0Ez74j0.js → PromptsView-BKnfThIF.js} +1 -1
  18. package/dist/client/{ProvidersView-CFc4K0IC.js → ProvidersView-Df41VhHD.js} +1 -1
  19. package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CtIBWHUR.js +22 -0
  20. package/dist/client/{ThreadsView-B1hFXL-4.js → ThreadsView-sjo5Rrcm.js} +1 -1
  21. package/dist/client/{ToolsView-B3KqeOZD.js → ToolsView-C0MH9x3N.js} +1 -1
  22. package/dist/client/{UsersView-CF1tomjI.js → UsersView--TQiJYP7.js} +1 -1
  23. package/dist/client/{VariablesView-CP0TDspK.js → VariablesView-BO3UljZu.js} +1 -1
  24. package/dist/client/assets/{ThreadInspectorPane-2QOWOtet.css → ThreadInspectorPane-D9ZMzSTn.css} +1 -1
  25. package/dist/client/{index-BTs3PMFs.js → index-BgZnQr8X.js} +2 -2
  26. package/dist/client/index.html +1 -1
  27. package/dist/{index-DUIfQjBW.d.ts → index-DceFbLG9.d.ts} +62 -2
  28. package/dist/index.d.ts +61 -3
  29. package/dist/index.js +10804 -10203
  30. package/dist/index.js.map +1 -1
  31. package/dist/packing.js +213 -161
  32. package/dist/packing.js.map +1 -1
  33. package/dist/plugin.js +537 -504
  34. package/dist/plugin.js.map +1 -1
  35. package/dist/runtime.d.ts +176 -39
  36. package/dist/runtime.js +10280 -9672
  37. package/dist/runtime.js.map +1 -1
  38. package/dist/test.d.ts +1 -1
  39. package/package.json +5 -5
  40. package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CXbSQo2-.js +0 -23
package/dist/plugin.js CHANGED
@@ -1,7 +1,7 @@
1
- import * as fs8 from 'fs';
2
- import fs8__default from 'fs';
3
- import * as path8 from 'path';
4
- import path8__default from 'path';
1
+ import * as fs9 from 'fs';
2
+ import fs9__default from 'fs';
3
+ import * as path9 from 'path';
4
+ import path9__default from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import MagicString from 'magic-string';
7
7
  import { exec } from 'child_process';
@@ -41,15 +41,15 @@ function extractSchemaFields(content) {
41
41
  }
42
42
  function scanPromptsWithSchemas(dir) {
43
43
  const results = [];
44
- if (!fs8__default.existsSync(dir)) {
44
+ if (!fs9__default.existsSync(dir)) {
45
45
  return results;
46
46
  }
47
47
  try {
48
- const entries = fs8__default.readdirSync(dir, { withFileTypes: true });
48
+ const entries = fs9__default.readdirSync(dir, { withFileTypes: true });
49
49
  for (const entry of entries) {
50
50
  if (entry.isFile() && entry.name.endsWith(".ts")) {
51
- const filePath = path8__default.join(dir, entry.name);
52
- const content = fs8__default.readFileSync(filePath, "utf-8");
51
+ const filePath = path9__default.join(dir, entry.name);
52
+ const content = fs9__default.readFileSync(filePath, "utf-8");
53
53
  const nameMatch = content.match(/name:\s*['"]([^'"]+)['"]/);
54
54
  if (nameMatch) {
55
55
  const name = nameMatch[1];
@@ -65,15 +65,15 @@ function scanPromptsWithSchemas(dir) {
65
65
  }
66
66
  function scanAgentsWithSideA(dir) {
67
67
  const results = [];
68
- if (!fs8__default.existsSync(dir)) {
68
+ if (!fs9__default.existsSync(dir)) {
69
69
  return results;
70
70
  }
71
71
  try {
72
- const entries = fs8__default.readdirSync(dir, { withFileTypes: true });
72
+ const entries = fs9__default.readdirSync(dir, { withFileTypes: true });
73
73
  for (const entry of entries) {
74
74
  if (entry.isFile() && entry.name.endsWith(".ts")) {
75
- const filePath = path8__default.join(dir, entry.name);
76
- const content = fs8__default.readFileSync(filePath, "utf-8");
75
+ const filePath = path9__default.join(dir, entry.name);
76
+ const content = fs9__default.readFileSync(filePath, "utf-8");
77
77
  const nameMatch = content.match(/name:\s*['"]([^'"]+)['"]/);
78
78
  if (nameMatch) {
79
79
  const name = nameMatch[1];
@@ -93,15 +93,15 @@ function scanAgentsWithSideA(dir) {
93
93
  }
94
94
  function scanForNames(dir, useFilename = false) {
95
95
  const names = [];
96
- if (!fs8__default.existsSync(dir)) {
96
+ if (!fs9__default.existsSync(dir)) {
97
97
  return names;
98
98
  }
99
99
  try {
100
- const entries = fs8__default.readdirSync(dir, { withFileTypes: true });
100
+ const entries = fs9__default.readdirSync(dir, { withFileTypes: true });
101
101
  for (const entry of entries) {
102
102
  if (entry.isFile() && entry.name.endsWith(".ts")) {
103
- const filePath = path8__default.join(dir, entry.name);
104
- const content = fs8__default.readFileSync(filePath, "utf-8");
103
+ const filePath = path9__default.join(dir, entry.name);
104
+ const content = fs9__default.readFileSync(filePath, "utf-8");
105
105
  if (useFilename) {
106
106
  const toolName = entry.name.replace(/\.ts$/, "");
107
107
  if (content.includes("defineTool")) {
@@ -122,18 +122,18 @@ function scanForNames(dir, useFilename = false) {
122
122
  }
123
123
  function scanHooksForIds(dir) {
124
124
  const hookIds = [];
125
- if (!fs8__default.existsSync(dir)) {
125
+ if (!fs9__default.existsSync(dir)) {
126
126
  return hookIds;
127
127
  }
128
128
  try {
129
- const entries = fs8__default.readdirSync(dir, { withFileTypes: true });
129
+ const entries = fs9__default.readdirSync(dir, { withFileTypes: true });
130
130
  for (const entry of entries) {
131
131
  if (entry.isFile() && entry.name.endsWith(".ts")) {
132
132
  if (entry.name === "index.ts") {
133
133
  continue;
134
134
  }
135
- const filePath = path8__default.join(dir, entry.name);
136
- const content = fs8__default.readFileSync(filePath, "utf-8");
135
+ const filePath = path9__default.join(dir, entry.name);
136
+ const content = fs9__default.readFileSync(filePath, "utf-8");
137
137
  const idMatch = content.match(/defineHook\s*\(\s*\{[^}]*id:\s*['"]([^'"]+)['"]/s);
138
138
  if (idMatch) {
139
139
  hookIds.push(idMatch[1]);
@@ -523,6 +523,8 @@ declare module 'virtual:@standardagents/builder' {
523
523
  executing?: boolean;
524
524
  /** Short excerpt of the most recent user message, for thread-list rows. */
525
525
  last_message_preview?: string | null;
526
+ /** Unix seconds of the newest message on this thread (never bumped by background activity). */
527
+ last_message_at?: number | null;
526
528
  }
527
529
 
528
530
  export interface UpdateThreadParams {
@@ -799,44 +801,44 @@ declare module 'virtual:@standardagents/router' {
799
801
  `;
800
802
  }
801
803
  function ensureDir(dir) {
802
- if (!fs8__default.existsSync(dir)) {
803
- fs8__default.mkdirSync(dir, { recursive: true });
804
+ if (!fs9__default.existsSync(dir)) {
805
+ fs9__default.mkdirSync(dir, { recursive: true });
804
806
  }
805
807
  }
806
808
  function writeFileIfChanged(filePath, content) {
807
- if (fs8__default.existsSync(filePath)) {
808
- const existing = fs8__default.readFileSync(filePath, "utf-8");
809
+ if (fs9__default.existsSync(filePath)) {
810
+ const existing = fs9__default.readFileSync(filePath, "utf-8");
809
811
  if (existing === content) {
810
812
  return;
811
813
  }
812
814
  }
813
- fs8__default.writeFileSync(filePath, content);
815
+ fs9__default.writeFileSync(filePath, content);
814
816
  }
815
817
  function generateTypes(config) {
816
818
  ensureDir(config.outputDir);
817
819
  const typesContent = generateTypesContent(config);
818
- writeFileIfChanged(path8__default.join(config.outputDir, "types.d.ts"), typesContent);
820
+ writeFileIfChanged(path9__default.join(config.outputDir, "types.d.ts"), typesContent);
819
821
  const virtualModuleContent = generateVirtualModuleContent();
820
- writeFileIfChanged(path8__default.join(config.outputDir, "virtual-module.d.ts"), virtualModuleContent);
821
- writeFileIfChanged(path8__default.join(config.outputDir, "tsconfig.json"), TSCONFIG_CONTENT);
822
- writeFileIfChanged(path8__default.join(config.outputDir, ".gitignore"), "*\n");
822
+ writeFileIfChanged(path9__default.join(config.outputDir, "virtual-module.d.ts"), virtualModuleContent);
823
+ writeFileIfChanged(path9__default.join(config.outputDir, "tsconfig.json"), TSCONFIG_CONTENT);
824
+ writeFileIfChanged(path9__default.join(config.outputDir, ".gitignore"), "*\n");
823
825
  }
824
826
  function needsRegeneration(config) {
825
- const typesPath = path8__default.join(config.outputDir, "types.d.ts");
826
- if (!fs8__default.existsSync(typesPath)) {
827
+ const typesPath = path9__default.join(config.outputDir, "types.d.ts");
828
+ if (!fs9__default.existsSync(typesPath)) {
827
829
  return true;
828
830
  }
829
- const typesMtime = fs8__default.statSync(typesPath).mtime;
831
+ const typesMtime = fs9__default.statSync(typesPath).mtime;
830
832
  const dirs = [config.modelsDir, config.promptsDir, config.agentsDir, config.toolsDir, config.hooksDir];
831
833
  for (const dir of dirs) {
832
- if (!fs8__default.existsSync(dir)) {
834
+ if (!fs9__default.existsSync(dir)) {
833
835
  continue;
834
836
  }
835
- const entries = fs8__default.readdirSync(dir, { withFileTypes: true });
837
+ const entries = fs9__default.readdirSync(dir, { withFileTypes: true });
836
838
  for (const entry of entries) {
837
839
  if (entry.isFile() && entry.name.endsWith(".ts")) {
838
- const filePath = path8__default.join(dir, entry.name);
839
- const fileMtime = fs8__default.statSync(filePath).mtime;
840
+ const filePath = path9__default.join(dir, entry.name);
841
+ const fileMtime = fs9__default.statSync(filePath).mtime;
840
842
  if (fileMtime > typesMtime) {
841
843
  return true;
842
844
  }
@@ -1042,7 +1044,7 @@ function createHmrReloader() {
1042
1044
  versions,
1043
1045
  invalidateSourceFileModule(server, filePath) {
1044
1046
  if (!filePath) return;
1045
- const absolutePath = path8__default.resolve(filePath);
1047
+ const absolutePath = path9__default.resolve(filePath);
1046
1048
  for (const [envName, env] of Object.entries(server.environments)) {
1047
1049
  const modules = env.moduleGraph.getModulesByFile(absolutePath);
1048
1050
  if (!modules) continue;
@@ -1053,10 +1055,10 @@ function createHmrReloader() {
1053
1055
  }
1054
1056
  },
1055
1057
  invalidateSourceDirectoryModules(server, dirPath) {
1056
- if (!fs8__default.existsSync(dirPath)) return;
1058
+ if (!fs9__default.existsSync(dirPath)) return;
1057
1059
  const scan = (currentDir) => {
1058
- for (const entry of fs8__default.readdirSync(currentDir, { withFileTypes: true })) {
1059
- const nextPath = path8__default.join(currentDir, entry.name);
1060
+ for (const entry of fs9__default.readdirSync(currentDir, { withFileTypes: true })) {
1061
+ const nextPath = path9__default.join(currentDir, entry.name);
1060
1062
  if (entry.isDirectory()) {
1061
1063
  scan(nextPath);
1062
1064
  } else if (entry.isFile() && entry.name.endsWith(".ts")) {
@@ -1220,12 +1222,12 @@ function createHmrReloader() {
1220
1222
  };
1221
1223
  return reloader;
1222
1224
  }
1223
- var STATE_RELATIVE_PATH = path8__default.join(".agents", "bootstrap-session.json");
1225
+ var STATE_RELATIVE_PATH = path9__default.join(".agents", "bootstrap-session.json");
1224
1226
  var PROJECT_ROOT_ENV_KEYS = ["INIT_CWD", "PWD", "npm_config_local_prefix"];
1225
1227
  function uniquePaths(paths) {
1226
1228
  return Array.from(
1227
1229
  new Set(
1228
- paths.filter((value) => !!value?.trim()).map((value) => path8__default.resolve(value))
1230
+ paths.filter((value) => !!value?.trim()).map((value) => path9__default.resolve(value))
1229
1231
  )
1230
1232
  );
1231
1233
  }
@@ -1241,11 +1243,11 @@ function mergeCookieHeader(cookieHeader, injectedCookie) {
1241
1243
  return raw ? `${raw}; ${injectedCookie}` : injectedCookie;
1242
1244
  }
1243
1245
  function loadLocalBootstrapSession(projectRoot) {
1244
- const statePath = path8__default.join(projectRoot, STATE_RELATIVE_PATH);
1245
- if (!fs8__default.existsSync(statePath)) return null;
1246
+ const statePath = path9__default.join(projectRoot, STATE_RELATIVE_PATH);
1247
+ if (!fs9__default.existsSync(statePath)) return null;
1246
1248
  try {
1247
1249
  const parsed = JSON.parse(
1248
- fs8__default.readFileSync(statePath, "utf-8")
1250
+ fs9__default.readFileSync(statePath, "utf-8")
1249
1251
  );
1250
1252
  if (parsed.version !== 1) return null;
1251
1253
  if (!parsed.endpoint || !parsed.user?.id || !parsed.account?.id) return null;
@@ -1262,7 +1264,7 @@ function findLocalBootstrapSession(projectRoot, env) {
1262
1264
  const envSession = loadLocalBootstrapSessionFromEnv();
1263
1265
  if (envSession) {
1264
1266
  return {
1265
- projectRoot: projectRoot ? path8__default.resolve(projectRoot) : process.cwd(),
1267
+ projectRoot: projectRoot ? path9__default.resolve(projectRoot) : process.cwd(),
1266
1268
  session: envSession
1267
1269
  };
1268
1270
  }
@@ -1907,23 +1909,23 @@ function nameToFilename(name) {
1907
1909
  }
1908
1910
  function getModelFilePath(modelsDir, name) {
1909
1911
  const filename = nameToFilename(name);
1910
- return path8__default.join(modelsDir, `${filename}.ts`);
1912
+ return path9__default.join(modelsDir, `${filename}.ts`);
1911
1913
  }
1912
1914
  function getProviderFilePath(providersDir, name) {
1913
1915
  const filename = nameToFilename(name);
1914
- return path8__default.join(providersDir, `${filename}.ts`);
1916
+ return path9__default.join(providersDir, `${filename}.ts`);
1915
1917
  }
1916
1918
  function extensionlessImportPath(fromDir, toFile) {
1917
- let relative2 = path8__default.relative(fromDir, toFile).replace(/\\/g, "/").replace(/\.ts$/, "");
1918
- if (!relative2.startsWith(".")) {
1919
- relative2 = `./${relative2}`;
1919
+ let relative4 = path9__default.relative(fromDir, toFile).replace(/\\/g, "/").replace(/\.ts$/, "");
1920
+ if (!relative4.startsWith(".")) {
1921
+ relative4 = `./${relative4}`;
1920
1922
  }
1921
- return relative2;
1923
+ return relative4;
1922
1924
  }
1923
1925
  function getLocalProviderInfo(modelsDir, providersDir, providerName) {
1924
1926
  if (!providersDir) return null;
1925
1927
  const providerPath = getProviderFilePath(providersDir, providerName);
1926
- if (!fs8__default.existsSync(providerPath)) return null;
1928
+ if (!fs9__default.existsSync(providerPath)) return null;
1927
1929
  return {
1928
1930
  name: nameToFilename(providerName),
1929
1931
  package: extensionlessImportPath(modelsDir, providerPath),
@@ -1932,15 +1934,15 @@ function getLocalProviderInfo(modelsDir, providersDir, providerName) {
1932
1934
  }
1933
1935
  function modelExists(modelsDir, name) {
1934
1936
  const filePath = getModelFilePath(modelsDir, name);
1935
- return fs8__default.existsSync(filePath);
1937
+ return fs9__default.existsSync(filePath);
1936
1938
  }
1937
1939
  async function saveModel(modelsDir, data, overwrite = false, providerPackageMap = defaultProviderPackageMap, providersDir) {
1938
1940
  try {
1939
- if (!fs8__default.existsSync(modelsDir)) {
1940
- fs8__default.mkdirSync(modelsDir, { recursive: true });
1941
+ if (!fs9__default.existsSync(modelsDir)) {
1942
+ fs9__default.mkdirSync(modelsDir, { recursive: true });
1941
1943
  }
1942
1944
  const filePath = getModelFilePath(modelsDir, data.name);
1943
- if (!overwrite && fs8__default.existsSync(filePath)) {
1945
+ if (!overwrite && fs9__default.existsSync(filePath)) {
1944
1946
  return {
1945
1947
  success: false,
1946
1948
  error: `Model file already exists: ${filePath}. Use update to modify existing models.`
@@ -1948,7 +1950,7 @@ async function saveModel(modelsDir, data, overwrite = false, providerPackageMap
1948
1950
  }
1949
1951
  const providerInfo = providerPackageMap[data.provider] ?? getLocalProviderInfo(modelsDir, providersDir, data.provider);
1950
1952
  if (!providerInfo) {
1951
- const localProviderNames = providersDir && fs8__default.existsSync(providersDir) ? fs8__default.readdirSync(providersDir).filter((fileName) => fileName.endsWith(".ts")).map((fileName) => fileName.replace(/\.ts$/, "")) : [];
1953
+ const localProviderNames = providersDir && fs9__default.existsSync(providersDir) ? fs9__default.readdirSync(providersDir).filter((fileName) => fileName.endsWith(".ts")).map((fileName) => fileName.replace(/\.ts$/, "")) : [];
1952
1954
  const validProviders = [...Object.keys(providerPackageMap), ...localProviderNames];
1953
1955
  return {
1954
1956
  success: false,
@@ -1960,7 +1962,7 @@ async function saveModel(modelsDir, data, overwrite = false, providerPackageMap
1960
1962
  providerPackage: providerInfo.package,
1961
1963
  defaultImport: providerInfo.defaultImport
1962
1964
  });
1963
- await fs8__default.promises.writeFile(filePath, content, "utf-8");
1965
+ await fs9__default.promises.writeFile(filePath, content, "utf-8");
1964
1966
  return {
1965
1967
  success: true,
1966
1968
  filePath
@@ -1975,13 +1977,13 @@ async function saveModel(modelsDir, data, overwrite = false, providerPackageMap
1975
1977
  async function deleteModel(modelsDir, name) {
1976
1978
  try {
1977
1979
  const filePath = getModelFilePath(modelsDir, name);
1978
- if (!fs8__default.existsSync(filePath)) {
1980
+ if (!fs9__default.existsSync(filePath)) {
1979
1981
  return {
1980
1982
  success: false,
1981
1983
  error: `Model file not found: ${filePath}`
1982
1984
  };
1983
1985
  }
1984
- await fs8__default.promises.unlink(filePath);
1986
+ await fs9__default.promises.unlink(filePath);
1985
1987
  return {
1986
1988
  success: true,
1987
1989
  filePath
@@ -2027,7 +2029,7 @@ function validateModelDataWithProviders(data, providerPackageMap, providersDir)
2027
2029
  const validProviders = Object.keys(providerPackageMap);
2028
2030
  const hasLocalProvider = Boolean(getLocalProviderInfo(process.cwd(), providersDir, data.provider));
2029
2031
  if (!validProviders.includes(data.provider) && !hasLocalProvider) {
2030
- const localProviderNames = providersDir && fs8__default.existsSync(providersDir) ? fs8__default.readdirSync(providersDir).filter((fileName) => fileName.endsWith(".ts")).map((fileName) => fileName.replace(/\.ts$/, "")) : [];
2032
+ const localProviderNames = providersDir && fs9__default.existsSync(providersDir) ? fs9__default.readdirSync(providersDir).filter((fileName) => fileName.endsWith(".ts")).map((fileName) => fileName.replace(/\.ts$/, "")) : [];
2031
2033
  errors["provider"] = `Invalid provider '${data.provider}'. Must be one of: ${[...validProviders, ...localProviderNames].join(", ")}`;
2032
2034
  }
2033
2035
  }
@@ -2244,26 +2246,26 @@ function transformPromptData(data) {
2244
2246
  }
2245
2247
  function getPromptFilePath(promptsDir, name) {
2246
2248
  const filename = nameToFilename(name);
2247
- return path8__default.join(promptsDir, `${filename}.ts`);
2249
+ return path9__default.join(promptsDir, `${filename}.ts`);
2248
2250
  }
2249
2251
  function promptExists(promptsDir, name) {
2250
2252
  const filePath = getPromptFilePath(promptsDir, name);
2251
- return fs8__default.existsSync(filePath);
2253
+ return fs9__default.existsSync(filePath);
2252
2254
  }
2253
2255
  async function savePrompt(promptsDir, data, overwrite = false) {
2254
2256
  try {
2255
- if (!fs8__default.existsSync(promptsDir)) {
2256
- fs8__default.mkdirSync(promptsDir, { recursive: true });
2257
+ if (!fs9__default.existsSync(promptsDir)) {
2258
+ fs9__default.mkdirSync(promptsDir, { recursive: true });
2257
2259
  }
2258
2260
  const filePath = getPromptFilePath(promptsDir, data.name);
2259
- if (!overwrite && fs8__default.existsSync(filePath)) {
2261
+ if (!overwrite && fs9__default.existsSync(filePath)) {
2260
2262
  return {
2261
2263
  success: false,
2262
2264
  error: `Prompt file already exists: ${filePath}. Use update to modify existing prompts.`
2263
2265
  };
2264
2266
  }
2265
2267
  const content = generatePromptFile(data);
2266
- await fs8__default.promises.writeFile(filePath, content, "utf-8");
2268
+ await fs9__default.promises.writeFile(filePath, content, "utf-8");
2267
2269
  return {
2268
2270
  success: true,
2269
2271
  filePath
@@ -2278,13 +2280,13 @@ async function savePrompt(promptsDir, data, overwrite = false) {
2278
2280
  async function deletePrompt(promptsDir, name) {
2279
2281
  try {
2280
2282
  const filePath = getPromptFilePath(promptsDir, name);
2281
- if (!fs8__default.existsSync(filePath)) {
2283
+ if (!fs9__default.existsSync(filePath)) {
2282
2284
  return {
2283
2285
  success: false,
2284
2286
  error: `Prompt file not found: ${filePath}`
2285
2287
  };
2286
2288
  }
2287
- await fs8__default.promises.unlink(filePath);
2289
+ await fs9__default.promises.unlink(filePath);
2288
2290
  return {
2289
2291
  success: true,
2290
2292
  filePath
@@ -2300,25 +2302,25 @@ async function renamePrompt(promptsDir, oldName, newName) {
2300
2302
  try {
2301
2303
  const oldFilePath = getPromptFilePath(promptsDir, oldName);
2302
2304
  const newFilePath = getPromptFilePath(promptsDir, newName);
2303
- if (!fs8__default.existsSync(oldFilePath)) {
2305
+ if (!fs9__default.existsSync(oldFilePath)) {
2304
2306
  return {
2305
2307
  success: false,
2306
2308
  error: `Prompt file not found: ${oldFilePath}`
2307
2309
  };
2308
2310
  }
2309
- if (fs8__default.existsSync(newFilePath)) {
2311
+ if (fs9__default.existsSync(newFilePath)) {
2310
2312
  return {
2311
2313
  success: false,
2312
2314
  error: `Prompt file already exists: ${newFilePath}`
2313
2315
  };
2314
2316
  }
2315
- const content = await fs8__default.promises.readFile(oldFilePath, "utf-8");
2317
+ const content = await fs9__default.promises.readFile(oldFilePath, "utf-8");
2316
2318
  const updatedContent = content.replace(
2317
2319
  /name:\s*['"]([^'"]+)['"]/,
2318
2320
  `name: '${newName}'`
2319
2321
  );
2320
- await fs8__default.promises.writeFile(newFilePath, updatedContent, "utf-8");
2321
- await fs8__default.promises.unlink(oldFilePath);
2322
+ await fs9__default.promises.writeFile(newFilePath, updatedContent, "utf-8");
2323
+ await fs9__default.promises.unlink(oldFilePath);
2322
2324
  return {
2323
2325
  success: true,
2324
2326
  filePath: newFilePath
@@ -2618,15 +2620,15 @@ function transformAgentData(data) {
2618
2620
  }
2619
2621
  function getAgentFilePath(agentsDir, name) {
2620
2622
  const filename = nameToFilename(name);
2621
- return path8__default.join(agentsDir, `${filename}.ts`);
2623
+ return path9__default.join(agentsDir, `${filename}.ts`);
2622
2624
  }
2623
2625
  function agentExists(agentsDir, name) {
2624
2626
  const filePath = getAgentFilePath(agentsDir, name);
2625
- return fs8__default.existsSync(filePath);
2627
+ return fs9__default.existsSync(filePath);
2626
2628
  }
2627
2629
  function extractAgentMetadata(filePath) {
2628
2630
  try {
2629
- const content = fs8__default.readFileSync(filePath, "utf-8");
2631
+ const content = fs9__default.readFileSync(filePath, "utf-8");
2630
2632
  const metadata = {};
2631
2633
  const packageNameMatch = content.match(/packageName:\s*['"]([^'"]+)['"]/);
2632
2634
  if (packageNameMatch) metadata.packageName = packageNameMatch[1];
@@ -2643,17 +2645,17 @@ function extractAgentMetadata(filePath) {
2643
2645
  }
2644
2646
  async function saveAgent(agentsDir, data, overwrite = false) {
2645
2647
  try {
2646
- if (!fs8__default.existsSync(agentsDir)) {
2647
- fs8__default.mkdirSync(agentsDir, { recursive: true });
2648
+ if (!fs9__default.existsSync(agentsDir)) {
2649
+ fs9__default.mkdirSync(agentsDir, { recursive: true });
2648
2650
  }
2649
2651
  const filePath = getAgentFilePath(agentsDir, data.name);
2650
- if (!overwrite && fs8__default.existsSync(filePath)) {
2652
+ if (!overwrite && fs9__default.existsSync(filePath)) {
2651
2653
  return {
2652
2654
  success: false,
2653
2655
  error: `Agent file already exists: ${filePath}. Use update to modify existing agents.`
2654
2656
  };
2655
2657
  }
2656
- if (overwrite && fs8__default.existsSync(filePath)) {
2658
+ if (overwrite && fs9__default.existsSync(filePath)) {
2657
2659
  const existingMetadata = extractAgentMetadata(filePath);
2658
2660
  if (existingMetadata.packageName && !data.packageName) {
2659
2661
  data.packageName = existingMetadata.packageName;
@@ -2669,7 +2671,7 @@ async function saveAgent(agentsDir, data, overwrite = false) {
2669
2671
  }
2670
2672
  }
2671
2673
  const content = generateAgentFile(data);
2672
- await fs8__default.promises.writeFile(filePath, content, "utf-8");
2674
+ await fs9__default.promises.writeFile(filePath, content, "utf-8");
2673
2675
  return {
2674
2676
  success: true,
2675
2677
  filePath
@@ -2684,13 +2686,13 @@ async function saveAgent(agentsDir, data, overwrite = false) {
2684
2686
  async function deleteAgent(agentsDir, name) {
2685
2687
  try {
2686
2688
  const filePath = getAgentFilePath(agentsDir, name);
2687
- if (!fs8__default.existsSync(filePath)) {
2689
+ if (!fs9__default.existsSync(filePath)) {
2688
2690
  return {
2689
2691
  success: false,
2690
2692
  error: `Agent file not found: ${filePath}`
2691
2693
  };
2692
2694
  }
2693
- await fs8__default.promises.unlink(filePath);
2695
+ await fs9__default.promises.unlink(filePath);
2694
2696
  return {
2695
2697
  success: true,
2696
2698
  filePath
@@ -2706,25 +2708,25 @@ async function renameModel(modelsDir, oldName, newName) {
2706
2708
  try {
2707
2709
  const oldFilePath = getModelFilePath(modelsDir, oldName);
2708
2710
  const newFilePath = getModelFilePath(modelsDir, newName);
2709
- if (!fs8__default.existsSync(oldFilePath)) {
2711
+ if (!fs9__default.existsSync(oldFilePath)) {
2710
2712
  return {
2711
2713
  success: false,
2712
2714
  error: `Model file not found: ${oldFilePath}`
2713
2715
  };
2714
2716
  }
2715
- if (fs8__default.existsSync(newFilePath)) {
2717
+ if (fs9__default.existsSync(newFilePath)) {
2716
2718
  return {
2717
2719
  success: false,
2718
2720
  error: `Model file already exists: ${newFilePath}`
2719
2721
  };
2720
2722
  }
2721
- const content = await fs8__default.promises.readFile(oldFilePath, "utf-8");
2723
+ const content = await fs9__default.promises.readFile(oldFilePath, "utf-8");
2722
2724
  const updatedContent = content.replace(
2723
2725
  /name:\s*['"]([^'"]+)['"]/,
2724
2726
  `name: '${newName}'`
2725
2727
  );
2726
- await fs8__default.promises.writeFile(newFilePath, updatedContent, "utf-8");
2727
- await fs8__default.promises.unlink(oldFilePath);
2728
+ await fs9__default.promises.writeFile(newFilePath, updatedContent, "utf-8");
2729
+ await fs9__default.promises.unlink(oldFilePath);
2728
2730
  return {
2729
2731
  success: true,
2730
2732
  filePath: newFilePath
@@ -2738,17 +2740,17 @@ async function renameModel(modelsDir, oldName, newName) {
2738
2740
  }
2739
2741
  async function updateModelReferencesInPrompts(promptsDir, oldModelName, newModelName) {
2740
2742
  const updatedFiles = [];
2741
- if (!fs8__default.existsSync(promptsDir)) {
2743
+ if (!fs9__default.existsSync(promptsDir)) {
2742
2744
  return updatedFiles;
2743
2745
  }
2744
- const files = fs8__default.readdirSync(promptsDir).filter((f) => f.endsWith(".ts"));
2746
+ const files = fs9__default.readdirSync(promptsDir).filter((f) => f.endsWith(".ts"));
2745
2747
  for (const file of files) {
2746
- const filePath = path8__default.join(promptsDir, file);
2747
- let content = await fs8__default.promises.readFile(filePath, "utf-8");
2748
+ const filePath = path9__default.join(promptsDir, file);
2749
+ let content = await fs9__default.promises.readFile(filePath, "utf-8");
2748
2750
  const modelRegex = new RegExp(`model:\\s*['"]${escapeRegExp(oldModelName)}['"]`, "g");
2749
2751
  if (modelRegex.test(content)) {
2750
2752
  content = content.replace(modelRegex, `model: '${newModelName}'`);
2751
- await fs8__default.promises.writeFile(filePath, content, "utf-8");
2753
+ await fs9__default.promises.writeFile(filePath, content, "utf-8");
2752
2754
  updatedFiles.push(filePath);
2753
2755
  }
2754
2756
  }
@@ -2756,13 +2758,13 @@ async function updateModelReferencesInPrompts(promptsDir, oldModelName, newModel
2756
2758
  }
2757
2759
  async function updatePromptReferencesInPrompts(promptsDir, oldPromptName, newPromptName) {
2758
2760
  const updatedFiles = [];
2759
- if (!fs8__default.existsSync(promptsDir)) {
2761
+ if (!fs9__default.existsSync(promptsDir)) {
2760
2762
  return updatedFiles;
2761
2763
  }
2762
- const files = fs8__default.readdirSync(promptsDir).filter((f) => f.endsWith(".ts"));
2764
+ const files = fs9__default.readdirSync(promptsDir).filter((f) => f.endsWith(".ts"));
2763
2765
  for (const file of files) {
2764
- const filePath = path8__default.join(promptsDir, file);
2765
- let content = await fs8__default.promises.readFile(filePath, "utf-8");
2766
+ const filePath = path9__default.join(promptsDir, file);
2767
+ let content = await fs9__default.promises.readFile(filePath, "utf-8");
2766
2768
  let modified = false;
2767
2769
  const toolsArrayRegex = /tools:\s*\[([^\]]*)\]/gs;
2768
2770
  const newContent = content.replace(toolsArrayRegex, (match) => {
@@ -2775,7 +2777,7 @@ async function updatePromptReferencesInPrompts(promptsDir, oldPromptName, newPro
2775
2777
  return replaced;
2776
2778
  });
2777
2779
  if (modified) {
2778
- await fs8__default.promises.writeFile(filePath, newContent, "utf-8");
2780
+ await fs9__default.promises.writeFile(filePath, newContent, "utf-8");
2779
2781
  updatedFiles.push(filePath);
2780
2782
  }
2781
2783
  }
@@ -2783,17 +2785,17 @@ async function updatePromptReferencesInPrompts(promptsDir, oldPromptName, newPro
2783
2785
  }
2784
2786
  async function updatePromptReferencesInAgents(agentsDir, oldPromptName, newPromptName) {
2785
2787
  const updatedFiles = [];
2786
- if (!fs8__default.existsSync(agentsDir)) {
2788
+ if (!fs9__default.existsSync(agentsDir)) {
2787
2789
  return updatedFiles;
2788
2790
  }
2789
- const files = fs8__default.readdirSync(agentsDir).filter((f) => f.endsWith(".ts"));
2791
+ const files = fs9__default.readdirSync(agentsDir).filter((f) => f.endsWith(".ts"));
2790
2792
  for (const file of files) {
2791
- const filePath = path8__default.join(agentsDir, file);
2792
- let content = await fs8__default.promises.readFile(filePath, "utf-8");
2793
+ const filePath = path9__default.join(agentsDir, file);
2794
+ let content = await fs9__default.promises.readFile(filePath, "utf-8");
2793
2795
  const promptRegex = new RegExp(`prompt:\\s*['"]${escapeRegExp(oldPromptName)}['"]`, "g");
2794
2796
  if (promptRegex.test(content)) {
2795
2797
  content = content.replace(promptRegex, `prompt: '${newPromptName}'`);
2796
- await fs8__default.promises.writeFile(filePath, content, "utf-8");
2798
+ await fs9__default.promises.writeFile(filePath, content, "utf-8");
2797
2799
  updatedFiles.push(filePath);
2798
2800
  }
2799
2801
  }
@@ -2920,16 +2922,16 @@ function parseThreadEndpointRouteKey(input) {
2920
2922
  };
2921
2923
  }
2922
2924
  function scanThreadEndpointFiles(dir, options = {}) {
2923
- if (!fs8__default.existsSync(dir)) {
2925
+ if (!fs9__default.existsSync(dir)) {
2924
2926
  return [];
2925
2927
  }
2926
2928
  const extensions = options.extensions ?? [".ts"];
2927
2929
  const routes = [];
2928
2930
  const scan = (currentDir, relativeDir = "") => {
2929
- const entries = fs8__default.readdirSync(currentDir, { withFileTypes: true });
2931
+ const entries = fs9__default.readdirSync(currentDir, { withFileTypes: true });
2930
2932
  for (const entry of entries) {
2931
- const filePath = path8__default.join(currentDir, entry.name);
2932
- const relativePath = relativeDir ? path8__default.posix.join(relativeDir, entry.name) : entry.name;
2933
+ const filePath = path9__default.join(currentDir, entry.name);
2934
+ const relativePath = relativeDir ? path9__default.posix.join(relativeDir, entry.name) : entry.name;
2933
2935
  if (entry.isDirectory()) {
2934
2936
  scan(filePath, relativePath);
2935
2937
  continue;
@@ -2963,7 +2965,7 @@ function scanApiDirectory(dir) {
2963
2965
  try {
2964
2966
  return scanThreadEndpointFiles(dir, {
2965
2967
  extensions: [".ts"],
2966
- importPathForFile: (filePath) => "./" + path8__default.relative(process.cwd(), filePath).replace(/\\/g, "/")
2968
+ importPathForFile: (filePath) => "./" + path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/")
2967
2969
  }).map(({ method, route, importPath }) => ({
2968
2970
  method,
2969
2971
  route,
@@ -2975,26 +2977,26 @@ function scanApiDirectory(dir) {
2975
2977
  }
2976
2978
  }
2977
2979
  function discoverPackedPackageDirectories(packedDir) {
2978
- if (!fs8__default.existsSync(packedDir)) {
2980
+ if (!fs9__default.existsSync(packedDir)) {
2979
2981
  return [];
2980
2982
  }
2981
2983
  const packageDirs = [];
2982
- const entries = fs8__default.readdirSync(packedDir, { withFileTypes: true }).filter((entry) => entry.isDirectory());
2984
+ const entries = fs9__default.readdirSync(packedDir, { withFileTypes: true }).filter((entry) => entry.isDirectory());
2983
2985
  for (const entry of entries) {
2984
- const fullPath = path8__default.join(packedDir, entry.name);
2985
- const packageJsonPath = path8__default.join(fullPath, "package.json");
2986
- if (fs8__default.existsSync(packageJsonPath)) {
2986
+ const fullPath = path9__default.join(packedDir, entry.name);
2987
+ const packageJsonPath = path9__default.join(fullPath, "package.json");
2988
+ if (fs9__default.existsSync(packageJsonPath)) {
2987
2989
  packageDirs.push(fullPath);
2988
2990
  continue;
2989
2991
  }
2990
2992
  if (!entry.name.startsWith("@")) {
2991
2993
  continue;
2992
2994
  }
2993
- const scopedEntries = fs8__default.readdirSync(fullPath, { withFileTypes: true }).filter((scopedEntry) => scopedEntry.isDirectory());
2995
+ const scopedEntries = fs9__default.readdirSync(fullPath, { withFileTypes: true }).filter((scopedEntry) => scopedEntry.isDirectory());
2994
2996
  for (const scopedEntry of scopedEntries) {
2995
- const scopedPackagePath = path8__default.join(fullPath, scopedEntry.name);
2996
- const scopedPackageJson = path8__default.join(scopedPackagePath, "package.json");
2997
- if (fs8__default.existsSync(scopedPackageJson)) {
2997
+ const scopedPackagePath = path9__default.join(fullPath, scopedEntry.name);
2998
+ const scopedPackageJson = path9__default.join(scopedPackagePath, "package.json");
2999
+ if (fs9__default.existsSync(scopedPackageJson)) {
2998
3000
  packageDirs.push(scopedPackagePath);
2999
3001
  }
3000
3002
  }
@@ -3002,26 +3004,26 @@ function discoverPackedPackageDirectories(packedDir) {
3002
3004
  return packageDirs;
3003
3005
  }
3004
3006
  function scanPackedDistDirectory(packagePath, outputDir, subDir) {
3005
- const fullPath = path8__default.join(packagePath, outputDir, subDir);
3006
- if (!fs8__default.existsSync(fullPath)) {
3007
+ const fullPath = path9__default.join(packagePath, outputDir, subDir);
3008
+ if (!fs9__default.existsSync(fullPath)) {
3007
3009
  return [];
3008
3010
  }
3009
- return fs8__default.readdirSync(fullPath).filter((fileName) => fileName.endsWith(".js") || fileName.endsWith(".ts")).map((fileName) => ({
3011
+ return fs9__default.readdirSync(fullPath).filter((fileName) => fileName.endsWith(".js") || fileName.endsWith(".ts")).map((fileName) => ({
3010
3012
  name: fileName.replace(/\.(js|ts)$/, ""),
3011
- path: path8__default.join(fullPath, fileName).replace(/\\/g, "/")
3013
+ path: path9__default.join(fullPath, fileName).replace(/\\/g, "/")
3012
3014
  }));
3013
3015
  }
3014
3016
  function scanPackedThreadEndpoints(packagePath, outputDir) {
3015
- const rootDir = path8__default.join(packagePath, outputDir, "thread-endpoints");
3016
- if (!fs8__default.existsSync(rootDir)) {
3017
+ const rootDir = path9__default.join(packagePath, outputDir, "thread-endpoints");
3018
+ if (!fs9__default.existsSync(rootDir)) {
3017
3019
  return [];
3018
3020
  }
3019
3021
  const endpoints = [];
3020
3022
  const scan = (dir, relativeDir = "") => {
3021
- const entries = fs8__default.readdirSync(dir, { withFileTypes: true });
3023
+ const entries = fs9__default.readdirSync(dir, { withFileTypes: true });
3022
3024
  for (const entry of entries) {
3023
- const nextRelative = relativeDir ? path8__default.posix.join(relativeDir, entry.name) : entry.name;
3024
- const absolutePath = path8__default.join(dir, entry.name);
3025
+ const nextRelative = relativeDir ? path9__default.posix.join(relativeDir, entry.name) : entry.name;
3026
+ const absolutePath = path9__default.join(dir, entry.name);
3025
3027
  if (entry.isDirectory()) {
3026
3028
  scan(absolutePath, nextRelative);
3027
3029
  continue;
@@ -3051,7 +3053,7 @@ function isSnakeCase(str) {
3051
3053
  }
3052
3054
  function validateToolFile(filePath, fileName) {
3053
3055
  try {
3054
- const content = fs8__default.readFileSync(filePath, "utf-8");
3056
+ const content = fs9__default.readFileSync(filePath, "utf-8");
3055
3057
  const hasDefaultExport = /export\s+default\s+defineTool/.test(content);
3056
3058
  if (!hasDefaultExport) {
3057
3059
  return `Tool file '${fileName}.ts' must have a default export using defineTool()`;
@@ -3063,15 +3065,15 @@ function validateToolFile(filePath, fileName) {
3063
3065
  }
3064
3066
  async function scanToolsDirectory(dir) {
3065
3067
  const tools = [];
3066
- if (!fs8__default.existsSync(dir)) {
3068
+ if (!fs9__default.existsSync(dir)) {
3067
3069
  return tools;
3068
3070
  }
3069
- const entries = await fs8__default.promises.readdir(dir, { withFileTypes: true });
3071
+ const entries = await fs9__default.promises.readdir(dir, { withFileTypes: true });
3070
3072
  for (const entry of entries) {
3071
3073
  if (entry.isFile() && entry.name.endsWith(".ts")) {
3072
3074
  const fileName = entry.name.replace(".ts", "");
3073
- const filePath = path8__default.join(dir, entry.name);
3074
- const importPath = "./" + path8__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3075
+ const filePath = path9__default.join(dir, entry.name);
3076
+ const importPath = "./" + path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3075
3077
  let toolError;
3076
3078
  const validationError = validateToolFile(filePath, fileName);
3077
3079
  if (validationError) {
@@ -3098,18 +3100,18 @@ async function scanToolsDirectory(dir) {
3098
3100
  }
3099
3101
  async function scanHooksDirectory(dir) {
3100
3102
  const hooks = [];
3101
- if (!fs8__default.existsSync(dir)) {
3103
+ if (!fs9__default.existsSync(dir)) {
3102
3104
  return hooks;
3103
3105
  }
3104
- const entries = await fs8__default.promises.readdir(dir, { withFileTypes: true });
3106
+ const entries = await fs9__default.promises.readdir(dir, { withFileTypes: true });
3105
3107
  for (const entry of entries) {
3106
3108
  if (entry.isFile() && entry.name.endsWith(".ts")) {
3107
3109
  const fileName = entry.name.replace(".ts", "");
3108
3110
  if (fileName === "index") continue;
3109
- const filePath = path8__default.join(dir, entry.name);
3110
- const importPath = "./" + path8__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3111
+ const filePath = path9__default.join(dir, entry.name);
3112
+ const importPath = "./" + path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3111
3113
  try {
3112
- const content = fs8__default.readFileSync(filePath, "utf-8");
3114
+ const content = fs9__default.readFileSync(filePath, "utf-8");
3113
3115
  const idMatch = content.match(/id:\s*['"]([^'"]+)['"]/);
3114
3116
  const hookMatch = content.match(/hook:\s*['"]([^'"]+)['"]/);
3115
3117
  if (idMatch && hookMatch) {
@@ -3132,16 +3134,16 @@ async function scanHooksDirectory(dir) {
3132
3134
  }
3133
3135
  async function scanConfigDirectory(dir, definePattern) {
3134
3136
  const items = [];
3135
- if (!fs8__default.existsSync(dir)) {
3137
+ if (!fs9__default.existsSync(dir)) {
3136
3138
  return items;
3137
3139
  }
3138
- const entries = await fs8__default.promises.readdir(dir, { withFileTypes: true });
3140
+ const entries = await fs9__default.promises.readdir(dir, { withFileTypes: true });
3139
3141
  for (const entry of entries) {
3140
3142
  if (entry.isFile() && entry.name.endsWith(".ts")) {
3141
- const filePath = path8__default.join(dir, entry.name);
3142
- const importPath = "./" + path8__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3143
+ const filePath = path9__default.join(dir, entry.name);
3144
+ const importPath = "./" + path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3143
3145
  try {
3144
- const content = fs8__default.readFileSync(filePath, "utf-8");
3146
+ const content = fs9__default.readFileSync(filePath, "utf-8");
3145
3147
  const hasDefaultExport = definePattern.test(content);
3146
3148
  if (!hasDefaultExport) {
3147
3149
  items.push({
@@ -3186,20 +3188,20 @@ async function scanAgentsDirectory(dir) {
3186
3188
  }
3187
3189
  async function scanEffectsDirectory(dir) {
3188
3190
  const effects = [];
3189
- if (!fs8__default.existsSync(dir)) {
3191
+ if (!fs9__default.existsSync(dir)) {
3190
3192
  return effects;
3191
3193
  }
3192
- const entries = await fs8__default.promises.readdir(dir, { withFileTypes: true });
3194
+ const entries = await fs9__default.promises.readdir(dir, { withFileTypes: true });
3193
3195
  for (const entry of entries) {
3194
3196
  if (entry.isFile() && entry.name.endsWith(".ts")) {
3195
3197
  const fileName = entry.name.replace(".ts", "");
3196
- const filePath = path8__default.join(dir, entry.name);
3197
- const importPath = "./" + path8__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3198
+ const filePath = path9__default.join(dir, entry.name);
3199
+ const importPath = "./" + path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3198
3200
  if (fileName === "CLAUDE" || fileName.startsWith("_")) {
3199
3201
  continue;
3200
3202
  }
3201
3203
  try {
3202
- const content = fs8__default.readFileSync(filePath, "utf-8");
3204
+ const content = fs9__default.readFileSync(filePath, "utf-8");
3203
3205
  if (!content.includes("defineEffect")) {
3204
3206
  continue;
3205
3207
  }
@@ -3212,14 +3214,14 @@ async function scanEffectsDirectory(dir) {
3212
3214
  return effects;
3213
3215
  }
3214
3216
  function parseRequestBody(req) {
3215
- return new Promise((resolve2, reject) => {
3217
+ return new Promise((resolve3, reject) => {
3216
3218
  let body = "";
3217
3219
  req.on("data", (chunk) => {
3218
3220
  body += chunk.toString();
3219
3221
  });
3220
3222
  req.on("end", () => {
3221
3223
  try {
3222
- resolve2(body ? JSON.parse(body) : {});
3224
+ resolve3(body ? JSON.parse(body) : {});
3223
3225
  } catch {
3224
3226
  reject(new Error("Invalid JSON body"));
3225
3227
  }
@@ -3229,17 +3231,17 @@ function parseRequestBody(req) {
3229
3231
  }
3230
3232
  function scanUsersDirectory(dir) {
3231
3233
  const results = [];
3232
- if (!fs8__default.existsSync(dir)) return results;
3234
+ if (!fs9__default.existsSync(dir)) return results;
3233
3235
  const walk = (current, prefix) => {
3234
3236
  let entries;
3235
3237
  try {
3236
- entries = fs8__default.readdirSync(current, { withFileTypes: true });
3238
+ entries = fs9__default.readdirSync(current, { withFileTypes: true });
3237
3239
  } catch (error) {
3238
3240
  console.error(`Error scanning users directory ${current}:`, error);
3239
3241
  return;
3240
3242
  }
3241
3243
  for (const entry of entries) {
3242
- const fullPath = path8__default.join(current, entry.name);
3244
+ const fullPath = path9__default.join(current, entry.name);
3243
3245
  if (entry.isDirectory()) {
3244
3246
  walk(fullPath, prefix ? `${prefix}/${entry.name}` : entry.name);
3245
3247
  continue;
@@ -3249,7 +3251,7 @@ function scanUsersDirectory(dir) {
3249
3251
  const key = prefix ? `${prefix}/${base}` : base;
3250
3252
  results.push({
3251
3253
  key,
3252
- importPath: "./" + path8__default.relative(process.cwd(), fullPath).replace(/\\/g, "/")
3254
+ importPath: "./" + path9__default.relative(process.cwd(), fullPath).replace(/\\/g, "/")
3253
3255
  });
3254
3256
  }
3255
3257
  };
@@ -3482,7 +3484,7 @@ async function handleModelApiRequest(context) {
3482
3484
  }
3483
3485
  await hmr.reloadRouterModule(server);
3484
3486
  await hmr.reloadBuilderModule(server);
3485
- await new Promise((resolve2) => setTimeout(resolve2, 100));
3487
+ await new Promise((resolve3) => setTimeout(resolve3, 100));
3486
3488
  res.statusCode = 200;
3487
3489
  res.setHeader("Content-Type", "application/json");
3488
3490
  res.end(JSON.stringify({
@@ -3709,6 +3711,49 @@ async function handleConfigApiRequest(context) {
3709
3711
  if (await handleAgentApiRequest(context)) return true;
3710
3712
  return false;
3711
3713
  }
3714
+
3715
+ // src/packing/package-identifier.ts
3716
+ function assertSafePackageIdentifier(identifier) {
3717
+ const value = identifier.trim();
3718
+ if (!value || value.includes("\\") || value.includes("\0") || value.startsWith("/")) {
3719
+ throw new Error("Invalid package identifier");
3720
+ }
3721
+ const parts = value.split("/");
3722
+ const scoped = parts.length === 2 && parts[0].startsWith("@");
3723
+ if (parts.length > 1 && !scoped) throw new Error("Invalid package identifier");
3724
+ if (parts.some((part) => !part || part === "." || part === ".." || !/^@?[a-zA-Z0-9._-]+$/.test(part))) {
3725
+ throw new Error("Invalid package identifier");
3726
+ }
3727
+ return value;
3728
+ }
3729
+
3730
+ // src/packing/path-safety.ts
3731
+ function isWithin(base, candidate) {
3732
+ const relative4 = path9.relative(base, candidate);
3733
+ return relative4 === "" || !relative4.startsWith(`..${path9.sep}`) && relative4 !== ".." && !path9.isAbsolute(relative4);
3734
+ }
3735
+ function resolvePathWithin(base, ...segments) {
3736
+ const resolvedBase = path9.resolve(base);
3737
+ const candidate = path9.resolve(resolvedBase, ...segments);
3738
+ if (!isWithin(resolvedBase, candidate)) {
3739
+ throw new Error("Path must remain inside the configured AgentBuilder directory");
3740
+ }
3741
+ if (fs9.existsSync(resolvedBase)) {
3742
+ const realBase = fs9.realpathSync(resolvedBase);
3743
+ if (typeof realBase !== "string") return candidate;
3744
+ let existing = candidate;
3745
+ while (!fs9.existsSync(existing) && existing !== resolvedBase) {
3746
+ existing = path9.dirname(existing);
3747
+ }
3748
+ if (fs9.existsSync(existing)) {
3749
+ const realExisting = fs9.realpathSync(existing);
3750
+ if (typeof realExisting === "string" && !isWithin(realBase, realExisting)) {
3751
+ throw new Error("Path traverses a symlink outside the configured AgentBuilder directory");
3752
+ }
3753
+ }
3754
+ }
3755
+ return candidate;
3756
+ }
3712
3757
  var MetadataService = class {
3713
3758
  metadataDir;
3714
3759
  /**
@@ -3717,7 +3762,7 @@ var MetadataService = class {
3717
3762
  * @param agentsDir - Path to the agents/ directory
3718
3763
  */
3719
3764
  constructor(agentsDir) {
3720
- this.metadataDir = path8.join(agentsDir, ".standardagent");
3765
+ this.metadataDir = path9.join(agentsDir, ".standardagent");
3721
3766
  }
3722
3767
  /**
3723
3768
  * Read metadata for an agent.
@@ -3727,11 +3772,11 @@ var MetadataService = class {
3727
3772
  */
3728
3773
  async read(agentName) {
3729
3774
  const filePath = this.getMetadataPath(agentName);
3730
- if (!fs8.existsSync(filePath)) {
3775
+ if (!fs9.existsSync(filePath)) {
3731
3776
  return null;
3732
3777
  }
3733
3778
  try {
3734
- const content = fs8.readFileSync(filePath, "utf-8");
3779
+ const content = fs9.readFileSync(filePath, "utf-8");
3735
3780
  return JSON.parse(content);
3736
3781
  } catch {
3737
3782
  return null;
@@ -3744,11 +3789,11 @@ var MetadataService = class {
3744
3789
  * @param metadata - Metadata to write
3745
3790
  */
3746
3791
  async write(agentName, metadata) {
3747
- if (!fs8.existsSync(this.metadataDir)) {
3748
- fs8.mkdirSync(this.metadataDir, { recursive: true });
3792
+ if (!fs9.existsSync(this.metadataDir)) {
3793
+ fs9.mkdirSync(this.metadataDir, { recursive: true });
3749
3794
  }
3750
3795
  const filePath = this.getMetadataPath(agentName);
3751
- fs8.writeFileSync(filePath, JSON.stringify(metadata, null, 2));
3796
+ fs9.writeFileSync(filePath, JSON.stringify(metadata, null, 2));
3752
3797
  }
3753
3798
  /**
3754
3799
  * Delete metadata for an agent.
@@ -3757,8 +3802,8 @@ var MetadataService = class {
3757
3802
  */
3758
3803
  async delete(agentName) {
3759
3804
  const filePath = this.getMetadataPath(agentName);
3760
- if (fs8.existsSync(filePath)) {
3761
- fs8.unlinkSync(filePath);
3805
+ if (fs9.existsSync(filePath)) {
3806
+ fs9.unlinkSync(filePath);
3762
3807
  }
3763
3808
  }
3764
3809
  /**
@@ -3839,7 +3884,7 @@ var MetadataService = class {
3839
3884
  * Get the file path for an agent's metadata.
3840
3885
  */
3841
3886
  getMetadataPath(agentName) {
3842
- return path8.join(this.metadataDir, `${agentName}.json`);
3887
+ return path9.join(this.metadataDir, `${agentName}.json`);
3843
3888
  }
3844
3889
  };
3845
3890
  var _ts;
@@ -4211,9 +4256,9 @@ var PackingService = class {
4211
4256
  * @returns Version specifier (e.g., '^1.2.3') or '*' if not found
4212
4257
  */
4213
4258
  resolvePackageVersion(pkgName, rootDir) {
4214
- const pkgJsonPath = path8.join(rootDir, "node_modules", pkgName, "package.json");
4259
+ const pkgJsonPath = path9.join(rootDir, "node_modules", pkgName, "package.json");
4215
4260
  try {
4216
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
4261
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
4217
4262
  return `^${pkgJson.version}`;
4218
4263
  } catch {
4219
4264
  return "*";
@@ -4230,7 +4275,7 @@ var PackingService = class {
4230
4275
  * @returns Analysis result with all discovered constituents
4231
4276
  */
4232
4277
  async analyzeAgent(agentName, rootDir) {
4233
- const agentsDir = path8.join(rootDir, "agents");
4278
+ const agentsDir = path9.join(rootDir, "agents");
4234
4279
  const analysis = {
4235
4280
  agent: agentName,
4236
4281
  primaryPrompt: "",
@@ -4254,7 +4299,7 @@ var PackingService = class {
4254
4299
  warnings: [],
4255
4300
  errors: []
4256
4301
  };
4257
- const agentFilePath = await this.findFile(path8.join(agentsDir, "agents"), agentName);
4302
+ const agentFilePath = await this.findFile(path9.join(agentsDir, "agents"), agentName);
4258
4303
  if (!agentFilePath) {
4259
4304
  analysis.errors.push(`Agent file not found: ${agentName}`);
4260
4305
  return analysis;
@@ -4265,7 +4310,7 @@ var PackingService = class {
4265
4310
  discoveredVia: "static",
4266
4311
  sharedWith: []
4267
4312
  });
4268
- const agentSource = fs8.readFileSync(agentFilePath, "utf-8");
4313
+ const agentSource = fs9.readFileSync(agentFilePath, "utf-8");
4269
4314
  const agentPrompts = await extractAgentPrompts(agentSource);
4270
4315
  if (agentPrompts.sideA) {
4271
4316
  analysis.primaryPrompt = agentPrompts.sideA;
@@ -4290,13 +4335,13 @@ var PackingService = class {
4290
4335
  * @returns Object with generatedReadme and agentDescription
4291
4336
  */
4292
4337
  async generateReadmeForAnalysis(analysis, rootDir) {
4293
- const agentsDir = path8.join(rootDir, "agents");
4338
+ const agentsDir = path9.join(rootDir, "agents");
4294
4339
  const metadataService = new MetadataService(agentsDir);
4295
4340
  let agentDescription;
4296
4341
  const agentItem = analysis.constituents.agents.find((a) => a.name === analysis.agent);
4297
4342
  if (agentItem?.filePath) {
4298
4343
  try {
4299
- const agentSource = fs8.readFileSync(agentItem.filePath, "utf-8");
4344
+ const agentSource = fs9.readFileSync(agentItem.filePath, "utf-8");
4300
4345
  agentDescription = await extractAgentDescription(agentSource) || void 0;
4301
4346
  } catch {
4302
4347
  }
@@ -4320,7 +4365,7 @@ var PackingService = class {
4320
4365
  * include all endpoint modules discovered under agents/api.
4321
4366
  */
4322
4367
  async analyzeThreadEndpoints(agentsDir, analysis) {
4323
- const apiDir = path8.join(agentsDir, "api");
4368
+ const apiDir = path9.join(agentsDir, "api");
4324
4369
  const endpoints = this.scanThreadEndpointFiles(apiDir);
4325
4370
  for (const endpoint of endpoints) {
4326
4371
  if (analysis.constituents.threadEndpoints.some((item) => item.name === endpoint.name)) {
@@ -4342,15 +4387,15 @@ var PackingService = class {
4342
4387
  * - `admin/users/[userId]/sync.post`
4343
4388
  */
4344
4389
  scanThreadEndpointFiles(apiDir, relativeDir = "") {
4345
- if (!fs8.existsSync(apiDir)) {
4390
+ if (!fs9.existsSync(apiDir)) {
4346
4391
  return [];
4347
4392
  }
4348
4393
  const endpoints = [];
4349
- const currentDir = relativeDir ? path8.join(apiDir, relativeDir) : apiDir;
4350
- if (!fs8.existsSync(currentDir)) {
4394
+ const currentDir = relativeDir ? path9.join(apiDir, relativeDir) : apiDir;
4395
+ if (!fs9.existsSync(currentDir)) {
4351
4396
  return endpoints;
4352
4397
  }
4353
- const entries = fs8.readdirSync(currentDir, { withFileTypes: true });
4398
+ const entries = fs9.readdirSync(currentDir, { withFileTypes: true });
4354
4399
  if (entries.length > 0 && typeof entries[0] === "string") {
4355
4400
  return endpoints;
4356
4401
  }
@@ -4358,8 +4403,8 @@ var PackingService = class {
4358
4403
  const entryName = typeof entry === "string" ? entry : entry.name;
4359
4404
  const isDirectory = typeof entry === "string" ? false : entry.isDirectory();
4360
4405
  const isFile = typeof entry === "string" ? true : entry.isFile();
4361
- const entryRelative = relativeDir ? path8.posix.join(relativeDir.replace(/\\/g, "/"), entryName) : entryName;
4362
- const absolutePath = path8.join(apiDir, entryRelative);
4406
+ const entryRelative = relativeDir ? path9.posix.join(relativeDir.replace(/\\/g, "/"), entryName) : entryName;
4407
+ const absolutePath = path9.join(apiDir, entryRelative);
4363
4408
  if (isDirectory) {
4364
4409
  endpoints.push(...this.scanThreadEndpointFiles(apiDir, entryRelative));
4365
4410
  continue;
@@ -4386,7 +4431,7 @@ var PackingService = class {
4386
4431
  * include all effect modules discovered under agents/effects.
4387
4432
  */
4388
4433
  async analyzeEffects(agentsDir, analysis) {
4389
- const effectsDir = path8.join(agentsDir, "effects");
4434
+ const effectsDir = path9.join(agentsDir, "effects");
4390
4435
  const effects = this.scanEffectFiles(effectsDir);
4391
4436
  for (const effect of effects) {
4392
4437
  if (analysis.constituents.effects.some((item) => item.name === effect.name)) {
@@ -4408,15 +4453,15 @@ var PackingService = class {
4408
4453
  * - `notifications/digest`
4409
4454
  */
4410
4455
  scanEffectFiles(effectsDir, relativeDir = "") {
4411
- if (!fs8.existsSync(effectsDir)) {
4456
+ if (!fs9.existsSync(effectsDir)) {
4412
4457
  return [];
4413
4458
  }
4414
4459
  const effects = [];
4415
- const currentDir = relativeDir ? path8.join(effectsDir, relativeDir) : effectsDir;
4416
- if (!fs8.existsSync(currentDir)) {
4460
+ const currentDir = relativeDir ? path9.join(effectsDir, relativeDir) : effectsDir;
4461
+ if (!fs9.existsSync(currentDir)) {
4417
4462
  return effects;
4418
4463
  }
4419
- const entries = fs8.readdirSync(currentDir, { withFileTypes: true });
4464
+ const entries = fs9.readdirSync(currentDir, { withFileTypes: true });
4420
4465
  if (entries.length > 0 && typeof entries[0] === "string") {
4421
4466
  return effects;
4422
4467
  }
@@ -4424,8 +4469,8 @@ var PackingService = class {
4424
4469
  const entryName = typeof entry === "string" ? entry : entry.name;
4425
4470
  const isDirectory = typeof entry === "string" ? false : entry.isDirectory();
4426
4471
  const isFile = typeof entry === "string" ? true : entry.isFile();
4427
- const entryRelative = relativeDir ? path8.posix.join(relativeDir.replace(/\\/g, "/"), entryName) : entryName;
4428
- const absolutePath = path8.join(effectsDir, entryRelative);
4472
+ const entryRelative = relativeDir ? path9.posix.join(relativeDir.replace(/\\/g, "/"), entryName) : entryName;
4473
+ const absolutePath = path9.join(effectsDir, entryRelative);
4429
4474
  if (isDirectory) {
4430
4475
  effects.push(...this.scanEffectFiles(effectsDir, entryRelative));
4431
4476
  continue;
@@ -4449,7 +4494,7 @@ var PackingService = class {
4449
4494
  * Recursively analyze a prompt and its dependencies.
4450
4495
  */
4451
4496
  async analyzePrompt(promptName, agentsDir, analysis, visited, parentKey) {
4452
- const promptFilePath = await this.findFile(path8.join(agentsDir, "prompts"), promptName);
4497
+ const promptFilePath = await this.findFile(path9.join(agentsDir, "prompts"), promptName);
4453
4498
  if (!promptFilePath) {
4454
4499
  analysis.warnings.push(`Prompt file not found: ${promptName}`);
4455
4500
  return;
@@ -4468,7 +4513,7 @@ var PackingService = class {
4468
4513
  return;
4469
4514
  }
4470
4515
  visited.add(`prompt:${promptName}`);
4471
- const promptSource = fs8.readFileSync(promptFilePath, "utf-8");
4516
+ const promptSource = fs9.readFileSync(promptFilePath, "utf-8");
4472
4517
  const modelName = await extractPromptModel(promptSource);
4473
4518
  if (modelName) {
4474
4519
  await this.analyzeModel(modelName, agentsDir, analysis, visited, thisKey);
@@ -4494,17 +4539,17 @@ var PackingService = class {
4494
4539
  */
4495
4540
  async analyzeTool(toolName, agentsDir, analysis, visited, discoveredVia, parentKey) {
4496
4541
  const thisKey = `tool:${toolName}`;
4497
- const promptFilePath = await this.findFile(path8.join(agentsDir, "prompts"), toolName);
4542
+ const promptFilePath = await this.findFile(path9.join(agentsDir, "prompts"), toolName);
4498
4543
  if (promptFilePath) {
4499
4544
  await this.analyzePrompt(toolName, agentsDir, analysis, visited, parentKey);
4500
4545
  return;
4501
4546
  }
4502
- const agentFilePath = await this.findFile(path8.join(agentsDir, "agents"), toolName);
4547
+ const agentFilePath = await this.findFile(path9.join(agentsDir, "agents"), toolName);
4503
4548
  if (agentFilePath) {
4504
4549
  await this.analyzeNestedAgent(toolName, agentsDir, analysis, visited, parentKey);
4505
4550
  return;
4506
4551
  }
4507
- const toolFilePath = await this.findFile(path8.join(agentsDir, "tools"), toolName);
4552
+ const toolFilePath = await this.findFile(path9.join(agentsDir, "tools"), toolName);
4508
4553
  if (!toolFilePath) {
4509
4554
  analysis.warnings.push(`Tool file not found: ${toolName}`);
4510
4555
  return;
@@ -4522,7 +4567,7 @@ var PackingService = class {
4522
4567
  return;
4523
4568
  }
4524
4569
  visited.add(`tool:${toolName}`);
4525
- const toolSource = fs8.readFileSync(toolFilePath, "utf-8");
4570
+ const toolSource = fs9.readFileSync(toolFilePath, "utf-8");
4526
4571
  const { uses } = await extractToolUses(toolSource);
4527
4572
  for (const usedItem of uses) {
4528
4573
  await this.analyzeTool(usedItem, agentsDir, analysis, visited, "uses", thisKey);
@@ -4532,7 +4577,7 @@ var PackingService = class {
4532
4577
  * Analyze a nested agent (used as a handoff target).
4533
4578
  */
4534
4579
  async analyzeNestedAgent(agentName, agentsDir, analysis, visited, parentKey) {
4535
- const agentFilePath = await this.findFile(path8.join(agentsDir, "agents"), agentName);
4580
+ const agentFilePath = await this.findFile(path9.join(agentsDir, "agents"), agentName);
4536
4581
  if (!agentFilePath) {
4537
4582
  analysis.warnings.push(`Agent file not found: ${agentName}`);
4538
4583
  return;
@@ -4551,7 +4596,7 @@ var PackingService = class {
4551
4596
  return;
4552
4597
  }
4553
4598
  visited.add(`agent:${agentName}`);
4554
- const agentSource = fs8.readFileSync(agentFilePath, "utf-8");
4599
+ const agentSource = fs9.readFileSync(agentFilePath, "utf-8");
4555
4600
  const agentPrompts = await extractAgentPrompts(agentSource);
4556
4601
  if (agentPrompts.sideA) {
4557
4602
  await this.analyzePrompt(agentPrompts.sideA, agentsDir, analysis, visited, thisKey);
@@ -4564,7 +4609,7 @@ var PackingService = class {
4564
4609
  * Analyze a model and its fallbacks.
4565
4610
  */
4566
4611
  async analyzeModel(modelName, agentsDir, analysis, visited, parentKey) {
4567
- const modelFilePath = await this.findFile(path8.join(agentsDir, "models"), modelName);
4612
+ const modelFilePath = await this.findFile(path9.join(agentsDir, "models"), modelName);
4568
4613
  if (!modelFilePath) {
4569
4614
  analysis.warnings.push(`Model file not found: ${modelName}`);
4570
4615
  return;
@@ -4583,7 +4628,7 @@ var PackingService = class {
4583
4628
  return;
4584
4629
  }
4585
4630
  visited.add(`model:${modelName}`);
4586
- const modelSource = fs8.readFileSync(modelFilePath, "utf-8");
4631
+ const modelSource = fs9.readFileSync(modelFilePath, "utf-8");
4587
4632
  const fallbacks = await extractModelFallbacks(modelSource);
4588
4633
  for (const fallbackName of fallbacks) {
4589
4634
  await this.analyzeModel(fallbackName, agentsDir, analysis, visited, thisKey);
@@ -4593,13 +4638,13 @@ var PackingService = class {
4593
4638
  * Check which items are shared with other agents.
4594
4639
  */
4595
4640
  async checkSharedItems(agentsDir, analysis) {
4596
- const agentsPath = path8.join(agentsDir, "agents");
4597
- if (!fs8.existsSync(agentsPath)) return;
4598
- const agentFiles = fs8.readdirSync(agentsPath).filter((f) => f.endsWith(".ts"));
4641
+ const agentsPath = path9.join(agentsDir, "agents");
4642
+ if (!fs9.existsSync(agentsPath)) return;
4643
+ const agentFiles = fs9.readdirSync(agentsPath).filter((f) => f.endsWith(".ts"));
4599
4644
  for (const agentFile of agentFiles) {
4600
4645
  const otherAgentName = agentFile.replace(".ts", "");
4601
4646
  if (otherAgentName === analysis.agent) continue;
4602
- const otherAnalysis = await this.analyzeAgentLight(otherAgentName, path8.dirname(agentsDir));
4647
+ const otherAnalysis = await this.analyzeAgentLight(otherAgentName, path9.dirname(agentsDir));
4603
4648
  for (const prompt of analysis.constituents.prompts) {
4604
4649
  if (otherAnalysis.prompts.includes(prompt.name)) {
4605
4650
  prompt.sharedWith.push(otherAgentName);
@@ -4631,19 +4676,19 @@ var PackingService = class {
4631
4676
  */
4632
4677
  async analyzeAgentLight(agentName, rootDir) {
4633
4678
  const result = { prompts: [], tools: [], models: [] };
4634
- const agentsDir = path8.join(rootDir, "agents");
4679
+ const agentsDir = path9.join(rootDir, "agents");
4635
4680
  const visited = /* @__PURE__ */ new Set();
4636
- const agentFilePath = await this.findFile(path8.join(agentsDir, "agents"), agentName);
4681
+ const agentFilePath = await this.findFile(path9.join(agentsDir, "agents"), agentName);
4637
4682
  if (!agentFilePath) return result;
4638
- const agentSource = fs8.readFileSync(agentFilePath, "utf-8");
4683
+ const agentSource = fs9.readFileSync(agentFilePath, "utf-8");
4639
4684
  const agentPrompts = await extractAgentPrompts(agentSource);
4640
4685
  const analyzePromptLight = async (promptName) => {
4641
4686
  if (visited.has(promptName)) return;
4642
4687
  visited.add(promptName);
4643
4688
  result.prompts.push(promptName);
4644
- const promptFilePath = await this.findFile(path8.join(agentsDir, "prompts"), promptName);
4689
+ const promptFilePath = await this.findFile(path9.join(agentsDir, "prompts"), promptName);
4645
4690
  if (!promptFilePath) return;
4646
- const promptSource = fs8.readFileSync(promptFilePath, "utf-8");
4691
+ const promptSource = fs9.readFileSync(promptFilePath, "utf-8");
4647
4692
  const modelName = await extractPromptModel(promptSource);
4648
4693
  if (modelName && !result.models.includes(modelName)) {
4649
4694
  result.models.push(modelName);
@@ -4716,14 +4761,15 @@ var PackingService = class {
4716
4761
  return result;
4717
4762
  }
4718
4763
  result.warnings = analysis.warnings;
4719
- const pkgOutputDir = path8.join(outputDir, packageId);
4720
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "agents"), { recursive: true });
4721
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "prompts"), { recursive: true });
4722
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "tools"), { recursive: true });
4723
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "models"), { recursive: true });
4724
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "hooks"), { recursive: true });
4725
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "effects"), { recursive: true });
4726
- fs8.mkdirSync(path8.join(pkgOutputDir, "dist", "thread-endpoints"), { recursive: true });
4764
+ const safePackageId = assertSafePackageIdentifier(packageId);
4765
+ const pkgOutputDir = resolvePathWithin(outputDir, safePackageId);
4766
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "agents"), { recursive: true });
4767
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "prompts"), { recursive: true });
4768
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "tools"), { recursive: true });
4769
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "models"), { recursive: true });
4770
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "hooks"), { recursive: true });
4771
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "effects"), { recursive: true });
4772
+ fs9.mkdirSync(path9.join(pkgOutputDir, "dist", "thread-endpoints"), { recursive: true });
4727
4773
  const seenItems = /* @__PURE__ */ new Set();
4728
4774
  const allItems = [];
4729
4775
  for (const a of analysis.constituents.agents) {
@@ -4777,13 +4823,13 @@ var PackingService = class {
4777
4823
  }
4778
4824
  const externalDeps = /* @__PURE__ */ new Map();
4779
4825
  for (const item of allItems) {
4780
- const outputPath = path8.join(
4826
+ const outputPath = resolvePathWithin(
4781
4827
  pkgOutputDir,
4782
4828
  "dist",
4783
4829
  this.getTypeDir(item.type),
4784
4830
  `${item.name}.js`
4785
4831
  );
4786
- fs8.mkdirSync(path8.dirname(outputPath), { recursive: true });
4832
+ fs9.mkdirSync(path9.dirname(outputPath), { recursive: true });
4787
4833
  const deps = await this.bundleFile(item.filePath, outputPath, rootDir);
4788
4834
  for (const [depName, depVersion] of deps) {
4789
4835
  if (!externalDeps.has(depName)) {
@@ -4793,12 +4839,12 @@ var PackingService = class {
4793
4839
  result.filesCreated.push(outputPath);
4794
4840
  }
4795
4841
  const indexJs = this.generateReExportIndex(analysis, meta);
4796
- const indexJsPath = path8.join(pkgOutputDir, "dist", "index.js");
4797
- fs8.writeFileSync(indexJsPath, indexJs);
4842
+ const indexJsPath = resolvePathWithin(pkgOutputDir, "dist", "index.js");
4843
+ fs9.writeFileSync(indexJsPath, indexJs);
4798
4844
  result.filesCreated.push(indexJsPath);
4799
4845
  const indexDts = this.generateIndexDts(analysis);
4800
- const indexDtsPath = path8.join(pkgOutputDir, "dist", "index.d.ts");
4801
- fs8.writeFileSync(indexDtsPath, indexDts);
4846
+ const indexDtsPath = resolvePathWithin(pkgOutputDir, "dist", "index.d.ts");
4847
+ fs9.writeFileSync(indexDtsPath, indexDts);
4802
4848
  result.filesCreated.push(indexDtsPath);
4803
4849
  const pkgJson = this.generatePackageJson(
4804
4850
  finalPackageName,
@@ -4811,13 +4857,13 @@ var PackingService = class {
4811
4857
  license,
4812
4858
  licenseOwner
4813
4859
  );
4814
- const pkgJsonPath = path8.join(pkgOutputDir, "package.json");
4815
- fs8.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
4860
+ const pkgJsonPath = path9.join(pkgOutputDir, "package.json");
4861
+ fs9.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
4816
4862
  result.filesCreated.push(pkgJsonPath);
4817
4863
  if (license) {
4818
4864
  const licenseContent = this.generateLicenseFile(license, licenseOwner);
4819
- const licensePath = path8.join(pkgOutputDir, "LICENSE");
4820
- fs8.writeFileSync(licensePath, licenseContent);
4865
+ const licensePath = path9.join(pkgOutputDir, "LICENSE");
4866
+ fs9.writeFileSync(licensePath, licenseContent);
4821
4867
  result.filesCreated.push(licensePath);
4822
4868
  }
4823
4869
  let readmeContent = readme;
@@ -4825,7 +4871,7 @@ var PackingService = class {
4825
4871
  const agentItem = analysis.constituents.agents.find((a) => a.name === agentName);
4826
4872
  let agentDescription;
4827
4873
  if (agentItem?.filePath) {
4828
- const agentSource = fs8.readFileSync(agentItem.filePath, "utf-8");
4874
+ const agentSource = fs9.readFileSync(agentItem.filePath, "utf-8");
4829
4875
  agentDescription = await extractAgentDescription(agentSource) || void 0;
4830
4876
  }
4831
4877
  readmeContent = this.generateReadme(
@@ -4836,21 +4882,21 @@ var PackingService = class {
4836
4882
  agentDescription
4837
4883
  );
4838
4884
  }
4839
- const readmePath = path8.join(pkgOutputDir, "README.md");
4840
- fs8.writeFileSync(readmePath, readmeContent);
4885
+ const readmePath = path9.join(pkgOutputDir, "README.md");
4886
+ fs9.writeFileSync(readmePath, readmeContent);
4841
4887
  result.filesCreated.push(readmePath);
4842
4888
  if (removeOriginals || itemSelections) {
4843
4889
  result.filesRemoved = [];
4844
4890
  for (const item of allItems) {
4845
4891
  const selection = itemSelections?.find((s) => s.name === item.name && s.type === item.type);
4846
4892
  const shouldRemove = selection ? selection.mode === "extract" : removeOriginals && item.sharedWith.length === 0 && item.type !== "thread-endpoint" && item.type !== "effect";
4847
- if (shouldRemove && fs8.existsSync(item.filePath)) {
4848
- fs8.unlinkSync(item.filePath);
4893
+ if (shouldRemove && fs9.existsSync(item.filePath)) {
4894
+ fs9.unlinkSync(item.filePath);
4849
4895
  result.filesRemoved.push(item.filePath);
4850
4896
  }
4851
4897
  }
4852
4898
  }
4853
- const agentsDir = path8.join(rootDir, "agents");
4899
+ const agentsDir = path9.join(rootDir, "agents");
4854
4900
  const metadataService = new MetadataService(agentsDir);
4855
4901
  const metadata = {
4856
4902
  packageName: finalPackageName,
@@ -4884,7 +4930,7 @@ var PackingService = class {
4884
4930
  const commonjs = (await import('@rollup/plugin-commonjs')).default;
4885
4931
  const esbuild = (await import('rollup-plugin-esbuild')).default;
4886
4932
  const externalDeps = /* @__PURE__ */ new Map();
4887
- const agentsDir = path8.join(rootDir, "agents");
4933
+ const agentsDir = path9.join(rootDir, "agents");
4888
4934
  const resolveVersion = this.resolvePackageVersion.bind(this);
4889
4935
  const trackExternalsPlugin = {
4890
4936
  name: "track-externals",
@@ -4893,14 +4939,14 @@ var PackingService = class {
4893
4939
  return null;
4894
4940
  }
4895
4941
  if (source.startsWith("./") || source.startsWith("../")) {
4896
- const resolved = path8.resolve(path8.dirname(importer), source);
4942
+ const resolved = path9.resolve(path9.dirname(importer), source);
4897
4943
  let tsResolved = resolved;
4898
4944
  if (!resolved.endsWith(".ts") && !resolved.endsWith(".js")) {
4899
- if (fs8.existsSync(`${resolved}.ts`)) {
4945
+ if (fs9.existsSync(`${resolved}.ts`)) {
4900
4946
  tsResolved = `${resolved}.ts`;
4901
- } else if (fs8.existsSync(`${resolved}.js`)) {
4947
+ } else if (fs9.existsSync(`${resolved}.js`)) {
4902
4948
  tsResolved = `${resolved}.js`;
4903
- } else if (fs8.existsSync(`${resolved}/index.ts`)) {
4949
+ } else if (fs9.existsSync(`${resolved}/index.ts`)) {
4904
4950
  tsResolved = `${resolved}/index.ts`;
4905
4951
  }
4906
4952
  }
@@ -4949,11 +4995,11 @@ var PackingService = class {
4949
4995
  exports: "named"
4950
4996
  });
4951
4997
  const bundledCode = output[0].code;
4952
- const header = `// Bundled from: ${path8.relative(rootDir, inputPath)}
4998
+ const header = `// Bundled from: ${path9.relative(rootDir, inputPath)}
4953
4999
  // Local dependencies have been inlined
4954
5000
 
4955
5001
  `;
4956
- fs8.writeFileSync(outputPath, header + bundledCode);
5002
+ fs9.writeFileSync(outputPath, header + bundledCode);
4957
5003
  await bundle.close();
4958
5004
  } catch (error) {
4959
5005
  await bundle.close();
@@ -5378,30 +5424,31 @@ Copyright (c) ${year} ${copyrightHolder}
5378
5424
  * @returns Package info or null if not found
5379
5425
  */
5380
5426
  getPackedInfo(packageId, rootDir) {
5381
- const packedDir = path8.join(rootDir, "agents", "packed");
5382
- let packageDir = path8.join(packedDir, packageId);
5383
- if (!fs8.existsSync(packageDir)) {
5384
- if (!fs8.existsSync(packedDir)) {
5427
+ const packedDir = path9.join(rootDir, "agents", "packed");
5428
+ const safePackageId = assertSafePackageIdentifier(packageId);
5429
+ let packageDir = resolvePathWithin(packedDir, safePackageId);
5430
+ if (!fs9.existsSync(packageDir)) {
5431
+ if (!fs9.existsSync(packedDir)) {
5385
5432
  return null;
5386
5433
  }
5387
- const dirs = fs8.readdirSync(packedDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
5434
+ const dirs = fs9.readdirSync(packedDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
5388
5435
  const matchingDir = dirs.find(
5389
5436
  (d) => d === packageId || d === `standardagent-${packageId}` || d === `standardagent-${packageId.replace(/_/g, "-")}`
5390
5437
  );
5391
5438
  if (!matchingDir) {
5392
5439
  return null;
5393
5440
  }
5394
- packageDir = path8.join(packedDir, matchingDir);
5441
+ packageDir = path9.join(packedDir, matchingDir);
5395
5442
  }
5396
- const pkgJsonPath = path8.join(packageDir, "package.json");
5397
- if (!fs8.existsSync(pkgJsonPath)) {
5443
+ const pkgJsonPath = path9.join(packageDir, "package.json");
5444
+ if (!fs9.existsSync(pkgJsonPath)) {
5398
5445
  return null;
5399
5446
  }
5400
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
5447
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
5401
5448
  let readme;
5402
- const readmePath = path8.join(packageDir, "README.md");
5403
- if (fs8.existsSync(readmePath)) {
5404
- readme = fs8.readFileSync(readmePath, "utf-8");
5449
+ const readmePath = path9.join(packageDir, "README.md");
5450
+ if (fs9.existsSync(readmePath)) {
5451
+ readme = fs9.readFileSync(readmePath, "utf-8");
5405
5452
  }
5406
5453
  return {
5407
5454
  packageName: pkgJson.name,
@@ -5419,11 +5466,11 @@ Copyright (c) ${year} ${copyrightHolder}
5419
5466
  * @returns Array of package directory names
5420
5467
  */
5421
5468
  listPackedPackages(rootDir) {
5422
- const packedDir = path8.join(rootDir, "agents", "packed");
5423
- if (!fs8.existsSync(packedDir)) {
5469
+ const packedDir = path9.join(rootDir, "agents", "packed");
5470
+ if (!fs9.existsSync(packedDir)) {
5424
5471
  return [];
5425
5472
  }
5426
- return fs8.readdirSync(packedDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
5473
+ return fs9.readdirSync(packedDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
5427
5474
  }
5428
5475
  /**
5429
5476
  * Generate README.md content for a packed agent.
@@ -5470,17 +5517,17 @@ ${license || "See LICENSE file"}
5470
5517
  * Find a file by name in a directory.
5471
5518
  */
5472
5519
  async findFile(dir, name) {
5473
- if (!fs8.existsSync(dir)) {
5520
+ if (!fs9.existsSync(dir)) {
5474
5521
  return null;
5475
5522
  }
5476
- const exactPath = path8.join(dir, `${name}.ts`);
5477
- if (fs8.existsSync(exactPath)) {
5523
+ const exactPath = resolvePathWithin(dir, `${name}.ts`);
5524
+ if (fs9.existsSync(exactPath)) {
5478
5525
  return exactPath;
5479
5526
  }
5480
- const files = fs8.readdirSync(dir).filter((f) => f.endsWith(".ts"));
5527
+ const files = fs9.readdirSync(dir).filter((f) => f.endsWith(".ts"));
5481
5528
  for (const file of files) {
5482
- const filePath = path8.join(dir, file);
5483
- const source = fs8.readFileSync(filePath, "utf-8");
5529
+ const filePath = path9.join(dir, file);
5530
+ const source = fs9.readFileSync(filePath, "utf-8");
5484
5531
  const extractedName = await extractDefinitionName(source);
5485
5532
  if (extractedName === name) {
5486
5533
  return filePath;
@@ -5492,15 +5539,15 @@ ${license || "See LICENSE file"}
5492
5539
  * List all agents in the workspace.
5493
5540
  */
5494
5541
  async listAgents(rootDir) {
5495
- const agentsDir = path8.join(rootDir, "agents", "agents");
5496
- if (!fs8.existsSync(agentsDir)) {
5542
+ const agentsDir = path9.join(rootDir, "agents", "agents");
5543
+ if (!fs9.existsSync(agentsDir)) {
5497
5544
  return [];
5498
5545
  }
5499
- const files = fs8.readdirSync(agentsDir).filter((f) => f.endsWith(".ts"));
5546
+ const files = fs9.readdirSync(agentsDir).filter((f) => f.endsWith(".ts"));
5500
5547
  const agents = [];
5501
5548
  for (const file of files) {
5502
- const filePath = path8.join(agentsDir, file);
5503
- const source = fs8.readFileSync(filePath, "utf-8");
5549
+ const filePath = path9.join(agentsDir, file);
5550
+ const source = fs9.readFileSync(filePath, "utf-8");
5504
5551
  const name = await extractDefinitionName(source);
5505
5552
  if (name) {
5506
5553
  agents.push(name);
@@ -5516,7 +5563,7 @@ var PackageDiscoveryService = class {
5516
5563
  constructor(config) {
5517
5564
  this.config = {
5518
5565
  rootDir: config.rootDir,
5519
- packedDir: config.packedDir ?? path8.join(config.rootDir, "agents", "packed"),
5566
+ packedDir: config.packedDir ?? path9.join(config.rootDir, "agents", "packed"),
5520
5567
  scanNpm: config.scanNpm ?? true,
5521
5568
  scanLocal: config.scanLocal ?? true
5522
5569
  };
@@ -5549,19 +5596,19 @@ var PackageDiscoveryService = class {
5549
5596
  */
5550
5597
  async discoverNpmPackages() {
5551
5598
  const packages = [];
5552
- const nodeModulesDir = path8.join(this.config.rootDir, "node_modules");
5553
- if (!fs8.existsSync(nodeModulesDir)) {
5599
+ const nodeModulesDir = path9.join(this.config.rootDir, "node_modules");
5600
+ if (!fs9.existsSync(nodeModulesDir)) {
5554
5601
  return packages;
5555
5602
  }
5556
5603
  const rootEntries = await this.scanDirectory(nodeModulesDir);
5557
5604
  for (const entry of rootEntries) {
5558
5605
  if (entry.startsWith(".")) continue;
5559
5606
  if (entry.startsWith("@")) {
5560
- const scopeDir = path8.join(nodeModulesDir, entry);
5607
+ const scopeDir = path9.join(nodeModulesDir, entry);
5561
5608
  const scopeEntries = await this.scanDirectory(scopeDir);
5562
5609
  for (const scopedPkg of scopeEntries) {
5563
5610
  if (scopedPkg.startsWith(".")) continue;
5564
- const pkgDir = path8.join(scopeDir, scopedPkg);
5611
+ const pkgDir = path9.join(scopeDir, scopedPkg);
5565
5612
  const fullName = `${entry}/${scopedPkg}`;
5566
5613
  const pkg = await this.checkNpmPackage(pkgDir, fullName);
5567
5614
  if (pkg) {
@@ -5569,7 +5616,7 @@ var PackageDiscoveryService = class {
5569
5616
  }
5570
5617
  }
5571
5618
  } else {
5572
- const pkgDir = path8.join(nodeModulesDir, entry);
5619
+ const pkgDir = path9.join(nodeModulesDir, entry);
5573
5620
  const pkg = await this.checkNpmPackage(pkgDir, entry);
5574
5621
  if (pkg) {
5575
5622
  packages.push(pkg);
@@ -5585,12 +5632,12 @@ var PackageDiscoveryService = class {
5585
5632
  * which must contain `entryAgents` array.
5586
5633
  */
5587
5634
  async checkNpmPackage(pkgDir, pkgName) {
5588
- const pkgJsonPath = path8.join(pkgDir, "package.json");
5589
- if (!fs8.existsSync(pkgJsonPath)) {
5635
+ const pkgJsonPath = path9.join(pkgDir, "package.json");
5636
+ if (!fs9.existsSync(pkgJsonPath)) {
5590
5637
  return null;
5591
5638
  }
5592
5639
  try {
5593
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
5640
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
5594
5641
  const isStandardAgent = (
5595
5642
  // Has "standardagent" keyword
5596
5643
  pkgJson.keywords?.includes("standardagent") || // Has "standardagent-*" prefix
@@ -5627,21 +5674,21 @@ var PackageDiscoveryService = class {
5627
5674
  */
5628
5675
  async discoverLocalPackages() {
5629
5676
  const packages = [];
5630
- if (!fs8.existsSync(this.config.packedDir)) {
5677
+ if (!fs9.existsSync(this.config.packedDir)) {
5631
5678
  return packages;
5632
5679
  }
5633
5680
  const entries = await this.scanDirectory(this.config.packedDir);
5634
5681
  for (const entry of entries) {
5635
5682
  if (entry.startsWith(".")) continue;
5636
- const pkgDir = path8.join(this.config.packedDir, entry);
5637
- const stat = fs8.statSync(pkgDir);
5683
+ const pkgDir = path9.join(this.config.packedDir, entry);
5684
+ const stat = fs9.statSync(pkgDir);
5638
5685
  if (!stat.isDirectory()) continue;
5639
5686
  if (entry.startsWith("@")) {
5640
5687
  const scopeEntries = await this.scanDirectory(pkgDir);
5641
5688
  for (const scopedPkg of scopeEntries) {
5642
5689
  if (scopedPkg.startsWith(".")) continue;
5643
- const scopedPkgDir = path8.join(pkgDir, scopedPkg);
5644
- const scopedStat = fs8.statSync(scopedPkgDir);
5690
+ const scopedPkgDir = path9.join(pkgDir, scopedPkg);
5691
+ const scopedStat = fs9.statSync(scopedPkgDir);
5645
5692
  if (!scopedStat.isDirectory()) continue;
5646
5693
  const fullName = `${entry}/${scopedPkg}`;
5647
5694
  const pkg = await this.checkLocalPackage(scopedPkgDir, fullName);
@@ -5664,12 +5711,12 @@ var PackageDiscoveryService = class {
5664
5711
  * Detection is based on the `standardagent` field in package.json.
5665
5712
  */
5666
5713
  async checkLocalPackage(pkgDir, dirName) {
5667
- const pkgJsonPath = path8.join(pkgDir, "package.json");
5668
- if (!fs8.existsSync(pkgJsonPath)) {
5714
+ const pkgJsonPath = path9.join(pkgDir, "package.json");
5715
+ if (!fs9.existsSync(pkgJsonPath)) {
5669
5716
  return null;
5670
5717
  }
5671
5718
  try {
5672
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
5719
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
5673
5720
  if (!pkgJson.standardagent?.entryAgents) {
5674
5721
  return null;
5675
5722
  }
@@ -5694,10 +5741,10 @@ var PackageDiscoveryService = class {
5694
5741
  * Scan a directory and return entry names.
5695
5742
  */
5696
5743
  async scanDirectory(dir) {
5697
- if (!fs8.existsSync(dir)) {
5744
+ if (!fs9.existsSync(dir)) {
5698
5745
  return [];
5699
5746
  }
5700
- const entries = fs8.readdirSync(dir);
5747
+ const entries = fs9.readdirSync(dir);
5701
5748
  return entries;
5702
5749
  }
5703
5750
  /**
@@ -5790,29 +5837,29 @@ var UnpackingService = class {
5790
5837
  }
5791
5838
  analysis.version = pkg.version;
5792
5839
  analysis.source = pkg.source;
5793
- const indexPath = path8.join(pkg.path, "dist", "index.js");
5794
- if (!fs8.existsSync(indexPath)) {
5840
+ const indexPath = path9.join(pkg.path, "dist", "index.js");
5841
+ if (!fs9.existsSync(indexPath)) {
5795
5842
  analysis.errors.push(`Package index not found: ${indexPath}`);
5796
5843
  return analysis;
5797
5844
  }
5798
- const indexContent = fs8.readFileSync(indexPath, "utf-8");
5845
+ const indexContent = fs9.readFileSync(indexPath, "utf-8");
5799
5846
  const registryItems = await this.parseIndexExports(indexContent);
5800
5847
  const availableItems = /* @__PURE__ */ new Map();
5801
5848
  for (const item of registryItems) {
5802
5849
  availableItems.set(`${item.type}:${item.name}`, item);
5803
5850
  }
5804
- const agentsDir = path8.join(rootDir, "agents");
5851
+ const agentsDir = path9.join(rootDir, "agents");
5805
5852
  const itemsWithRelations = [];
5806
5853
  for (const item of registryItems) {
5807
- const targetPath = path8.join(agentsDir, TYPE_TO_TARGET_DIR[item.type], `${item.name}.ts`);
5808
- const sourcePath = path8.join(pkg.path, "dist", TYPE_TO_DIR[item.type], `${item.name}.js`);
5854
+ const targetPath = resolvePathWithin(agentsDir, TYPE_TO_TARGET_DIR[item.type], `${item.name}.ts`);
5855
+ const sourcePath = resolvePathWithin(pkg.path, "dist", TYPE_TO_DIR[item.type], `${item.name}.js`);
5809
5856
  const existsGlobally = this.fileExists(targetPath);
5810
- const sourceExists = fs8.existsSync(sourcePath);
5857
+ const sourceExists = fs9.existsSync(sourcePath);
5811
5858
  if (!sourceExists) {
5812
5859
  analysis.warnings.push(`Source file not found for ${item.type} "${item.name}": ${sourcePath}`);
5813
5860
  continue;
5814
5861
  }
5815
- const bundledCode = fs8.readFileSync(sourcePath, "utf-8");
5862
+ const bundledCode = fs9.readFileSync(sourcePath, "utf-8");
5816
5863
  const children = await this.discoverRelationships(item.type, item.name, bundledCode, availableItems);
5817
5864
  itemsWithRelations.push({
5818
5865
  name: item.name,
@@ -5822,10 +5869,10 @@ var UnpackingService = class {
5822
5869
  action: existsGlobally ? "skip" : "generate"
5823
5870
  });
5824
5871
  for (const child of children) {
5825
- const childTargetPath = path8.join(agentsDir, TYPE_TO_TARGET_DIR[child.type], `${child.name}.ts`);
5826
- const childSourcePath = path8.join(pkg.path, "dist", TYPE_TO_DIR[child.type], `${child.name}.js`);
5872
+ const childTargetPath = resolvePathWithin(agentsDir, TYPE_TO_TARGET_DIR[child.type], `${child.name}.ts`);
5873
+ const childSourcePath = resolvePathWithin(pkg.path, "dist", TYPE_TO_DIR[child.type], `${child.name}.js`);
5827
5874
  const childExists = this.fileExists(childTargetPath);
5828
- const childSourceExists = fs8.existsSync(childSourcePath);
5875
+ const childSourceExists = fs9.existsSync(childSourcePath);
5829
5876
  if (!childSourceExists) {
5830
5877
  continue;
5831
5878
  }
@@ -5928,8 +5975,8 @@ var UnpackingService = class {
5928
5975
  return result;
5929
5976
  }
5930
5977
  const itemsToProcess = this.applySelections(analysis.items, itemSelections);
5931
- const pkgJsonPath = path8.join(pkg.path, "package.json");
5932
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
5978
+ const pkgJsonPath = path9.join(pkg.path, "package.json");
5979
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
5933
5980
  let author = "";
5934
5981
  if (typeof pkgJson.author === "string") {
5935
5982
  author = pkgJson.author;
@@ -5954,18 +6001,19 @@ var UnpackingService = class {
5954
6001
  continue;
5955
6002
  }
5956
6003
  try {
5957
- const sourcePath = path8.join(pkg.path, "dist", TYPE_TO_DIR[item.type], `${item.name}.js`);
5958
- const bundledCode = fs8.readFileSync(sourcePath, "utf-8");
6004
+ const sourcePath = resolvePathWithin(pkg.path, "dist", TYPE_TO_DIR[item.type], `${item.name}.js`);
6005
+ const targetPath = resolvePathWithin(path9.join(rootDir, "agents"), path9.relative(path9.join(rootDir, "agents"), item.targetPath));
6006
+ const bundledCode = fs9.readFileSync(sourcePath, "utf-8");
5959
6007
  let tsCode = await transformBundledJs(bundledCode);
5960
6008
  if (item.type === "agent") {
5961
6009
  tsCode = await injectAgentMetadata(tsCode, agentMetadata);
5962
6010
  }
5963
- const dir = path8.dirname(item.targetPath);
5964
- if (!fs8.existsSync(dir)) {
5965
- fs8.mkdirSync(dir, { recursive: true });
6011
+ const dir = path9.dirname(targetPath);
6012
+ if (!fs9.existsSync(dir)) {
6013
+ fs9.mkdirSync(dir, { recursive: true });
5966
6014
  }
5967
- fs8.writeFileSync(item.targetPath, tsCode);
5968
- result.filesGenerated.push(item.targetPath);
6015
+ fs9.writeFileSync(targetPath, tsCode);
6016
+ result.filesGenerated.push(targetPath);
5969
6017
  } catch (error) {
5970
6018
  result.warnings.push(
5971
6019
  `Failed to generate ${item.type} "${item.name}": ${error instanceof Error ? error.message : String(error)}`
@@ -5974,7 +6022,12 @@ var UnpackingService = class {
5974
6022
  }
5975
6023
  if (deletePackage && pkg.source === "local") {
5976
6024
  try {
5977
- this.deleteDirectory(pkg.path);
6025
+ const localPackedRoot = path9.join(rootDir, "agents", "packed");
6026
+ const safePackagePath = resolvePathWithin(
6027
+ localPackedRoot,
6028
+ path9.relative(localPackedRoot, pkg.path)
6029
+ );
6030
+ this.deleteDirectory(safePackagePath);
5978
6031
  result.packageDeleted = true;
5979
6032
  } catch (error) {
5980
6033
  result.warnings.push(
@@ -6053,14 +6106,14 @@ var UnpackingService = class {
6053
6106
  */
6054
6107
  async resolvePackage(pkgIdentifier, rootDir) {
6055
6108
  if (pkgIdentifier.startsWith("/") || pkgIdentifier.startsWith("./")) {
6056
- const absolutePath = path8.isAbsolute(pkgIdentifier) ? pkgIdentifier : path8.join(rootDir, pkgIdentifier);
6057
- const pkgJsonPath2 = path8.join(absolutePath, "package.json");
6058
- if (fs8.existsSync(pkgJsonPath2)) {
6109
+ const absolutePath = path9.isAbsolute(pkgIdentifier) ? pkgIdentifier : path9.join(rootDir, pkgIdentifier);
6110
+ const pkgJsonPath2 = path9.join(absolutePath, "package.json");
6111
+ if (fs9.existsSync(pkgJsonPath2)) {
6059
6112
  try {
6060
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath2, "utf-8"));
6113
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath2, "utf-8"));
6061
6114
  if (pkgJson.standardagent?.entryAgents) {
6062
6115
  return {
6063
- packageId: pkgJson.name || path8.basename(absolutePath),
6116
+ packageId: pkgJson.name || path9.basename(absolutePath),
6064
6117
  version: pkgJson.version || "0.0.0",
6065
6118
  source: "local",
6066
6119
  path: absolutePath,
@@ -6072,11 +6125,12 @@ var UnpackingService = class {
6072
6125
  }
6073
6126
  return null;
6074
6127
  }
6075
- const packedDir = path8.join(rootDir, "agents", "packed", pkgIdentifier);
6076
- const pkgJsonPath = path8.join(packedDir, "package.json");
6077
- if (fs8.existsSync(pkgJsonPath)) {
6128
+ const safeIdentifier = assertSafePackageIdentifier(pkgIdentifier);
6129
+ const packedDir = resolvePathWithin(path9.join(rootDir, "agents", "packed"), safeIdentifier);
6130
+ const pkgJsonPath = path9.join(packedDir, "package.json");
6131
+ if (fs9.existsSync(pkgJsonPath)) {
6078
6132
  try {
6079
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
6133
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
6080
6134
  if (pkgJson.standardagent?.entryAgents) {
6081
6135
  return {
6082
6136
  packageId: pkgJson.name || pkgIdentifier,
@@ -6117,18 +6171,18 @@ var UnpackingService = class {
6117
6171
  * Check if a file exists.
6118
6172
  */
6119
6173
  fileExists(filePath) {
6120
- if (fs8.existsSync(filePath)) {
6174
+ if (fs9.existsSync(filePath)) {
6121
6175
  return true;
6122
6176
  }
6123
6177
  const withoutExt = filePath.replace(/\.(ts|js)$/, "");
6124
- return fs8.existsSync(`${withoutExt}.ts`) || fs8.existsSync(`${withoutExt}.js`);
6178
+ return fs9.existsSync(`${withoutExt}.ts`) || fs9.existsSync(`${withoutExt}.js`);
6125
6179
  }
6126
6180
  /**
6127
6181
  * Recursively delete a directory.
6128
6182
  */
6129
6183
  deleteDirectory(dirPath) {
6130
- if (fs8.existsSync(dirPath)) {
6131
- fs8.rmSync(dirPath, { recursive: true, force: true });
6184
+ if (fs9.existsSync(dirPath)) {
6185
+ fs9.rmSync(dirPath, { recursive: true, force: true });
6132
6186
  }
6133
6187
  }
6134
6188
  /**
@@ -6204,8 +6258,8 @@ var NpmPublishService = class {
6204
6258
  error: "Registry URL must use HTTPS"
6205
6259
  };
6206
6260
  }
6207
- const pkgJsonPath = path8.join(packageDir, "package.json");
6208
- if (!fs8.existsSync(pkgJsonPath)) {
6261
+ const pkgJsonPath = path9.join(packageDir, "package.json");
6262
+ if (!fs9.existsSync(pkgJsonPath)) {
6209
6263
  return {
6210
6264
  success: false,
6211
6265
  output: "",
@@ -6215,7 +6269,7 @@ var NpmPublishService = class {
6215
6269
  let packageName;
6216
6270
  let version;
6217
6271
  try {
6218
- const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
6272
+ const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
6219
6273
  packageName = pkgJson.name;
6220
6274
  version = pkgJson.version;
6221
6275
  } catch (e) {
@@ -6225,13 +6279,13 @@ var NpmPublishService = class {
6225
6279
  error: `Failed to read package.json: ${e instanceof Error ? e.message : String(e)}`
6226
6280
  };
6227
6281
  }
6228
- const npmrcPath = path8.join(packageDir, ".npmrc");
6282
+ const npmrcPath = path9.join(packageDir, ".npmrc");
6229
6283
  const registryHost = new URL(registry).host;
6230
6284
  const npmrcContent = `//${registryHost}/:_authToken=${token}
6231
6285
  registry=${registry}
6232
6286
  `;
6233
6287
  try {
6234
- fs8.writeFileSync(npmrcPath, npmrcContent, { mode: 384 });
6288
+ fs9.writeFileSync(npmrcPath, npmrcContent, { mode: 384 });
6235
6289
  const args = ["publish"];
6236
6290
  if (dryRun) {
6237
6291
  args.push("--dry-run");
@@ -6263,8 +6317,8 @@ registry=${registry}
6263
6317
  };
6264
6318
  } finally {
6265
6319
  try {
6266
- if (fs8.existsSync(npmrcPath)) {
6267
- fs8.unlinkSync(npmrcPath);
6320
+ if (fs9.existsSync(npmrcPath)) {
6321
+ fs9.unlinkSync(npmrcPath);
6268
6322
  }
6269
6323
  } catch {
6270
6324
  }
@@ -6357,7 +6411,7 @@ async function handlePackingApiRequest(context) {
6357
6411
  const body = await parseRequestBody(req);
6358
6412
  const packingService = new PackingService();
6359
6413
  const rootDir = process.cwd();
6360
- const outputDir = path8__default.join(rootDir, "agents", "packed");
6414
+ const outputDir = path9__default.join(rootDir, "agents", "packed");
6361
6415
  const result = await packingService.pack({
6362
6416
  agentName,
6363
6417
  rootDir,
@@ -6410,8 +6464,8 @@ async function handlePackingApiRequest(context) {
6410
6464
  res.end(JSON.stringify({ error: "Cannot delete npm packages. Use npm uninstall instead." }));
6411
6465
  return true;
6412
6466
  }
6413
- const fs18 = await import('fs');
6414
- fs18.rmSync(pkg.path, { recursive: true, force: true });
6467
+ const fs19 = await import('fs');
6468
+ fs19.rmSync(pkg.path, { recursive: true, force: true });
6415
6469
  await reloadAllAgentModules(context);
6416
6470
  res.statusCode = 200;
6417
6471
  res.setHeader("Content-Type", "application/json");
@@ -6439,8 +6493,8 @@ async function handlePackingApiRequest(context) {
6439
6493
  return true;
6440
6494
  }
6441
6495
  const { spawn } = await import('child_process');
6442
- const parentDir = path8__default.dirname(pkg.path);
6443
- const dirName = path8__default.basename(pkg.path);
6496
+ const parentDir = path9__default.dirname(pkg.path);
6497
+ const dirName = path9__default.basename(pkg.path);
6444
6498
  res.setHeader("Content-Type", "application/gzip");
6445
6499
  res.setHeader("Content-Disposition", `attachment; filename="${packageId}.tar.gz"`);
6446
6500
  const tar = spawn("tar", ["-czf", "-", "-C", parentDir, dirName]);
@@ -6494,18 +6548,19 @@ async function handlePackingApiRequest(context) {
6494
6548
  if (packPublishMatch && method === "POST") {
6495
6549
  try {
6496
6550
  const packageId = decodeURIComponent(packPublishMatch[1]);
6551
+ assertSafePackageIdentifier(packageId);
6497
6552
  const body = await parseRequestBody(req);
6498
6553
  const rootDir = process.cwd();
6499
- const packedDir = path8__default.join(rootDir, "agents", "packed");
6500
- let packageDir = path8__default.join(packedDir, packageId);
6501
- if (!fs8__default.existsSync(packageDir)) {
6502
- if (!fs8__default.existsSync(packedDir)) {
6554
+ const packedDir = path9__default.join(rootDir, "agents", "packed");
6555
+ let packageDir = resolvePathWithin(packedDir, packageId);
6556
+ if (!fs9__default.existsSync(packageDir)) {
6557
+ if (!fs9__default.existsSync(packedDir)) {
6503
6558
  res.statusCode = 400;
6504
6559
  res.setHeader("Content-Type", "application/json");
6505
6560
  res.end(JSON.stringify({ error: "No packed packages found. Pack the agent first." }));
6506
6561
  return true;
6507
6562
  }
6508
- const dirs = fs8__default.readdirSync(packedDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
6563
+ const dirs = fs9__default.readdirSync(packedDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
6509
6564
  const matchingDir = dirs.find(
6510
6565
  (d) => d === packageId || d === `standardagent-${packageId}` || d === `standardagent-${packageId.replace(/_/g, "-")}`
6511
6566
  );
@@ -6517,14 +6572,14 @@ async function handlePackingApiRequest(context) {
6517
6572
  }));
6518
6573
  return true;
6519
6574
  }
6520
- packageDir = path8__default.join(packedDir, matchingDir);
6575
+ packageDir = resolvePathWithin(packedDir, matchingDir);
6521
6576
  }
6522
6577
  let token = body.token || process.env.NPM_TOKEN;
6523
6578
  let tokenSource = body.token ? "provided" : "environment";
6524
6579
  if (!token) {
6525
- const devVarsPath = path8__default.join(rootDir, ".dev.vars");
6526
- if (fs8__default.existsSync(devVarsPath)) {
6527
- const devVars = fs8__default.readFileSync(devVarsPath, "utf-8");
6580
+ const devVarsPath = path9__default.join(rootDir, ".dev.vars");
6581
+ if (fs9__default.existsSync(devVarsPath)) {
6582
+ const devVars = fs9__default.readFileSync(devVarsPath, "utf-8");
6528
6583
  const match = devVars.match(/^NPM_TOKEN=(.+)$/m);
6529
6584
  if (match) {
6530
6585
  token = match[1].trim();
@@ -6635,27 +6690,67 @@ async function handlePackingApiRequest(context) {
6635
6690
  return false;
6636
6691
  }
6637
6692
 
6693
+ // src/routing/access-policy.ts
6694
+ function isProviderIconRoute(routePath) {
6695
+ return /^\/api\/providers\/[^/]+\/icon$/.test(routePath);
6696
+ }
6697
+ function isHostedInstance(env) {
6698
+ const value = env?.STANDARD_AGENTS_HOSTED;
6699
+ if (typeof value === "string") {
6700
+ const normalized = value.trim().toLowerCase();
6701
+ return normalized !== "" && normalized !== "0" && normalized !== "false";
6702
+ }
6703
+ return Boolean(value);
6704
+ }
6705
+ function isTrustedLocalDevelopmentRequest(request, env) {
6706
+ if (isHostedInstance(env)) return false;
6707
+ let hostname;
6708
+ try {
6709
+ hostname = new URL(request.url).hostname.toLowerCase();
6710
+ } catch {
6711
+ return false;
6712
+ }
6713
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local");
6714
+ }
6715
+ function isAdminOnlyApiRoute(routePath, method = "GET") {
6716
+ if (routePath === "/api/skills" || routePath.startsWith("/api/skills/")) return true;
6717
+ if (routePath === "/api/pack" || routePath.startsWith("/api/pack/")) return true;
6718
+ if (routePath === "/api/unpack" || routePath.startsWith("/api/unpack/")) return true;
6719
+ if (routePath === "/api/prompts" || routePath.startsWith("/api/prompts/")) return true;
6720
+ if (routePath === "/api/tools" || routePath.startsWith("/api/tools/")) return true;
6721
+ if (routePath === "/api/models" || routePath.startsWith("/api/models/")) return true;
6722
+ if (routePath === "/api/providers") return true;
6723
+ if (routePath.startsWith("/api/providers/")) {
6724
+ return !isProviderIconRoute(routePath);
6725
+ }
6726
+ if (routePath.startsWith("/api/agents/")) {
6727
+ return !/^\/api\/agents\/[^/]+\/tenvs$/.test(routePath);
6728
+ }
6729
+ if (routePath === "/api/agents" && method.toUpperCase() !== "GET") return true;
6730
+ return false;
6731
+ }
6732
+
6638
6733
  // src/plugin/dev-middleware.ts
6639
6734
  function readRawRequestBody(req) {
6640
- return new Promise((resolve2, reject) => {
6735
+ return new Promise((resolve3, reject) => {
6641
6736
  const chunks = [];
6642
6737
  req.on("data", (chunk) => {
6643
6738
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
6644
6739
  });
6645
6740
  req.on("end", () => {
6646
- resolve2(chunks.length > 0 ? Buffer.concat(chunks) : void 0);
6741
+ resolve3(chunks.length > 0 ? Buffer.concat(chunks) : void 0);
6647
6742
  });
6648
6743
  req.on("error", reject);
6649
6744
  });
6650
6745
  }
6651
6746
  function resolveContainedFile(baseDir, requestPath) {
6652
- const resolvedBase = path8__default.resolve(baseDir);
6653
- const resolved = path8__default.resolve(resolvedBase, `.${path8__default.sep}${requestPath.replace(/^\/+/, "")}`);
6654
- if (resolved !== resolvedBase && !resolved.startsWith(resolvedBase + path8__default.sep)) {
6747
+ const resolvedBase = path9__default.resolve(baseDir);
6748
+ const resolved = path9__default.resolve(resolvedBase, `.${path9__default.sep}${requestPath.replace(/^\/+/, "")}`);
6749
+ if (resolved !== resolvedBase && !resolved.startsWith(resolvedBase + path9__default.sep)) {
6655
6750
  return null;
6656
6751
  }
6657
6752
  try {
6658
- return fs8__default.existsSync(resolved) && fs8__default.statSync(resolved).isFile() ? resolved : null;
6753
+ return fs9__default.existsSync(resolved) && fs9__default.statSync(resolved).isFile() ? resolved : null;
6659
6754
  } catch {
6660
6755
  return null;
6661
6756
  }
@@ -6705,6 +6800,21 @@ function createDevMiddleware(server, context) {
6705
6800
  return;
6706
6801
  }
6707
6802
  }
6803
+ const routePath = new URL(pathWithoutMount, "http://localhost").pathname;
6804
+ let trustedLocalHost = false;
6805
+ try {
6806
+ trustedLocalHost = isTrustedLocalDevelopmentRequest(
6807
+ new Request(`http://${req.headers.host || "invalid.remote"}${routePath}`),
6808
+ {}
6809
+ );
6810
+ } catch {
6811
+ }
6812
+ if (isAdminOnlyApiRoute(routePath, method) && !trustedLocalHost) {
6813
+ res.statusCode = 403;
6814
+ res.setHeader("Content-Type", "application/json");
6815
+ res.end(JSON.stringify({ error: "Authoring APIs are available only from local development hosts" }));
6816
+ return;
6817
+ }
6708
6818
  if (await handleConfigApiRequest({
6709
6819
  req,
6710
6820
  res,
@@ -6794,19 +6904,19 @@ function createDevMiddleware(server, context) {
6794
6904
  const clientPath = pathWithoutMount.startsWith("/agents/") ? pathWithoutMount.slice("/agents".length) || "/" : pathWithoutMount;
6795
6905
  const isStaticAsset = clientPath.startsWith("/assets/") || clientPath.startsWith("/vendor.js") || clientPath.startsWith("/vue.js") || clientPath.startsWith("/monaco.js") || clientPath.startsWith("/index.js") || clientPath.startsWith("/index.css") || clientPath.match(/\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$/);
6796
6906
  {
6797
- const currentDir = path8__default.dirname(fileURLToPath(import.meta.url));
6907
+ const currentDir = path9__default.dirname(fileURLToPath(import.meta.url));
6798
6908
  const isInDist = currentDir.endsWith("dist");
6799
- const clientDir = path8__default.resolve(
6909
+ const clientDir = path9__default.resolve(
6800
6910
  currentDir,
6801
6911
  isInDist ? "./client" : "../dist/client"
6802
6912
  );
6803
6913
  let filePath;
6804
6914
  if (isStaticAsset) {
6805
6915
  const cleanUrl = clientPath.split("?")[0];
6806
- filePath = path8__default.join(clientDir, cleanUrl);
6807
- if (!fs8__default.existsSync(filePath)) {
6916
+ filePath = path9__default.join(clientDir, cleanUrl);
6917
+ if (!fs9__default.existsSync(filePath)) {
6808
6918
  const projectPublicFile = resolveContainedFile(
6809
- path8__default.resolve(server.config.root, "public"),
6919
+ path9__default.resolve(server.config.root, "public"),
6810
6920
  cleanUrl
6811
6921
  );
6812
6922
  if (projectPublicFile) {
@@ -6814,12 +6924,12 @@ function createDevMiddleware(server, context) {
6814
6924
  }
6815
6925
  }
6816
6926
  } else {
6817
- filePath = path8__default.join(clientDir, "index.html");
6927
+ filePath = path9__default.join(clientDir, "index.html");
6818
6928
  }
6819
6929
  try {
6820
- if (fs8__default.existsSync(filePath)) {
6821
- let content = fs8__default.readFileSync(filePath);
6822
- const ext = path8__default.extname(filePath).toLowerCase();
6930
+ if (fs9__default.existsSync(filePath)) {
6931
+ let content = fs9__default.readFileSync(filePath);
6932
+ const ext = path9__default.extname(filePath).toLowerCase();
6823
6933
  if (ext === ".html") {
6824
6934
  content = Buffer.from(
6825
6935
  injectUiConfigIntoHtml(content.toString())
@@ -6859,7 +6969,7 @@ async function loadBuilderVirtualModule(context) {
6859
6969
  const effects = await scanEffectsDirectory(effectsDir);
6860
6970
  const toAbsolutePath = (relativePath) => {
6861
6971
  if (relativePath.startsWith("./")) {
6862
- return path8__default.resolve(process.cwd(), relativePath).replace(/\\/g, "/");
6972
+ return path9__default.resolve(process.cwd(), relativePath).replace(/\\/g, "/");
6863
6973
  }
6864
6974
  return relativePath;
6865
6975
  };
@@ -7131,7 +7241,7 @@ async function loadRegistryVirtualModule(context) {
7131
7241
  const effects = await scanEffectsDirectory(effectsDir);
7132
7242
  const toAbsolutePath = (relativePath) => {
7133
7243
  if (relativePath.startsWith("./")) {
7134
- return path8__default.resolve(process.cwd(), relativePath).replace(/\\/g, "/");
7244
+ return path9__default.resolve(process.cwd(), relativePath).replace(/\\/g, "/");
7135
7245
  }
7136
7246
  return relativePath;
7137
7247
  };
@@ -7159,23 +7269,23 @@ async function loadRegistryVirtualModule(context) {
7159
7269
  const absPath = toAbsolutePath(importPath);
7160
7270
  return ` "${name}": async () => (await import("${absPath}")).default,`;
7161
7271
  }).join("\n");
7162
- const packedDir = path8__default.resolve(process.cwd(), "agents/packed");
7272
+ const packedDir = path9__default.resolve(process.cwd(), "agents/packed");
7163
7273
  const packedPackages = [];
7164
- if (fs8__default.existsSync(packedDir)) {
7274
+ if (fs9__default.existsSync(packedDir)) {
7165
7275
  console.log(`[vite-plugin-agent] Scanning packed directory: ${packedDir}`);
7166
7276
  const packageDirs = discoverPackedPackageDirectories(packedDir);
7167
7277
  console.log(`[vite-plugin-agent] Found package dirs: ${packageDirs.join(", ")}`);
7168
7278
  for (const pkgPath of packageDirs) {
7169
- const pkgJsonPath = path8__default.join(pkgPath, "package.json");
7170
- if (fs8__default.existsSync(pkgJsonPath)) {
7279
+ const pkgJsonPath = path9__default.join(pkgPath, "package.json");
7280
+ if (fs9__default.existsSync(pkgJsonPath)) {
7171
7281
  try {
7172
- const pkgJson = JSON.parse(fs8__default.readFileSync(pkgJsonPath, "utf-8"));
7282
+ const pkgJson = JSON.parse(fs9__default.readFileSync(pkgJsonPath, "utf-8"));
7173
7283
  console.log(`[vite-plugin-agent] Loaded ${pkgPath} package.json, standardagent:`, pkgJson.standardagent);
7174
7284
  if (!pkgJson.standardagent) {
7175
7285
  continue;
7176
7286
  }
7177
7287
  const mainEntry = pkgJson.main || "./dist/index.js";
7178
- const outputDir = path8__default.dirname(mainEntry).replace(/^\.\//, "");
7288
+ const outputDir = path9__default.dirname(mainEntry).replace(/^\.\//, "");
7179
7289
  const pkg = {
7180
7290
  packageId: pkgJson.name,
7181
7291
  version: pkgJson.version,
@@ -7293,7 +7403,7 @@ export function getVisibleToolNames() {
7293
7403
  async function loadRoutesVirtualModule(context) {
7294
7404
  const { threadApiDir, rou3Code, hmr } = context;
7295
7405
  const threadRoutes = scanApiDirectory(threadApiDir);
7296
- const toAbsolutePath = (inputPath) => path8__default.resolve(process.cwd(), inputPath).replace(/\\/g, "/");
7406
+ const toAbsolutePath = (inputPath) => path9__default.resolve(process.cwd(), inputPath).replace(/\\/g, "/");
7297
7407
  const threadRouteCode = threadRoutes.map(({ method, route, importPath }) => {
7298
7408
  const apiRoute = `/api/threads/:threadId${route}`;
7299
7409
  return ` addRoute(
@@ -7304,20 +7414,20 @@ async function loadRoutesVirtualModule(context) {
7304
7414
  );`;
7305
7415
  }).join("\n");
7306
7416
  const packedThreadRoutes = [];
7307
- const packedDir = path8__default.resolve(process.cwd(), "agents/packed");
7417
+ const packedDir = path9__default.resolve(process.cwd(), "agents/packed");
7308
7418
  const packedPackageDirs = discoverPackedPackageDirectories(packedDir);
7309
7419
  for (const packagePath of packedPackageDirs) {
7310
- const packageJsonPath = path8__default.join(packagePath, "package.json");
7311
- if (!fs8__default.existsSync(packageJsonPath)) {
7420
+ const packageJsonPath = path9__default.join(packagePath, "package.json");
7421
+ if (!fs9__default.existsSync(packageJsonPath)) {
7312
7422
  continue;
7313
7423
  }
7314
7424
  try {
7315
- const packageJson = JSON.parse(fs8__default.readFileSync(packageJsonPath, "utf-8"));
7425
+ const packageJson = JSON.parse(fs9__default.readFileSync(packageJsonPath, "utf-8"));
7316
7426
  if (!packageJson.standardagent) {
7317
7427
  continue;
7318
7428
  }
7319
7429
  const mainEntry = packageJson.main || "./dist/index.js";
7320
- const outputDir = path8__default.dirname(mainEntry).replace(/^\.\//, "");
7430
+ const outputDir = path9__default.dirname(mainEntry).replace(/^\.\//, "");
7321
7431
  const threadEndpoints = scanPackedThreadEndpoints(packagePath, outputDir);
7322
7432
  for (const endpoint of threadEndpoints) {
7323
7433
  const apiRoute = `/api/threads/:threadId${endpoint.route}`;
@@ -7351,97 +7461,16 @@ import { providers, providerNames, providerFactories } from "virtual:@standardag
7351
7461
  import { prompts, promptNames } from "virtual:@standardagents-prompts";
7352
7462
  import { agents, agentNames } from "virtual:@standardagents-agents";
7353
7463
  import { registry } from "virtual:@standardagents-registry";
7354
- import { requireAuth, createThreadEndpointHandler } from "@standardagents/builder/runtime";
7464
+ import {
7465
+ requireAuth,
7466
+ createThreadEndpointHandler,
7467
+ canAccessThread,
7468
+ isHostedInstance,
7469
+ isPublicApiRoute,
7470
+ isAdminOnlyApiRoute,
7471
+ } from "@standardagents/builder/runtime";
7355
7472
  import { isThreadEndpoint } from "@standardagents/spec";
7356
7473
 
7357
- // Routes that don't require authentication
7358
- const PUBLIC_ROUTES = [
7359
- '/api/auth/bootstrap',
7360
- '/api/auth/login',
7361
- '/api/auth/config',
7362
- '/api/auth/platform-cleanup',
7363
- '/api/auth/platform-replica',
7364
- '/api/auth/sa/start', // Login with Standard Agents (OAuth) \u2014 unauthenticated entry
7365
- '/api/auth/sa/callback', // OAuth callback (sets the session cookie)
7366
- '/api/config',
7367
- '/api/auth/oauth/github',
7368
- '/api/auth/oauth/google',
7369
- '/api/auth/oauth/github/callback',
7370
- '/api/auth/oauth/google/callback',
7371
- '/api/platform-auth/bootstrap',
7372
- '/api/platform-auth/login',
7373
- '/api/platform-auth/logout',
7374
- '/api/platform-auth/me',
7375
- '/api/hooks' // Hook metadata is safe to expose publicly
7376
- ];
7377
-
7378
- // True when the platform deployed this instance (injects STANDARD_AGENTS_HOSTED).
7379
- // Hosted instances are internet-reachable and multi-tenant, so the thread data
7380
- // API and event/stream WebSockets must NOT be anonymously public the way they
7381
- // are in single-user local dev \u2014 they require a session (admin) or API key (SDK).
7382
- function isHostedInstance(env) {
7383
- const value = env && env.STANDARD_AGENTS_HOSTED;
7384
- if (typeof value === 'string') {
7385
- const trimmed = value.trim().toLowerCase();
7386
- return trimmed !== '' && trimmed !== '0' && trimmed !== 'false';
7387
- }
7388
- return Boolean(value);
7389
- }
7390
-
7391
- // Check if a route is public (no auth required)
7392
- function isPublicRoute(routePath, hosted) {
7393
- // Exact match for auth routes
7394
- if (PUBLIC_ROUTES.includes(routePath)) {
7395
- return true;
7396
- }
7397
-
7398
- // Thread routes (REST + message/log stream WebSockets) are public in local
7399
- // single-user dev, but on a hosted deployment they require auth \u2014 requireAuth
7400
- // accepts the admin's session (cookie or token) or the SDK's API key, so this
7401
- // only blocks anonymous access to another tenant's threads/messages/files.
7402
- if (!hosted && (routePath.startsWith('/api/threads/') || routePath === '/api/threads')) {
7403
- return true;
7404
- }
7405
-
7406
- // Device-code CLI login: start/poll are public by design (possession of the
7407
- // one-time code is the secret) and the approve page must reach its controller
7408
- // even when anonymous so it can redirect the browser through the platform
7409
- // login (the controller enforces session auth itself).
7410
- if (routePath === '/api/auth/device/start' || routePath.startsWith('/api/auth/device/')) {
7411
- return true;
7412
- }
7413
-
7414
- // Provider icon routes are public (used by <img src>)
7415
- if (routePath.startsWith('/api/providers/') && routePath.includes('/icon')) {
7416
- return true;
7417
- }
7418
-
7419
- // Platform proxy routes handle their own auth in local dev only.
7420
- if (hosted && (routePath.startsWith('/api/platform/') || routePath === '/api/platform')) {
7421
- return false;
7422
- }
7423
- if (routePath.startsWith('/api/platform/') || routePath === '/api/platform') {
7424
- return true;
7425
- }
7426
-
7427
- // Platform session proxy and auth bridge are local-dev helpers only.
7428
- if (hosted && (routePath.startsWith('/api/platform-session/') || routePath === '/api/platform-session')) {
7429
- return false;
7430
- }
7431
- if (routePath.startsWith('/api/platform-session/') || routePath === '/api/platform-session') {
7432
- return true;
7433
- }
7434
-
7435
- if (hosted && (routePath.startsWith('/api/platform-auth/') || routePath === '/api/platform-auth')) {
7436
- return false;
7437
- }
7438
- if (routePath.startsWith('/api/platform-auth/') || routePath === '/api/platform-auth') {
7439
- return true;
7440
- }
7441
-
7442
- return false;
7443
- }
7444
-
7445
7474
  function platformEndpoint(env) {
7446
7475
  const configured =
7447
7476
  env && (env.PLATFORM_ENDPOINT || env.STANDARD_AGENTS_PLATFORM_URL || env.PLATFORM_URL || env.STANDARD_AGENTS_PUBLIC_URL);
@@ -7584,7 +7613,7 @@ ${packedThreadRouteCode}
7584
7613
 
7585
7614
  if (routeMatch) {
7586
7615
  // Check if authentication is required for this route
7587
- const publicRoute = isPublicRoute(routePath, isHostedInstance(env));
7616
+ const publicRoute = isPublicApiRoute(routePath, request, env);
7588
7617
  const isApiRoute = routePath.startsWith('/api/');
7589
7618
 
7590
7619
  let authContext = null;
@@ -7600,6 +7629,10 @@ ${packedThreadRouteCode}
7600
7629
 
7601
7630
  authContext = authResult;
7602
7631
 
7632
+ if (isAdminOnlyApiRoute(routePath, request.method) && authContext.user.role !== 'admin') {
7633
+ return addCorsHeaders(Response.json({ error: 'Forbidden: Admin access required' }, { status: 403 }));
7634
+ }
7635
+
7603
7636
  if (routePath.startsWith('/api/threads/')) {
7604
7637
  // Packed and user thread endpoints reserve threadId for the owning
7605
7638
  // thread while nested endpoint parameters may also be named id.
@@ -7613,7 +7646,7 @@ ${packedThreadRouteCode}
7613
7646
  if (!thread) {
7614
7647
  return addCorsHeaders(Response.json({ error: \`Thread not found: \${threadId}\` }, { status: 404 }));
7615
7648
  }
7616
- if (authContext.user.role !== 'admin' && (thread.user_id === null || thread.user_id !== authContext.user.id)) {
7649
+ if (!canAccessThread(authContext, thread)) {
7617
7650
  return addCorsHeaders(Response.json({ error: "Forbidden: You don't have access to this thread" }, { status: 403 }));
7618
7651
  }
7619
7652
  }
@@ -7789,13 +7822,13 @@ ${hooksCode}
7789
7822
  };`;
7790
7823
  }
7791
7824
  if (id === RESOLVED_VIRTUAL_CONFIG_ID) {
7792
- const relativeToolsDir = path8__default.relative(process.cwd(), toolsDir).replace(/\\/g, "/");
7793
- const relativeHooksDir = path8__default.relative(process.cwd(), hooksDir).replace(/\\/g, "/");
7794
- const relativeApiDir = path8__default.relative(process.cwd(), threadApiDir).replace(/\\/g, "/");
7795
- const relativeModelsDir = path8__default.relative(process.cwd(), modelsDir).replace(/\\/g, "/");
7796
- const relativeProvidersDir = path8__default.relative(process.cwd(), providersDir).replace(/\\/g, "/");
7797
- const relativePromptsDir = path8__default.relative(process.cwd(), promptsDir).replace(/\\/g, "/");
7798
- const relativeAgentsDir = path8__default.relative(process.cwd(), agentsDir).replace(/\\/g, "/");
7825
+ const relativeToolsDir = path9__default.relative(process.cwd(), toolsDir).replace(/\\/g, "/");
7826
+ const relativeHooksDir = path9__default.relative(process.cwd(), hooksDir).replace(/\\/g, "/");
7827
+ const relativeApiDir = path9__default.relative(process.cwd(), threadApiDir).replace(/\\/g, "/");
7828
+ const relativeModelsDir = path9__default.relative(process.cwd(), modelsDir).replace(/\\/g, "/");
7829
+ const relativeProvidersDir = path9__default.relative(process.cwd(), providersDir).replace(/\\/g, "/");
7830
+ const relativePromptsDir = path9__default.relative(process.cwd(), promptsDir).replace(/\\/g, "/");
7831
+ const relativeAgentsDir = path9__default.relative(process.cwd(), agentsDir).replace(/\\/g, "/");
7799
7832
  return `// Virtual agent config module
7800
7833
  export const config = {
7801
7834
  toolsDir: "${relativeToolsDir}",
@@ -8012,14 +8045,14 @@ var packingDeps = [
8012
8045
  "typescript"
8013
8046
  ];
8014
8047
  function createPluginViteConfig(pluginModuleUrl) {
8015
- const currentDir = path8__default.dirname(fileURLToPath(pluginModuleUrl));
8048
+ const currentDir = path9__default.dirname(fileURLToPath(pluginModuleUrl));
8016
8049
  const isInDist = currentDir.endsWith("dist");
8017
- const builderClientDir = path8__default.resolve(
8050
+ const builderClientDir = path9__default.resolve(
8018
8051
  currentDir,
8019
8052
  isInDist ? "./client" : "../dist/client"
8020
8053
  );
8021
8054
  return {
8022
- publicDir: fs8__default.existsSync(builderClientDir) ? builderClientDir : void 0,
8055
+ publicDir: fs9__default.existsSync(builderClientDir) ? builderClientDir : void 0,
8023
8056
  build: {
8024
8057
  rollupOptions: {
8025
8058
  external: [...packingDeps]
@@ -8166,24 +8199,24 @@ function applyPluginEnvironmentConfig(config) {
8166
8199
 
8167
8200
  // src/plugin.ts
8168
8201
  function agentbuilder(options = {}) {
8169
- const toolsDir = options.toolsDir ? path8__default.resolve(process.cwd(), options.toolsDir) : path8__default.resolve(process.cwd(), "agents/tools");
8170
- const hooksDir = options.hooksDir ? path8__default.resolve(process.cwd(), options.hooksDir) : path8__default.resolve(process.cwd(), "agents/hooks");
8171
- const threadApiDir = options.apiDir ? path8__default.resolve(process.cwd(), options.apiDir) : path8__default.resolve(process.cwd(), "agents/api");
8172
- const modelsDir = options.modelsDir ? path8__default.resolve(process.cwd(), options.modelsDir) : path8__default.resolve(process.cwd(), "agents/models");
8173
- const providersDir = options.providersDir ? path8__default.resolve(process.cwd(), options.providersDir) : path8__default.resolve(process.cwd(), "agents/providers");
8174
- const promptsDir = options.promptsDir ? path8__default.resolve(process.cwd(), options.promptsDir) : path8__default.resolve(process.cwd(), "agents/prompts");
8175
- const agentsDir = options.agentsDir ? path8__default.resolve(process.cwd(), options.agentsDir) : path8__default.resolve(process.cwd(), "agents/agents");
8176
- const effectsDir = options.effectsDir ? path8__default.resolve(process.cwd(), options.effectsDir) : path8__default.resolve(process.cwd(), "agents/effects");
8177
- const usersDir = options.usersDir ? path8__default.resolve(process.cwd(), options.usersDir) : path8__default.resolve(process.cwd(), "agents/users");
8178
- const outputDir = path8__default.resolve(process.cwd(), ".agents");
8179
- const generatedWorkerEntry = path8__default.join(outputDir, "worker.ts");
8202
+ const toolsDir = options.toolsDir ? path9__default.resolve(process.cwd(), options.toolsDir) : path9__default.resolve(process.cwd(), "agents/tools");
8203
+ const hooksDir = options.hooksDir ? path9__default.resolve(process.cwd(), options.hooksDir) : path9__default.resolve(process.cwd(), "agents/hooks");
8204
+ const threadApiDir = options.apiDir ? path9__default.resolve(process.cwd(), options.apiDir) : path9__default.resolve(process.cwd(), "agents/api");
8205
+ const modelsDir = options.modelsDir ? path9__default.resolve(process.cwd(), options.modelsDir) : path9__default.resolve(process.cwd(), "agents/models");
8206
+ const providersDir = options.providersDir ? path9__default.resolve(process.cwd(), options.providersDir) : path9__default.resolve(process.cwd(), "agents/providers");
8207
+ const promptsDir = options.promptsDir ? path9__default.resolve(process.cwd(), options.promptsDir) : path9__default.resolve(process.cwd(), "agents/prompts");
8208
+ const agentsDir = options.agentsDir ? path9__default.resolve(process.cwd(), options.agentsDir) : path9__default.resolve(process.cwd(), "agents/agents");
8209
+ const effectsDir = options.effectsDir ? path9__default.resolve(process.cwd(), options.effectsDir) : path9__default.resolve(process.cwd(), "agents/effects");
8210
+ const usersDir = options.usersDir ? path9__default.resolve(process.cwd(), options.usersDir) : path9__default.resolve(process.cwd(), "agents/users");
8211
+ const outputDir = path9__default.resolve(process.cwd(), ".agents");
8212
+ const generatedWorkerEntry = path9__default.join(outputDir, "worker.ts");
8180
8213
  const isProviderPackageInstalled = (packageName) => {
8181
8214
  let dir = process.cwd();
8182
8215
  for (; ; ) {
8183
- if (fs8__default.existsSync(path8__default.join(dir, "node_modules", packageName, "package.json"))) {
8216
+ if (fs9__default.existsSync(path9__default.join(dir, "node_modules", packageName, "package.json"))) {
8184
8217
  return true;
8185
8218
  }
8186
- const parent = path8__default.dirname(dir);
8219
+ const parent = path9__default.dirname(dir);
8187
8220
  if (parent === dir) return false;
8188
8221
  dir = parent;
8189
8222
  }
@@ -8218,17 +8251,17 @@ export default {
8218
8251
 
8219
8252
  export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog, DurableUserHub };
8220
8253
  `;
8221
- fs8__default.mkdirSync(outputDir, { recursive: true });
8222
- if (!fs8__default.existsSync(generatedWorkerEntry) || fs8__default.readFileSync(generatedWorkerEntry, "utf-8") !== content) {
8223
- fs8__default.writeFileSync(generatedWorkerEntry, content);
8254
+ fs9__default.mkdirSync(outputDir, { recursive: true });
8255
+ if (!fs9__default.existsSync(generatedWorkerEntry) || fs9__default.readFileSync(generatedWorkerEntry, "utf-8") !== content) {
8256
+ fs9__default.writeFileSync(generatedWorkerEntry, content);
8224
8257
  }
8225
8258
  }
8226
8259
  const __filename = fileURLToPath(import.meta.url);
8227
- const __dirname = path8__default.dirname(__filename);
8228
- const rou3Path = path8__default.join(__dirname, "../dist/rou3.js");
8260
+ const __dirname = path9__default.dirname(__filename);
8261
+ const rou3Path = path9__default.join(__dirname, "../dist/rou3.js");
8229
8262
  let rou3Code = "";
8230
8263
  try {
8231
- rou3Code = fs8__default.readFileSync(rou3Path, "utf-8").replace(/^export \{[^}]+\};?\s*$/gm, "").replace(/\/\/# sourceMappingURL=.+$/gm, "").trim();
8264
+ rou3Code = fs9__default.readFileSync(rou3Path, "utf-8").replace(/^export \{[^}]+\};?\s*$/gm, "").replace(/\/\/# sourceMappingURL=.+$/gm, "").trim();
8232
8265
  } catch (err) {
8233
8266
  console.warn("[vite-plugin-agent] Could not read rou3.js for inlining:", err);
8234
8267
  }
@@ -8271,7 +8304,7 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8271
8304
  sourceDirs,
8272
8305
  regenerateTypes
8273
8306
  };
8274
- const workerEntry = path8__default.relative(process.cwd(), generatedWorkerEntry).split(path8__default.sep).join("/");
8307
+ const workerEntry = path9__default.relative(process.cwd(), generatedWorkerEntry).split(path9__default.sep).join("/");
8275
8308
  const corePlugin = {
8276
8309
  name: "vite-plugin-agent",
8277
8310
  enforce: "pre",
@@ -8346,28 +8379,28 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8346
8379
  },
8347
8380
  writeBundle(options2, bundle) {
8348
8381
  const outDir = options2.dir || "dist";
8349
- const mountDir = path8__default.join(outDir, "../client");
8350
- const currentDir = path8__default.dirname(fileURLToPath(import.meta.url));
8382
+ const mountDir = path9__default.join(outDir, "../client");
8383
+ const currentDir = path9__default.dirname(fileURLToPath(import.meta.url));
8351
8384
  const isInDist = currentDir.endsWith("dist");
8352
- const clientDir = path8__default.resolve(
8385
+ const clientDir = path9__default.resolve(
8353
8386
  currentDir,
8354
8387
  isInDist ? "./client" : "../dist/client"
8355
8388
  );
8356
- if (!fs8__default.existsSync(clientDir)) {
8389
+ if (!fs9__default.existsSync(clientDir)) {
8357
8390
  console.warn(`[agentbuilder] Client directory not found at ${clientDir}`);
8358
8391
  return;
8359
8392
  }
8360
- fs8__default.mkdirSync(mountDir, { recursive: true });
8393
+ fs9__default.mkdirSync(mountDir, { recursive: true });
8361
8394
  function copyRecursive(src, dest) {
8362
- const entries = fs8__default.readdirSync(src, { withFileTypes: true });
8395
+ const entries = fs9__default.readdirSync(src, { withFileTypes: true });
8363
8396
  for (const entry of entries) {
8364
- const srcPath = path8__default.join(src, entry.name);
8365
- const destPath = path8__default.join(dest, entry.name);
8397
+ const srcPath = path9__default.join(src, entry.name);
8398
+ const destPath = path9__default.join(dest, entry.name);
8366
8399
  if (entry.isDirectory()) {
8367
- fs8__default.mkdirSync(destPath, { recursive: true });
8400
+ fs9__default.mkdirSync(destPath, { recursive: true });
8368
8401
  copyRecursive(srcPath, destPath);
8369
8402
  } else {
8370
- let content = fs8__default.readFileSync(srcPath);
8403
+ let content = fs9__default.readFileSync(srcPath);
8371
8404
  if (entry.name === "index.html") {
8372
8405
  const configScript = `<script>window.__AGENTBUILDER_CONFIG__ = {};</script>`;
8373
8406
  let htmlContent = content.toString();
@@ -8375,27 +8408,27 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8375
8408
  htmlContent = htmlContent.replace("</head>", `${configScript}</head>`);
8376
8409
  content = Buffer.from(htmlContent);
8377
8410
  }
8378
- fs8__default.writeFileSync(destPath, content);
8411
+ fs9__default.writeFileSync(destPath, content);
8379
8412
  }
8380
8413
  }
8381
8414
  }
8382
8415
  copyRecursive(clientDir, mountDir);
8383
- const projectPublicDir = path8__default.resolve(process.cwd(), "public");
8384
- if (fs8__default.existsSync(projectPublicDir)) {
8416
+ const projectPublicDir = path9__default.resolve(process.cwd(), "public");
8417
+ if (fs9__default.existsSync(projectPublicDir)) {
8385
8418
  let copyPublicRecursive2 = function(src, dest) {
8386
- const entries = fs8__default.readdirSync(src, { withFileTypes: true });
8419
+ const entries = fs9__default.readdirSync(src, { withFileTypes: true });
8387
8420
  for (const entry of entries) {
8388
- const srcPath = path8__default.join(src, entry.name);
8389
- const destPath = path8__default.join(dest, entry.name);
8421
+ const srcPath = path9__default.join(src, entry.name);
8422
+ const destPath = path9__default.join(dest, entry.name);
8390
8423
  if (entry.isDirectory()) {
8391
- fs8__default.mkdirSync(destPath, { recursive: true });
8424
+ fs9__default.mkdirSync(destPath, { recursive: true });
8392
8425
  copyPublicRecursive2(srcPath, destPath);
8393
- } else if (fs8__default.existsSync(destPath)) {
8426
+ } else if (fs9__default.existsSync(destPath)) {
8394
8427
  console.warn(
8395
8428
  `[agentbuilder] Skipping public/ file that collides with a built UI asset: ${destPath}`
8396
8429
  );
8397
8430
  } else {
8398
- fs8__default.copyFileSync(srcPath, destPath);
8431
+ fs9__default.copyFileSync(srcPath, destPath);
8399
8432
  }
8400
8433
  }
8401
8434
  };