syntaur 0.55.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dashboard/dist/assets/{_basePickBy-DmVNJO8J.js → _basePickBy-BboQhTYn.js} +1 -1
  3. package/dashboard/dist/assets/{_baseUniq-BtWQDHxm.js → _baseUniq-C6ARYdEJ.js} +1 -1
  4. package/dashboard/dist/assets/{arc-BDZ8fFmA.js → arc-D76wUYJ-.js} +1 -1
  5. package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-DmE3bMva.js → architectureDiagram-2XIMDMQ5-eoW8_dbN.js} +1 -1
  6. package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-BUpzLbve.js → blockDiagram-WCTKOSBZ--XxaNbBK.js} +1 -1
  7. package/dashboard/dist/assets/{c4Diagram-IC4MRINW-5lB7kxgt.js → c4Diagram-IC4MRINW-D2B-NJq6.js} +1 -1
  8. package/dashboard/dist/assets/channel-BPykMjmL.js +1 -0
  9. package/dashboard/dist/assets/{chunk-4BX2VUAB-DdRqNqOP.js → chunk-4BX2VUAB-CY34rkdT.js} +1 -1
  10. package/dashboard/dist/assets/{chunk-55IACEB6-D_qI2OxO.js → chunk-55IACEB6-CLXE1Ejn.js} +1 -1
  11. package/dashboard/dist/assets/{chunk-FMBD7UC4-BMtQHZt3.js → chunk-FMBD7UC4-D00VtmIk.js} +1 -1
  12. package/dashboard/dist/assets/{chunk-JSJVCQXG-CeCGSMMb.js → chunk-JSJVCQXG-_EITJTaI.js} +1 -1
  13. package/dashboard/dist/assets/{chunk-KX2RTZJC-Biv2a0MB.js → chunk-KX2RTZJC-DrqZI_kX.js} +1 -1
  14. package/dashboard/dist/assets/{chunk-NQ4KR5QH-CbkEQT8f.js → chunk-NQ4KR5QH-DnYhUmZY.js} +1 -1
  15. package/dashboard/dist/assets/{chunk-QZHKN3VN-BU54yyBK.js → chunk-QZHKN3VN-CqCcFoFI.js} +1 -1
  16. package/dashboard/dist/assets/{chunk-WL4C6EOR-ypzKdtzY.js → chunk-WL4C6EOR-Bwx5h46l.js} +1 -1
  17. package/dashboard/dist/assets/classDiagram-VBA2DB6C-z8L393gl.js +1 -0
  18. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-z8L393gl.js +1 -0
  19. package/dashboard/dist/assets/clone--rMJOGpf.js +1 -0
  20. package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-Cfexs6Pq.js → cose-bilkent-S5V4N54A-QUZroYuH.js} +1 -1
  21. package/dashboard/dist/assets/{dagre-KLK3FWXG-BjdeaK5Z.js → dagre-KLK3FWXG-D8hYiZ7i.js} +1 -1
  22. package/dashboard/dist/assets/{diagram-E7M64L7V-BVZRb5bD.js → diagram-E7M64L7V-Cl_n980P.js} +1 -1
  23. package/dashboard/dist/assets/{diagram-IFDJBPK2-6fnO4hw1.js → diagram-IFDJBPK2-01DdmzmS.js} +1 -1
  24. package/dashboard/dist/assets/{diagram-P4PSJMXO-DX_fbvo0.js → diagram-P4PSJMXO-GcqkAPB2.js} +1 -1
  25. package/dashboard/dist/assets/{erDiagram-INFDFZHY-Dc-Ult_U.js → erDiagram-INFDFZHY-DQnXbhhn.js} +1 -1
  26. package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-nrIBfe3g.js → flowDiagram-PKNHOUZH-DSmXtiZK.js} +1 -1
  27. package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-7zt_k1Nl.js → ganttDiagram-A5KZAMGK-BLyt9LDp.js} +1 -1
  28. package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-2yK7iOPo.js → gitGraphDiagram-K3NZZRJ6-FWlr0I_j.js} +1 -1
  29. package/dashboard/dist/assets/{graph-DD0OOYtL.js → graph-Czw8ZNXY.js} +1 -1
  30. package/dashboard/dist/assets/index-EntCfH3I.css +1 -0
  31. package/dashboard/dist/assets/index-zHNBGpC7.js +602 -0
  32. package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-7nottSf8.js → infoDiagram-LFFYTUFH-CygGWMzd.js} +1 -1
  33. package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-DHd9lm-i.js → ishikawaDiagram-PHBUUO56-39XaFufR.js} +1 -1
  34. package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-BS86Ecdy.js → journeyDiagram-4ABVD52K-DCMzi84v.js} +1 -1
  35. package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-B9uccuva.js → kanban-definition-K7BYSVSG-RSNF4GmM.js} +1 -1
  36. package/dashboard/dist/assets/{layout-Bq6MeguZ.js → layout-AOYFASCy.js} +1 -1
  37. package/dashboard/dist/assets/{linear-XkyDYAy6.js → linear-Bf-cRRMe.js} +1 -1
  38. package/dashboard/dist/assets/{mermaid.core-BH9rlHr4.js → mermaid.core-7QJzPWTu.js} +4 -4
  39. package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-Cc-hDkvW.js → mindmap-definition-YRQLILUH-Ck4L1K7y.js} +1 -1
  40. package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-BFIPTP1F.js → pieDiagram-SKSYHLDU-BHEH_9Yh.js} +1 -1
  41. package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-yVL8WrSz.js → quadrantDiagram-337W2JSQ-DScQHhsU.js} +1 -1
  42. package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-DxWjrQut.js → requirementDiagram-Z7DCOOCP-DLmxwUdt.js} +1 -1
  43. package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-BPkz1Yl7.js → sankeyDiagram-WA2Y5GQK-B6OZtKmg.js} +1 -1
  44. package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-DlgeS-S7.js → sequenceDiagram-2WXFIKYE-woFPqQIY.js} +1 -1
  45. package/dashboard/dist/assets/{stateDiagram-RAJIS63D-DBpOK-Ql.js → stateDiagram-RAJIS63D-Db9HV_HG.js} +1 -1
  46. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-DZsj07hg.js +1 -0
  47. package/dashboard/dist/assets/{timeline-definition-YZTLITO2-abDjZ0W-.js → timeline-definition-YZTLITO2-CGVOTXAD.js} +1 -1
  48. package/dashboard/dist/assets/{treemap-KZPCXAKY-bF6AoBlY.js → treemap-KZPCXAKY-CGmqtjaL.js} +1 -1
  49. package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-lUeCE7KT.js → vennDiagram-LZ73GAT5-DAuyqqKn.js} +1 -1
  50. package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-ByECFP6v.js → xychartDiagram-JWTSCODW--uOFgr6-.js} +1 -1
  51. package/dashboard/dist/index.html +2 -2
  52. package/dist/dashboard/server.js +290 -23
  53. package/dist/dashboard/server.js.map +1 -1
  54. package/dist/index.js +290 -23
  55. package/dist/index.js.map +1 -1
  56. package/dist/launch/index.d.ts +25 -0
  57. package/dist/launch/index.js +187 -1
  58. package/dist/launch/index.js.map +1 -1
  59. package/package.json +1 -1
  60. package/platforms/claude-code/.claude-plugin/plugin.json +1 -1
  61. package/platforms/codex/.codex-plugin/plugin.json +1 -1
  62. package/platforms/hermes/plugins/syntaur/__pycache__/__init__.cpython-312.pyc +0 -0
  63. package/platforms/hermes/plugins/syntaur/__pycache__/boundary.cpython-312.pyc +0 -0
  64. package/dashboard/dist/assets/channel-SCYGGwh4.js +0 -1
  65. package/dashboard/dist/assets/classDiagram-VBA2DB6C-DDovN08E.js +0 -1
  66. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-DDovN08E.js +0 -1
  67. package/dashboard/dist/assets/clone-DjHcKoH3.js +0 -1
  68. package/dashboard/dist/assets/index-BKfPPYKw.js +0 -602
  69. package/dashboard/dist/assets/index-C8THdvxD.css +0 -1
  70. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-CS61beS7.js +0 -1
