@starlein/paperclip-plugin-company-wizard 0.6.2 → 0.6.3

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.
package/dist/worker.js CHANGED
@@ -29352,7 +29352,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
29352
29352
  var manifest = {
29353
29353
  id: "starlein.paperclip-plugin-company-wizard",
29354
29354
  apiVersion: 1,
29355
- version: "0.6.2",
29355
+ version: "0.6.3",
29356
29356
  displayName: "Company Wizard",
29357
29357
  description: "AI-powered wizard to bootstrap agent companies from composable templates",
29358
29358
  author: "Sascha Pietrowski <sp@speednetwork.de>",
@@ -29388,7 +29388,7 @@ var manifest = {
29388
29388
  },
29389
29389
  templatesPath: {
29390
29390
  type: "string",
29391
- description: "Optional operator-managed templates directory. Defaults to templates bundled with this plugin release. Local files are never overwritten by refresh."
29391
+ description: "Optional existing template root containing roles/, modules/, and presets/. Overrides the GitHub URL. Leave empty to use bundled release templates or a custom GitHub source. Refresh never populates or overwrites this directory."
29392
29392
  },
29393
29393
  templatesRepoUrl: {
29394
29394
  type: "string",
@@ -29399,7 +29399,7 @@ var manifest = {
29399
29399
  type: "string",
29400
29400
  enum: ["anthropic", "openai"],
29401
29401
  default: "anthropic",
29402
- description: "AI provider used for company generation. Anthropic uses Claude Opus 5 at max effort; OpenAI uses GPT-5.6 Sol at high reasoning effort."
29402
+ description: "AI provider used for company generation. Anthropic uses Claude Opus 5 at max effort; OpenAI uses GPT-6-Astra at high reasoning effort."
29403
29403
  },
29404
29404
  anthropicApiKey: {
29405
29405
  // Paperclip's secret picker submits an EnvSecretRefBinding object,
@@ -31673,17 +31673,13 @@ function isDockerLayout() {
31673
31673
  async function ensureTemplatesDir(cfg) {
31674
31674
  const repoUrl = cfg.templatesRepoUrl || DEFAULT_TEMPLATES_REPO_URL;
31675
31675
  if (cfg.templatesPath) {
31676
- if (fs2.existsSync(cfg.templatesPath)) return cfg.templatesPath;
31677
- throw new Error(`Configured templatesPath does not exist: ${cfg.templatesPath}`);
31676
+ return validateTemplatesDir(cfg.templatesPath, "Configured templatesPath");
31678
31677
  }
31679
31678
  if (!cfg.templatesRepoUrl || cfg.templatesRepoUrl === DEFAULT_TEMPLATES_REPO_URL) {
31680
- if (fs2.existsSync(BUNDLED_TEMPLATES_DIR)) return BUNDLED_TEMPLATES_DIR;
31681
- throw new Error(
31682
- "Bundled templates are missing. Reinstall Company Wizard or configure templatesPath."
31683
- );
31679
+ return validateTemplatesDir(BUNDLED_TEMPLATES_DIR, "Bundled templates");
31684
31680
  }
31685
31681
  const cacheDir = resolveTemplatesCacheDir(cfg);
31686
- if (fs2.existsSync(cacheDir)) return cacheDir;
31682
+ if (fs2.existsSync(cacheDir)) return validateTemplatesDir(cacheDir, "Cached templates");
31687
31683
  return refreshTemplatesCache(cfg);
31688
31684
  }
31689
31685
  function resolveTemplatesCacheDir(cfg) {
@@ -31695,14 +31691,12 @@ function resolveTemplatesCacheDir(cfg) {
31695
31691
  }
31696
31692
  function refreshTemplatesCache(cfg, log) {
31697
31693
  if (cfg.templatesPath) {
31698
- if (!fs2.existsSync(cfg.templatesPath))
31699
- throw new Error(`Configured templatesPath does not exist: ${cfg.templatesPath}`);
31694
+ validateTemplatesDir(cfg.templatesPath, "Configured templatesPath");
31700
31695
  log?.("Using operator-managed templatesPath; no files overwritten.");
31701
31696
  return cfg.templatesPath;
31702
31697
  }
31703
31698
  if (!cfg.templatesRepoUrl || cfg.templatesRepoUrl === DEFAULT_TEMPLATES_REPO_URL) {
31704
- if (!fs2.existsSync(BUNDLED_TEMPLATES_DIR))
31705
- throw new Error("Bundled templates are missing. Reinstall Company Wizard.");
31699
+ validateTemplatesDir(BUNDLED_TEMPLATES_DIR, "Bundled templates");
31706
31700
  log?.(`Using bundled Company Wizard ${CURRENT_PLUGIN_VERSION} templates.`);
31707
31701
  return BUNDLED_TEMPLATES_DIR;
31708
31702
  }
@@ -31713,6 +31707,9 @@ function refreshTemplatesCache(cfg, log) {
31713
31707
  const backupDir = `${stagingDir}-previous`;
31714
31708
  try {
31715
31709
  downloadTemplatesFromGithub(stagingDir, repoUrl);
31710
+ validateTemplatesDir(stagingDir, "Downloaded templates");
31711
+ const { loadErrors } = loadTemplates(stagingDir);
31712
+ if (loadErrors.length > 0) throw new Error(loadErrors.join("\n"));
31716
31713
  if (fs2.existsSync(targetDir)) fs2.renameSync(targetDir, backupDir);
31717
31714
  try {
31718
31715
  fs2.renameSync(stagingDir, targetDir);
@@ -31728,7 +31725,7 @@ function refreshTemplatesCache(cfg, log) {
31728
31725
  return targetDir;
31729
31726
  }
31730
31727
  var ANTHROPIC_AI_MODEL = "claude-opus-5";
31731
- var OPENAI_AI_MODEL = "gpt-5.6-sol";
31728
+ var OPENAI_AI_MODEL = "gpt-6-astra";
31732
31729
  function isLikelyAnthropicApiKey(value) {
31733
31730
  return value.startsWith("sk-ant-");
31734
31731
  }
@@ -31878,7 +31875,11 @@ function loadJsonFiles(dir, filename) {
31878
31875
  const fp = path2.join(fullDir, filename);
31879
31876
  if (!fs2.existsSync(fp)) continue;
31880
31877
  try {
31881
- items.push(JSON.parse(fs2.readFileSync(fp, "utf-8")));
31878
+ const item = JSON.parse(fs2.readFileSync(fp, "utf-8"));
31879
+ if (!item || typeof item !== "object" || Array.isArray(item) || typeof item.name !== "string" || !item.name.trim()) {
31880
+ throw new Error("Template metadata must be an object with a non-empty name");
31881
+ }
31882
+ items.push(item);
31882
31883
  } catch (err) {
31883
31884
  errors.push(`Failed to parse ${fp}: ${err instanceof Error ? err.message : String(err)}`);
31884
31885
  }
@@ -31909,6 +31910,23 @@ function loadTemplates(templatesDir) {
31909
31910
  loadErrors: [...presetLoad.errors, ...moduleLoad.errors, ...roleLoad.errors]
31910
31911
  };
31911
31912
  }
31913
+ function validateTemplatesDir(dir, source) {
31914
+ try {
31915
+ if (!fs2.existsSync(dir)) throw new Error("directory does not exist");
31916
+ if (!fs2.statSync(dir).isDirectory()) throw new Error("path is not a directory");
31917
+ const templates = loadTemplates(dir);
31918
+ if (!templates.roles.some((role) => role.name === "ceo" && role._base)) {
31919
+ throw new Error(
31920
+ 'No base CEO template found. Expected roles/ceo/role.meta.json with name "ceo" and base: true.' + (templates.loadErrors.length ? ` ${templates.loadErrors.join(" ")}` : "")
31921
+ );
31922
+ }
31923
+ return dir;
31924
+ } catch (err) {
31925
+ const detail = err instanceof Error ? err.message : String(err);
31926
+ const guidance = source === "Configured templatesPath" ? "Point templatesPath to the template root (containing roles/, modules/, presets/), or clear templatesPath to use bundled templates / the configured GitHub source. templatesPath overrides templatesRepoUrl; refresh never populates or overwrites local files." : "Reinstall Company Wizard for bundled templates, or refresh the configured custom GitHub source.";
31927
+ throw new Error(`${source} "${dir}": ${detail} ${guidance}`);
31928
+ }
31929
+ }
31912
31930
  function resolvePaperclipCredentials(cfg) {
31913
31931
  return {
31914
31932
  url: cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100",
@@ -32369,14 +32387,18 @@ ${moduleNames.length > 0 ? moduleNames.map((mod) => `- ${mod}`).join("\n") : "-
32369
32387
  var plugin = definePlugin({
32370
32388
  async setup(ctx) {
32371
32389
  ctx.data.register("templates", async () => {
32372
- const cfg = await ctx.config.get() ?? {};
32373
- const templates = loadTemplates(await ensureTemplatesDir(cfg));
32374
- if (templates.loadErrors.length > 0) {
32375
- for (const err of templates.loadErrors) {
32376
- ctx.logger.info(`\u26A0 Template load warning: ${err}`);
32390
+ try {
32391
+ const cfg = await ctx.config.get() ?? {};
32392
+ const templates = loadTemplates(await ensureTemplatesDir(cfg));
32393
+ for (const warning of templates.loadErrors) {
32394
+ ctx.logger.info(`\u26A0 Template load warning: ${warning}`);
32377
32395
  }
32396
+ return templates;
32397
+ } catch (err) {
32398
+ const error61 = err instanceof Error ? err.message : String(err);
32399
+ ctx.logger.info(`Template load failed: ${error61}`);
32400
+ return { presets: [], modules: [], roles: [], loadErrors: [error61], error: error61 };
32378
32401
  }
32379
- return templates;
32380
32402
  });
32381
32403
  ctx.actions.register("refresh-templates", async () => {
32382
32404
  try {
@@ -33551,6 +33573,8 @@ var plugin = definePlugin({
33551
33573
  async onValidateConfig(config2) {
33552
33574
  const paperclipUrl = config2.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
33553
33575
  try {
33576
+ const templates = loadTemplates(await ensureTemplatesDir(config2));
33577
+ if (templates.loadErrors.length > 0) return { ok: false, errors: templates.loadErrors };
33554
33578
  const client = new PaperclipClient(paperclipUrl, {
33555
33579
  email: config2.paperclipEmail || "",
33556
33580
  password: config2.paperclipPassword || ""