@@ -3378,6 +3378,98 @@ var init_terminal_schema = __esm({
3378
3378
  }
3379
3379
  });
3380
3380
 
3381
+ // src/utils/search-schema.ts
3382
+ function isEntityKind(value) {
3383
+ return typeof value === "string" && ENTITY_KINDS.includes(value);
3384
+ }
3385
+ function isDefaultScope(value) {
3386
+ return value === "all" || isEntityKind(value);
3387
+ }
3388
+ function normalizeSearchConfig(raw2) {
3389
+ if (!raw2 || typeof raw2 !== "object") {
3390
+ return cloneDefaultSearchConfig();
3391
+ }
3392
+ const r = raw2;
3393
+ const defaultScope = isDefaultScope(r["defaultScope"]) ? r["defaultScope"] : DEFAULT_SEARCH_CONFIG.defaultScope;
3394
+ const externalIds = typeof r["externalIds"] === "boolean" ? r["externalIds"] : DEFAULT_SEARCH_CONFIG.externalIds;
3395
+ let aliases;
3396
+ if (r["aliases"] && typeof r["aliases"] === "object") {
3397
+ aliases = {};
3398
+ for (const [key, value] of Object.entries(r["aliases"])) {
3399
+ if (ALIAS_KEY_RE.test(key) && key !== RESERVED_ALIAS && !SEARCH_FIELD_NAMES.includes(key) && isEntityKind(value)) {
3400
+ aliases[key] = value;
3401
+ }
3402
+ }
3403
+ } else {
3404
+ aliases = { ...DEFAULT_SEARCH_CONFIG.aliases };
3405
+ }
3406
+ return { defaultScope, aliases, externalIds };
3407
+ }
3408
+ function validateAliases(aliases) {
3409
+ if (!aliases || typeof aliases !== "object") {
3410
+ return { ok: false, errors: ["aliases must be an object"] };
3411
+ }
3412
+ const errors = [];
3413
+ for (const [key, value] of Object.entries(aliases)) {
3414
+ if (!ALIAS_KEY_RE.test(key)) {
3415
+ errors.push(`alias key "${key}" must be lowercase and match [a-z][a-z0-9]*`);
3416
+ }
3417
+ if (key === RESERVED_ALIAS) {
3418
+ errors.push(`alias key "${RESERVED_ALIAS}" is reserved (the "search everything" escape)`);
3419
+ }
3420
+ if (SEARCH_FIELD_NAMES.includes(key)) {
3421
+ errors.push(`alias key "${key}" collides with the reserved field name "${key}"`);
3422
+ }
3423
+ if (!isEntityKind(value)) {
3424
+ errors.push(`alias "${key}" must map to one of: ${ENTITY_KINDS.join(", ")}`);
3425
+ }
3426
+ }
3427
+ return errors.length === 0 ? { ok: true } : { ok: false, errors };
3428
+ }
3429
+ function isValidDefaultScope(value) {
3430
+ return isDefaultScope(value);
3431
+ }
3432
+ function cloneDefaultSearchConfig() {
3433
+ return {
3434
+ defaultScope: DEFAULT_SEARCH_CONFIG.defaultScope,
3435
+ aliases: { ...DEFAULT_SEARCH_CONFIG.aliases },
3436
+ externalIds: DEFAULT_SEARCH_CONFIG.externalIds
3437
+ };
3438
+ }
3439
+ var ENTITY_KINDS, DEFAULT_SEARCH_CONFIG, SEARCH_FIELD_NAMES, RESERVED_ALIAS, ALIAS_KEY_RE;
3440
+ var init_search_schema = __esm({
3441
+ "src/utils/search-schema.ts"() {
3442
+ "use strict";
3443
+ ENTITY_KINDS = [
3444
+ "assignment",
3445
+ "project",
3446
+ "todo",
3447
+ "server",
3448
+ "playbook"
3449
+ ];
3450
+ DEFAULT_SEARCH_CONFIG = {
3451
+ defaultScope: "all",
3452
+ aliases: { a: "assignment", p: "project", t: "todo", s: "server", pb: "playbook" },
3453
+ externalIds: true
3454
+ };
3455
+ SEARCH_FIELD_NAMES = [
3456
+ "kind",
3457
+ "status",
3458
+ "tag",
3459
+ "tags",
3460
+ "assignee",
3461
+ "type",
3462
+ "project",
3463
+ "externalid",
3464
+ "jira",
3465
+ "title",
3466
+ "search"
3467
+ ];
3468
+ RESERVED_ALIAS = "all";
3469
+ ALIAS_KEY_RE = /^[a-z][a-z0-9]*$/;
3470
+ }
3471
+ });
3472
+
3381
3473
  // src/utils/workspace-visibility-schema.ts
3382
3474
  function normalizeHiddenList(input) {
3383
3475
  if (!Array.isArray(input)) return [];
@@ -3418,18 +3510,22 @@ __export(config_exports, {
3418
3510
  buildDefaultStatusConfig: () => buildDefaultStatusConfig,
3419
3511
  deleteAgentsConfig: () => deleteAgentsConfig,
3420
3512
  deleteHotkeyBindingsConfig: () => deleteHotkeyBindingsConfig,
3513
+ deleteSearchConfig: () => deleteSearchConfig,
3421
3514
  deleteStatusConfig: () => deleteStatusConfig,
3422
3515
  deleteTerminalConfig: () => deleteTerminalConfig,
3423
3516
  deleteThemeConfig: () => deleteThemeConfig,
3424
3517
  deleteWorkspaceVisibilityConfig: () => deleteWorkspaceVisibilityConfig,
3425
3518
  getAgents: () => getAgents,
3426
3519
  getAssignmentTypes: () => getAssignmentTypes,
3520
+ getSearchConfig: () => getSearchConfig,
3427
3521
  getTerminal: () => getTerminal,
3428
3522
  normalizeFactDeclarations: () => normalizeFactDeclarations,
3429
3523
  parseAgentCommand: () => parseAgentCommand,
3524
+ parseSearchConfig: () => parseSearchConfig,
3430
3525
  parseStatusConfig: () => parseStatusConfig,
3431
3526
  parseTerminalConfig: () => parseTerminalConfig,
3432
3527
  readConfig: () => readConfig,
3528
+ serializeSearchConfig: () => serializeSearchConfig,
3433
3529
  serializeStatusConfig: () => serializeStatusConfig,
3434
3530
  toTitleCase: () => toTitleCase,
3435
3531
  updateAgentsConfig: () => updateAgentsConfig,
@@ -3443,6 +3539,7 @@ __export(config_exports, {
3443
3539
  validateFactDeclarations: () => validateFactDeclarations,
3444
3540
  writeAgentsConfig: () => writeAgentsConfig,
3445
3541
  writeHotkeyBindingsConfig: () => writeHotkeyBindingsConfig,
3542
+ writeSearchConfig: () => writeSearchConfig,
3446
3543
  writeStatusConfig: () => writeStatusConfig,
3447
3544
  writeTerminalConfig: () => writeTerminalConfig,
3448
3545
  writeThemeConfig: () => writeThemeConfig,
@@ -4250,7 +4347,7 @@ function stripTopLevelBlock(fmBlock, key) {
4250
4347
  if (!blockStart) {
4251
4348
  return fmBlock.replace(/\n+$/, "");
4252
4349
  }
4253
- const startIdx = fmBlock.indexOf(blockStart[0]);
4350
+ const startIdx = blockStart.index ?? 0;
4254
4351
  const before = fmBlock.slice(0, startIdx);
4255
4352
  const after = fmBlock.slice(startIdx + blockStart[0].length);
4256
4353
  const remaining = after.split("\n");
@@ -4676,6 +4773,116 @@ ${cleanedFm}
4676
4773
  ---${afterFrontmatter}`;
4677
4774
  await writeFileForce(configPath, newContent);
4678
4775
  }
4776
+ function parseSearchConfig(content) {
4777
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
4778
+ if (!match) return null;
4779
+ const fmBlock = match[1];
4780
+ const blockStart = fmBlock.match(/^search:\s*$/m);
4781
+ if (!blockStart) return null;
4782
+ const startIdx = (blockStart.index ?? 0) + blockStart[0].length;
4783
+ const lines = fmBlock.slice(startIdx).split("\n");
4784
+ const unquote = (v) => {
4785
+ const t = v.trim();
4786
+ if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'")) {
4787
+ return t.slice(1, -1);
4788
+ }
4789
+ return t;
4790
+ };
4791
+ const raw2 = {};
4792
+ let inAliases = false;
4793
+ for (const line of lines) {
4794
+ if (line.trim() === "") continue;
4795
+ const trimmed = line.trimStart();
4796
+ const indent = line.length - trimmed.length;
4797
+ if (indent === 0) break;
4798
+ if (indent <= 2) {
4799
+ inAliases = false;
4800
+ if (trimmed === "aliases:") {
4801
+ inAliases = true;
4802
+ raw2.aliases = {};
4803
+ continue;
4804
+ }
4805
+ const ci = trimmed.indexOf(":");
4806
+ if (ci <= 0) continue;
4807
+ const key = trimmed.slice(0, ci).trim();
4808
+ const value = unquote(trimmed.slice(ci + 1).trim());
4809
+ if (key === "defaultScope") {
4810
+ raw2.defaultScope = value;
4811
+ } else if (key === "externalIds") {
4812
+ const v = value.toLowerCase();
4813
+ if (v === "true") raw2.externalIds = true;
4814
+ else if (v === "false") raw2.externalIds = false;
4815
+ }
4816
+ } else if (inAliases) {
4817
+ const ci = trimmed.indexOf(":");
4818
+ if (ci <= 0) continue;
4819
+ raw2.aliases ??= {};
4820
+ raw2.aliases[trimmed.slice(0, ci).trim()] = unquote(trimmed.slice(ci + 1).trim());
4821
+ }
4822
+ }
4823
+ return normalizeSearchConfig(raw2);
4824
+ }
4825
+ function serializeSearchConfig(search) {
4826
+ const cfg = normalizeSearchConfig(search);
4827
+ const lines = ["search:"];
4828
+ lines.push(` defaultScope: ${cfg.defaultScope}`);
4829
+ lines.push(" aliases:");
4830
+ for (const [prefix, kind] of Object.entries(cfg.aliases)) {
4831
+ lines.push(` ${prefix}: ${kind}`);
4832
+ }
4833
+ lines.push(` externalIds: ${cfg.externalIds ? "true" : "false"}`);
4834
+ return lines.join("\n");
4835
+ }
4836
+ async function writeSearchConfig(search) {
4837
+ const configPath = resolve6(syntaurRoot(), "config.md");
4838
+ const searchBlock = serializeSearchConfig(search);
4839
+ if (!await fileExists(configPath)) {
4840
+ const content = `---
4841
+ version: "2.0"
4842
+ defaultProjectDir: ~/projects
4843
+ ${searchBlock}
4844
+ ---
4845
+ `;
4846
+ await writeFileForce(configPath, content);
4847
+ return;
4848
+ }
4849
+ const existing = await readFile5(configPath, "utf-8");
4850
+ const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
4851
+ if (!fmMatch) {
4852
+ const content = `---
4853
+ version: "2.0"
4854
+ ${searchBlock}
4855
+ ---
4856
+ ${existing}`;
4857
+ await writeFileForce(configPath, content);
4858
+ return;
4859
+ }
4860
+ const fmBlock = fmMatch[2];
4861
+ const afterFrontmatter = existing.slice(fmMatch[0].length);
4862
+ const cleanedFm = stripTopLevelBlock(fmBlock, "search");
4863
+ const newContent = `---
4864
+ ${cleanedFm}
4865
+ ${searchBlock}
4866
+ ---${afterFrontmatter}`;
4867
+ await writeFileForce(configPath, newContent);
4868
+ }
4869
+ async function deleteSearchConfig() {
4870
+ const configPath = resolve6(syntaurRoot(), "config.md");
4871
+ if (!await fileExists(configPath)) return;
4872
+ const existing = await readFile5(configPath, "utf-8");
4873
+ const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
4874
+ if (!fmMatch) return;
4875
+ const fmBlock = fmMatch[2];
4876
+ const afterFrontmatter = existing.slice(fmMatch[0].length);
4877
+ const cleanedFm = stripTopLevelBlock(fmBlock, "search");
4878
+ const newContent = `---
4879
+ ${cleanedFm}
4880
+ ---${afterFrontmatter}`;
4881
+ await writeFileForce(configPath, newContent);
4882
+ }
4883
+ function getSearchConfig(config) {
4884
+ return config.searchConfig ?? DEFAULT_SEARCH_CONFIG;
4885
+ }
4679
4886
  async function updateIntegrationConfig(integrations) {
4680
4887
  const configPath = resolve6(syntaurRoot(), "config.md");
4681
4888
  const nextIntegrations = {
@@ -4847,6 +5054,7 @@ async function readConfig() {
4847
5054
  return null;
4848
5055
  }
4849
5056
  })(),
5057
+ searchConfig: parseSearchConfig(content),
4850
5058
  workspaceVisibility: parseWorkspaceVisibilityConfig(fmBlock)
4851
5059
  };
4852
5060
  }
@@ -4925,6 +5133,7 @@ var init_config2 = __esm({
4925
5133
  init_derive_config();
4926
5134
  init_fact_registry();
4927
5135
  init_terminal_schema();
5136
+ init_search_schema();
4928
5137
  init_workspace_visibility_schema();
4929
5138
  DEFAULT_ASSIGNMENT_TYPES = {
4930
5139
  definitions: [
@@ -4965,6 +5174,7 @@ var init_config2 = __esm({
4965
5174
  theme: null,
4966
5175
  hotkeys: null,
4967
5176
  terminal: null,
5177
+ searchConfig: null,
4968
5178
  workspaceVisibility: {
4969
5179
  hidden: []
4970
5180
  }
@@ -17189,12 +17399,68 @@ function createTerminalConfigRouter() {
17189
17399
  return router;
17190
17400
  }
17191
17401
 
17402
+ // src/dashboard/api-search-config.ts
17403
+ init_config2();
17404
+ init_search_schema();
17405
+ import { Router as Router8 } from "express";
17406
+ function createSearchConfigRouter() {
17407
+ const router = Router8();
17408
+ router.get("/", async (_req, res) => {
17409
+ try {
17410
+ const config = await readConfig();
17411
+ res.json({
17412
+ search: getSearchConfig(config),
17413
+ custom: config.searchConfig !== null
17414
+ });
17415
+ } catch (error) {
17416
+ console.error("Error getting search config:", error);
17417
+ res.status(500).json({ error: "Failed to get search config" });
17418
+ }
17419
+ });
17420
+ router.post("/", async (req2, res) => {
17421
+ try {
17422
+ const body = req2.body ?? {};
17423
+ if (body["defaultScope"] !== void 0 && !isValidDefaultScope(body["defaultScope"])) {
17424
+ res.status(400).json({
17425
+ error: `defaultScope must be one of: all, ${ENTITY_KINDS.join(", ")}`
17426
+ });
17427
+ return;
17428
+ }
17429
+ const aliasCheck = validateAliases(body["aliases"] ?? {});
17430
+ if (!aliasCheck.ok) {
17431
+ res.status(400).json({ error: "Invalid aliases", errors: aliasCheck.errors });
17432
+ return;
17433
+ }
17434
+ const search = normalizeSearchConfig(body);
17435
+ await writeSearchConfig(search);
17436
+ res.json({ search, custom: true });
17437
+ } catch (error) {
17438
+ console.error("Error saving search config:", error);
17439
+ res.status(500).json({ error: "Failed to save search config" });
17440
+ }
17441
+ });
17442
+ router.delete("/", async (_req, res) => {
17443
+ try {
17444
+ await deleteSearchConfig();
17445
+ const config = await readConfig();
17446
+ res.json({
17447
+ search: getSearchConfig(config),
17448
+ custom: config.searchConfig !== null
17449
+ });
17450
+ } catch (error) {
17451
+ console.error("Error resetting search config:", error);
17452
+ res.status(500).json({ error: "Failed to reset search config" });
17453
+ }
17454
+ });
17455
+ return router;
17456
+ }
17457
+
17192
17458
  // src/dashboard/api-workspace-visibility-config.ts
17193
17459
  init_config2();
17194
17460
  init_workspace_visibility_schema();
17195
- import { Router as Router8 } from "express";
17461
+ import { Router as Router9 } from "express";
17196
17462
  function createWorkspaceVisibilityConfigRouter() {
17197
- const router = Router8();
17463
+ const router = Router9();
17198
17464
  router.get("/", async (_req, res) => {
17199
17465
  try {
17200
17466
  const config = await readConfig();
@@ -17240,7 +17506,7 @@ init_fact_registry();
17240
17506
  init_state_machine();
17241
17507
  init_api();
17242
17508
  init_derive();
17243
- import { Router as Router9 } from "express";
17509
+ import { Router as Router10 } from "express";
17244
17510
 
17245
17511
  // src/utils/status-config-resolution.ts
17246
17512
  init_frontmatter();
@@ -17625,7 +17891,7 @@ function mapResolutionErrorToHttp(err, applied) {
17625
17891
  }
17626
17892
  }
17627
17893
  function createStatusConfigRouter(projectsDir, assignmentsDir2) {
17628
- const router = Router9();
17894
+ const router = Router10();
17629
17895
  installRecordsInvalidation(router);
17630
17896
  router.get("/", async (_req, res) => {
17631
17897
  try {
@@ -17945,7 +18211,7 @@ function createStatusConfigRouter(projectsDir, assignmentsDir2) {
17945
18211
  }
17946
18212
 
17947
18213
  // src/dashboard/api-leases.ts
17948
- import { Router as Router10 } from "express";
18214
+ import { Router as Router11 } from "express";
17949
18215
 
17950
18216
  // src/db/leases-db.ts
17951
18217
  init_paths();
@@ -18127,7 +18393,7 @@ function forceReleaseLease(lease_id) {
18127
18393
 
18128
18394
  // src/dashboard/api-leases.ts
18129
18395
  function createLeasesRouter(broadcast) {
18130
- const router = Router10();
18396
+ const router = Router11();
18131
18397
  router.get("/", (_req, res) => {
18132
18398
  try {
18133
18399
  initLeasesDb();
@@ -18183,7 +18449,7 @@ function createLeasesRouter(broadcast) {
18183
18449
 
18184
18450
  // src/dashboard/api-schedules.ts
18185
18451
  init_timestamp();
18186
- import { Router as Router11 } from "express";
18452
+ import { Router as Router12 } from "express";
18187
18453
 
18188
18454
  // src/schedules/store.ts
18189
18455
  init_fs();
@@ -18744,7 +19010,7 @@ function canFire(job, deps) {
18744
19010
  init_agent_sessions();
18745
19011
  init_session_db();
18746
19012
  function createSchedulesRouter(broadcast) {
18747
- const router = Router11();
19013
+ const router = Router12();
18748
19014
  const notify = () => broadcast?.({ type: "schedules-updated", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
18749
19015
  router.get("/", async (_req, res) => {
18750
19016
  try {
@@ -19127,7 +19393,7 @@ async function runTick(deps = {}) {
19127
19393
  }
19128
19394
 
19129
19395
  // src/dashboard/api-usage.ts
19130
- import { Router as Router12 } from "express";
19396
+ import { Router as Router13 } from "express";
19131
19397
 
19132
19398
  // src/db/usage-db.ts
19133
19399
  init_paths();
@@ -19384,7 +19650,7 @@ function listDistinctTools() {
19384
19650
  // src/dashboard/api-usage.ts
19385
19651
  init_api();
19386
19652
  function createUsageRouter(projectsDir, assignmentsDir2) {
19387
- const router = Router12();
19653
+ const router = Router13();
19388
19654
  router.get("/facets", (_req, res) => {
19389
19655
  try {
19390
19656
  initUsageDb();
@@ -19567,7 +19833,7 @@ init_parser();
19567
19833
  init_slug();
19568
19834
  init_timestamp();
19569
19835
  init_fs();
19570
- import { Router as Router13 } from "express";
19836
+ import { Router as Router14 } from "express";
19571
19837
  import { resolve as resolve33 } from "path";
19572
19838
  import { readFile as readFile23 } from "fs/promises";
19573
19839
  init_playbooks();
@@ -19584,7 +19850,7 @@ function statusForPlaybookError(code) {
19584
19850
  }
19585
19851
  }
19586
19852
  function createPlaybooksRouter(playbooksDir2) {
19587
- const router = Router13();
19853
+ const router = Router14();
19588
19854
  router.get("/", async (_req, res) => {
19589
19855
  try {
19590
19856
  const playbooks = await listPlaybooks(playbooksDir2);
@@ -19748,7 +20014,7 @@ init_fs_migration();
19748
20014
  init_parser2();
19749
20015
  init_fs();
19750
20016
  init_paths();
19751
- import { Router as Router15 } from "express";
20017
+ import { Router as Router16 } from "express";
19752
20018
  import { readdir as readdir15 } from "fs/promises";
19753
20019
  import { resolve as resolvePath, dirname as dirname10 } from "path";
19754
20020
  import { rename as rename6, mkdir as mkdir5 } from "fs/promises";
@@ -20428,7 +20694,7 @@ function touchItem3(item) {
20428
20694
  item.updatedAt = now;
20429
20695
  }
20430
20696
  function createTodosRouter(todosDir2, broadcast, projectsDir) {
20431
- const router = Router15();
20697
+ const router = Router16();
20432
20698
  installRecordsInvalidation(router);
20433
20699
  function broadcastUpdate() {
20434
20700
  broadcast({ type: "todos-updated", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
@@ -21202,7 +21468,7 @@ init_parser2();
21202
21468
  init_fs();
21203
21469
  init_paths();
21204
21470
  init_slug();
21205
- import { Router as Router16 } from "express";
21471
+ import { Router as Router17 } from "express";
21206
21472
  import { mkdir as mkdir6, readFile as readFile24, rename as rename7 } from "fs/promises";
21207
21473
  import { resolve as resolve36, dirname as dirname11 } from "path";
21208
21474
  init_api();
@@ -21253,7 +21519,7 @@ function notFound(res, slug) {
21253
21519
  res.status(404).json({ error: `Project "${slug}" not found` });
21254
21520
  }
21255
21521
  function createProjectTodosRouter(projectsDir, broadcast, workspaceTodosDir) {
21256
- const router = Router16({ mergeParams: true });
21522
+ const router = Router17({ mergeParams: true });
21257
21523
  installRecordsInvalidation(router);
21258
21524
  function broadcastUpdate(projectSlug) {
21259
21525
  broadcast({ type: "todos-updated", projectSlug, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
@@ -22112,7 +22378,7 @@ workspace: ${slug}
22112
22378
  }
22113
22379
 
22114
22380
  // src/dashboard/api-bundles.ts
22115
- import { Router as Router17 } from "express";
22381
+ import { Router as Router18 } from "express";
22116
22382
  import { readdir as readdir16 } from "fs/promises";
22117
22383
 
22118
22384
  // src/todos/bundle-parser.ts
@@ -22223,7 +22489,7 @@ function annotate(bundle, items) {
22223
22489
  }
22224
22490
  function createBundlesRouter(todosDir2, broadcast) {
22225
22491
  void broadcast;
22226
- const router = Router17();
22492
+ const router = Router18();
22227
22493
  function validateWorkspace(req2, res, next) {
22228
22494
  const workspace = getWorkspaceParam2(req2.params.workspace);
22229
22495
  if (workspace && !WORKSPACE_REGEX3.test(workspace)) {
@@ -22289,7 +22555,7 @@ function createBundlesRouter(todosDir2, broadcast) {
22289
22555
  init_fs();
22290
22556
  init_paths();
22291
22557
  init_slug();
22292
- import { Router as Router18 } from "express";
22558
+ import { Router as Router19 } from "express";
22293
22559
  import { resolve as resolve37 } from "path";
22294
22560
  init_parser2();
22295
22561
  function deriveStatus2(bundle, items) {
@@ -22319,7 +22585,7 @@ function notFound2(res, slug) {
22319
22585
  }
22320
22586
  function createProjectBundlesRouter(projectsDir, broadcast) {
22321
22587
  void broadcast;
22322
- const router = Router18({ mergeParams: true });
22588
+ const router = Router19({ mergeParams: true });
22323
22589
  function validateProjectId(req2, res, next) {
22324
22590
  const slug = getProjectIdParam2(req2.params.projectId);
22325
22591
  if (!slug || !isValidSlug(slug)) {
@@ -22353,7 +22619,7 @@ function createProjectBundlesRouter(projectsDir, broadcast) {
22353
22619
  init_config2();
22354
22620
  init_api();
22355
22621
  init_scanner();
22356
- import { Router as Router19 } from "express";
22622
+ import { Router as Router20 } from "express";
22357
22623
 
22358
22624
  // src/utils/github-backup.ts
22359
22625
  init_paths();
@@ -22676,7 +22942,7 @@ async function getBackupStatus() {
22676
22942
 
22677
22943
  // src/dashboard/api-backup.ts
22678
22944
  function createBackupRouter() {
22679
- const router = Router19();
22945
+ const router = Router20();
22680
22946
  router.get("/", async (_req, res) => {
22681
22947
  try {
22682
22948
  const status = await getBackupStatus();
@@ -23535,6 +23801,7 @@ function createDashboardServer(options) {
23535
23801
  }
23536
23802
  });
23537
23803
  app.use("/api/config/terminal", createTerminalConfigRouter());
23804
+ app.use("/api/config/search", createSearchConfigRouter());
23538
23805
  app.use("/api/config/workspace-visibility", createWorkspaceVisibilityConfigRouter());
23539
23806
  app.get("/api/config/hotkeys", async (_req, res) => {
23540
23807
  try {