@unbrained/pm-cli 2026.5.28 → 2026.5.29

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 (83) hide show
  1. package/CHANGELOG.md +100 -83
  2. package/dist/cli/commander-usage.js +8 -8
  3. package/dist/cli/commander-usage.js.map +1 -1
  4. package/dist/cli/commands/aggregate.js +4 -3
  5. package/dist/cli/commands/aggregate.js.map +1 -1
  6. package/dist/cli/commands/calendar.d.ts +8 -0
  7. package/dist/cli/commands/calendar.js +13 -2
  8. package/dist/cli/commands/calendar.js.map +1 -1
  9. package/dist/cli/commands/completion.js +34 -2
  10. package/dist/cli/commands/completion.js.map +1 -1
  11. package/dist/cli/commands/config.d.ts +11 -1
  12. package/dist/cli/commands/config.js +68 -6
  13. package/dist/cli/commands/config.js.map +1 -1
  14. package/dist/cli/commands/create.d.ts +1 -0
  15. package/dist/cli/commands/create.js +40 -4
  16. package/dist/cli/commands/create.js.map +1 -1
  17. package/dist/cli/commands/extension/bundled-catalog.js +4 -3
  18. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -1
  19. package/dist/cli/commands/health.js +3 -11
  20. package/dist/cli/commands/health.js.map +1 -1
  21. package/dist/cli/commands/linked-test-parsers.js +5 -4
  22. package/dist/cli/commands/linked-test-parsers.js.map +1 -1
  23. package/dist/cli/commands/plan.js +5 -4
  24. package/dist/cli/commands/plan.js.map +1 -1
  25. package/dist/cli/commands/search.js +45 -2
  26. package/dist/cli/commands/search.js.map +1 -1
  27. package/dist/cli/commands/update-many.js +35 -6
  28. package/dist/cli/commands/update-many.js.map +1 -1
  29. package/dist/cli/commands/update.d.ts +2 -0
  30. package/dist/cli/commands/update.js +38 -6
  31. package/dist/cli/commands/update.js.map +1 -1
  32. package/dist/cli/help-json-payload.d.ts +1 -11
  33. package/dist/cli/help-json-payload.js +12 -12
  34. package/dist/cli/help-json-payload.js.map +1 -1
  35. package/dist/cli/register-mutation.js +20 -8
  36. package/dist/cli/register-mutation.js.map +1 -1
  37. package/dist/cli/register-setup.js +4 -2
  38. package/dist/cli/register-setup.js.map +1 -1
  39. package/dist/cli/registration-helpers.d.ts +2 -6
  40. package/dist/cli/registration-helpers.js +9 -6
  41. package/dist/cli/registration-helpers.js.map +1 -1
  42. package/dist/core/config/nested-settings.d.ts +86 -0
  43. package/dist/core/config/nested-settings.js +258 -0
  44. package/dist/core/config/nested-settings.js.map +1 -0
  45. package/dist/core/item/parse.d.ts +19 -0
  46. package/dist/core/item/parse.js +76 -2
  47. package/dist/core/item/parse.js.map +1 -1
  48. package/dist/core/item/priority.d.ts +2 -1
  49. package/dist/core/item/priority.js +12 -2
  50. package/dist/core/item/priority.js.map +1 -1
  51. package/dist/core/search/providers.js +25 -5
  52. package/dist/core/search/providers.js.map +1 -1
  53. package/dist/core/search/staleness.d.ts +23 -0
  54. package/dist/core/search/staleness.js +34 -0
  55. package/dist/core/search/staleness.js.map +1 -0
  56. package/dist/core/search/vector-stores.js +12 -3
  57. package/dist/core/search/vector-stores.js.map +1 -1
  58. package/dist/core/shared/html-entity-decode.d.ts +21 -0
  59. package/dist/core/shared/html-entity-decode.js +122 -0
  60. package/dist/core/shared/html-entity-decode.js.map +1 -0
  61. package/dist/core/shared/split-comma-list.d.ts +20 -0
  62. package/dist/core/shared/split-comma-list.js +29 -0
  63. package/dist/core/shared/split-comma-list.js.map +1 -0
  64. package/dist/mcp/server.js +10 -3
  65. package/dist/mcp/server.js.map +1 -1
  66. package/dist/sdk/cli-contracts/commander-mutation-options.js +47 -11
  67. package/dist/sdk/cli-contracts/commander-mutation-options.js.map +1 -1
  68. package/dist/sdk/cli-contracts/tool-option-contracts.js +5 -2
  69. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
  70. package/dist/sdk/cli-contracts/tool-parameter-tables.js +12 -2
  71. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
  72. package/dist/sdk/cli-contracts.js +25 -4
  73. package/dist/sdk/cli-contracts.js.map +1 -1
  74. package/dist/sdk/runtime.d.ts +1 -1
  75. package/dist/sdk/runtime.js +3 -3
  76. package/dist/sdk/runtime.js.map +1 -1
  77. package/docs/AGENT_GUIDE.md +7 -0
  78. package/docs/COMMANDS.md +17 -0
  79. package/docs/CONFIGURATION.md +55 -0
  80. package/docs/QUICKSTART.md +3 -0
  81. package/package.json +1 -1
  82. package/packages/pm-calendar/extensions/calendar/runtime.js +5 -0
  83. package/packages/pm-calendar/extensions/calendar/runtime.ts +6 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-settings.js","sources":["core/config/nested-settings.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Nested leaf settings exposed via `pm config <scope> set/get <key> <value>`.\n *\n * These are simple string/number leaves of {@link PmSettings} (provider URLs,\n * vector-store adapter, search tuning) that previously required hand-editing\n * `.agents/pm/settings.json`. They live here so the same dotted path is\n * documented in one place and surfaced both to the config dispatcher and to\n * `pm config list` (so `pm config list --json` is discoverable).\n *\n * Shape conventions:\n * - `path` is the dotted JSON path in {@link PmSettings} (e.g. `search.provider`).\n * - `kind` is the value shape: \"string\" | \"integer\" | \"number\" | \"ratio\"\n * - \"ratio\" must be a finite number in [0, 1].\n * - \"integer\" must be a finite non-negative integer. Set `min: 1` for keys\n * where the runtime silently falls back when 0 is supplied (e.g. batch\n * size, timeout, max-results limits).\n * - \"number\" must be a finite number — negatives ARE allowed (e.g. score\n * thresholds may legitimately be negative when a provider normalizes\n * scores into a signed range).\n *\n * Adding a key here makes it acceptable to `pm config <scope> set <key> <value>`\n * with no other code changes — the dispatcher walks the dotted path on the\n * already-validated PmSettings shape.\n */\n\nexport type NestedSettingKind = \"string\" | \"integer\" | \"number\" | \"ratio\";\n\nexport interface NestedSettingDescriptor {\n /** CLI key (snake_case). Kebab-case form is accepted by normalizing `-` → `_`. */\n key: string;\n /** Dotted JSON path in PmSettings. */\n path: string;\n /** Value shape. */\n kind: NestedSettingKind;\n /** Short human-facing summary for `pm config list`. */\n summary: string;\n /**\n * Optional minimum value for `integer` / `number` kinds. When set,\n * `parseNestedSettingValue` rejects values strictly below `min`. Useful for\n * settings where 0 would be silently ignored by the runtime (batch sizes,\n * timeouts, max-results limits).\n */\n min?: number;\n}\n\n/**\n * Search/provider/vector-store leaves. Order is the display order in\n * `pm config list` and in error hints.\n */\nexport const NESTED_SETTING_DESCRIPTORS: readonly NestedSettingDescriptor[] = [\n {\n key: \"search_provider\",\n path: \"search.provider\",\n kind: \"string\",\n summary: \"Search embedding provider name (e.g. openai, ollama, or an extension provider).\",\n },\n {\n key: \"search_embedding_model\",\n path: \"search.embedding_model\",\n kind: \"string\",\n summary: \"Default embedding model name (overrides provider-specific model when set).\",\n },\n {\n key: \"search_embedding_batch_size\",\n path: \"search.embedding_batch_size\",\n kind: \"integer\",\n min: 1,\n summary: \"Number of items embedded per request batch.\",\n },\n {\n key: \"search_embedding_timeout_ms\",\n path: \"search.embedding_timeout_ms\",\n kind: \"integer\",\n min: 1,\n summary: \"Per-request embedding timeout in milliseconds.\",\n },\n {\n key: \"search_score_threshold\",\n path: \"search.score_threshold\",\n kind: \"number\",\n summary: \"Minimum score for a hit to be returned (0 keeps all matches).\",\n },\n {\n key: \"search_hybrid_semantic_weight\",\n path: \"search.hybrid_semantic_weight\",\n kind: \"ratio\",\n summary: \"Hybrid mode semantic weight in [0, 1] (1-weight goes to keyword).\",\n },\n {\n key: \"search_max_results\",\n path: \"search.max_results\",\n kind: \"integer\",\n min: 1,\n summary: \"Default upper bound on search hits when --limit is not supplied.\",\n },\n {\n key: \"openai_base_url\",\n path: \"providers.openai.base_url\",\n kind: \"string\",\n summary: \"OpenAI-compatible API base URL (LM Studio/vLLM also use this).\",\n },\n {\n key: \"openai_api_key\",\n path: \"providers.openai.api_key\",\n kind: \"string\",\n summary: \"OpenAI-compatible API key.\",\n },\n {\n key: \"openai_model\",\n path: \"providers.openai.model\",\n kind: \"string\",\n summary: \"OpenAI-compatible embedding model name.\",\n },\n {\n key: \"ollama_base_url\",\n path: \"providers.ollama.base_url\",\n kind: \"string\",\n summary: \"Ollama API base URL (typically http://localhost:11434).\",\n },\n {\n key: \"ollama_model\",\n path: \"providers.ollama.model\",\n kind: \"string\",\n summary: \"Ollama embedding model name (e.g. nomic-embed-text).\",\n },\n {\n key: \"vector_store_adapter\",\n path: \"vector_store.adapter\",\n kind: \"string\",\n summary: \"Vector store adapter name (lancedb, qdrant, or an extension adapter).\",\n },\n {\n key: \"qdrant_url\",\n path: \"vector_store.qdrant.url\",\n kind: \"string\",\n summary: \"Qdrant HTTP API URL.\",\n },\n {\n key: \"qdrant_api_key\",\n path: \"vector_store.qdrant.api_key\",\n kind: \"string\",\n summary: \"Qdrant API key (empty if running unauthenticated).\",\n },\n {\n key: \"lancedb_path\",\n path: \"vector_store.lancedb.path\",\n kind: \"string\",\n summary: \"LanceDB storage path (relative to pm root or absolute).\",\n },\n];\n\nconst DESCRIPTOR_BY_KEY: ReadonlyMap<string, NestedSettingDescriptor> = new Map(\n NESTED_SETTING_DESCRIPTORS.map((descriptor) => [descriptor.key, descriptor]),\n);\n\n/** Canonical CLI keys (in declaration order). */\nexport const NESTED_SETTING_KEYS: readonly string[] = NESTED_SETTING_DESCRIPTORS.map(\n (descriptor) => descriptor.key,\n);\n\n/**\n * Map a raw user-supplied key (kebab or snake case, any casing) onto a known\n * nested-leaf descriptor. Returns `undefined` when the key is not a nested\n * leaf (callers can then fall back to the regular ConfigKey path).\n */\nexport function resolveNestedSettingDescriptor(raw: string | undefined): NestedSettingDescriptor | undefined {\n if (typeof raw !== \"string\") {\n return undefined;\n }\n const normalized = raw.trim().toLowerCase().replaceAll(\"-\", \"_\");\n if (normalized.length === 0) {\n return undefined;\n }\n return DESCRIPTOR_BY_KEY.get(normalized);\n}\n\n/** Recoverable parsed value with the descriptor it satisfied. */\nexport interface NestedSettingParsedValue {\n descriptor: NestedSettingDescriptor;\n value: string | number;\n}\n\n/** Throwable validation error returned as a structured result. */\nexport interface NestedSettingParseError {\n message: string;\n}\n\nexport type NestedSettingParseResult =\n | { ok: true; parsed: NestedSettingParsedValue }\n | { ok: false; error: NestedSettingParseError };\n\n/**\n * Validate and coerce a raw string value for a nested-leaf setting. The\n * returned value is the typed leaf that should be written into PmSettings.\n *\n * Empty strings are allowed for \"string\" leaves (used to clear a value).\n */\nexport function parseNestedSettingValue(\n descriptor: NestedSettingDescriptor,\n rawValue: string,\n): NestedSettingParseResult {\n if (typeof rawValue !== \"string\") {\n return { ok: false, error: { message: `Config set ${descriptor.key} requires a string value` } };\n }\n const trimmed = rawValue.trim();\n if (descriptor.kind === \"string\") {\n return { ok: true, parsed: { descriptor, value: trimmed } };\n }\n\n // Number(\"\") === 0, which would silently accept empty / whitespace-only input\n // as a valid zero. Reject explicitly so misconfigurations don't slip through.\n if (trimmed.length === 0) {\n return {\n ok: false,\n error: { message: `Config set ${descriptor.key} requires a non-empty value` },\n };\n }\n\n const parsed = Number(trimmed);\n if (!Number.isFinite(parsed)) {\n return {\n ok: false,\n error: { message: `Config set ${descriptor.key} requires a finite number, got \"${rawValue}\"` },\n };\n }\n if (descriptor.kind === \"integer\") {\n if (!Number.isInteger(parsed) || parsed < 0) {\n return {\n ok: false,\n error: { message: `Config set ${descriptor.key} requires a non-negative integer, got \"${rawValue}\"` },\n };\n }\n if (descriptor.min !== undefined && parsed < descriptor.min) {\n return {\n ok: false,\n error: {\n message: `Config set ${descriptor.key} requires an integer >= ${descriptor.min}, got \"${rawValue}\" (the runtime silently ignores 0 here and falls back to the default)`,\n },\n };\n }\n return { ok: true, parsed: { descriptor, value: parsed } };\n }\n if (descriptor.kind === \"ratio\") {\n if (parsed < 0 || parsed > 1) {\n return {\n ok: false,\n error: { message: `Config set ${descriptor.key} requires a number in [0, 1], got \"${rawValue}\"` },\n };\n }\n return { ok: true, parsed: { descriptor, value: parsed } };\n }\n // kind === \"number\" — negatives are allowed; only apply an explicit `min`.\n if (descriptor.min !== undefined && parsed < descriptor.min) {\n return {\n ok: false,\n error: { message: `Config set ${descriptor.key} requires a number >= ${descriptor.min}, got \"${rawValue}\"` },\n };\n }\n return { ok: true, parsed: { descriptor, value: parsed } };\n}\n\n/** Walk a dotted path on an arbitrary record (best-effort, returns null on miss). */\nexport function readNestedSettingValue(settings: unknown, descriptor: NestedSettingDescriptor): string | number | null {\n const segments = descriptor.path.split(\".\");\n let cursor: unknown = settings;\n for (const segment of segments) {\n if (typeof cursor !== \"object\" || cursor === null) {\n return null;\n }\n cursor = (cursor as Record<string, unknown>)[segment];\n }\n if (typeof cursor === \"string\" || typeof cursor === \"number\") {\n return cursor;\n }\n return null;\n}\n\n/**\n * Set a leaf value on a settings object by walking the descriptor's dotted\n * path. Missing intermediate objects are created. Returns `true` when the\n * value actually changed.\n */\nexport function writeNestedSettingValue(\n settings: Record<string, unknown>,\n descriptor: NestedSettingDescriptor,\n value: string | number,\n): boolean {\n const segments = descriptor.path.split(\".\");\n let cursor: Record<string, unknown> = settings;\n for (let index = 0; index < segments.length - 1; index += 1) {\n const segment = segments[index];\n const existing = cursor[segment];\n if (typeof existing !== \"object\" || existing === null || Array.isArray(existing)) {\n const next: Record<string, unknown> = {};\n cursor[segment] = next;\n cursor = next;\n } else {\n cursor = existing as Record<string, unknown>;\n }\n }\n const leafKey = segments[segments.length - 1];\n const previous = cursor[leafKey];\n if (previous === value) {\n return false;\n }\n cursor[leafKey] = value;\n return true;\n}\n"],"names":[],"mappings":"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","debugId":"6cd249f1-0f64-51af-941f-2feb42b4a037"}
@@ -1,4 +1,23 @@
1
1
  export declare function parseTags(raw: string): string[];
2
+ /**
3
+ * Merge repeated `--add-tags` / `--remove-tags` values into a single normalized
4
+ * tag list. Each entry can itself be CSV or a JSON array, mirroring the format
5
+ * accepted by `--tags`. Returns a deterministically sorted, deduped list.
6
+ */
7
+ export declare function collectTagFlagValues(values: readonly string[] | undefined): string[];
8
+ /**
9
+ * Apply an additive tag mutation to a base tag list. Used by `pm create` and
10
+ * `pm update` so `--add-tags` extends `--tags` (or the existing tags) without
11
+ * replacing them. Output is sorted + deduped lowercase, matching `parseTags`.
12
+ */
13
+ export declare function mergeAdditiveTags(baseTags: readonly string[], add: readonly string[] | undefined): string[];
14
+ /**
15
+ * Apply a subtractive tag mutation to a base tag list. Used by `pm update` so
16
+ * `--remove-tags x,y` prunes those entries without rewriting the full set.
17
+ * Removal is case-insensitive: both the base list and the removal selectors are
18
+ * normalized to canonical lowercase before matching.
19
+ */
20
+ export declare function applyTagRemovals(baseTags: readonly string[], remove: readonly string[] | undefined): string[];
2
21
  export declare function parseCsvKv(raw: string, optionName: string): Record<string, string>;
3
22
  export interface StdinTokenResolver {
4
23
  resolveValue(value: string | undefined, optionName: string): Promise<string | undefined>;
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2c3c0fc7-42bc-59f9-b864-f89511f894ec")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d5e00545-4334-546c-8d97-005469be3899")}catch(e){}}();
3
3
  import { PmCliError } from "../shared/errors.js";
4
4
  import { EXIT_CODE } from "../shared/constants.js";
5
5
  const STDIN_TOKEN = "-";
@@ -38,6 +38,80 @@ export function parseTags(raw) {
38
38
  .map((tag) => tag.toLowerCase());
39
39
  return Array.from(new Set(tags)).sort((a, b) => a.localeCompare(b));
40
40
  }
41
+ /**
42
+ * Merge repeated `--add-tags` / `--remove-tags` values into a single normalized
43
+ * tag list. Each entry can itself be CSV or a JSON array, mirroring the format
44
+ * accepted by `--tags`. Returns a deterministically sorted, deduped list.
45
+ */
46
+ export function collectTagFlagValues(values) {
47
+ if (!Array.isArray(values) || values.length === 0) {
48
+ return [];
49
+ }
50
+ const collected = [];
51
+ for (const raw of values) {
52
+ if (typeof raw !== "string") {
53
+ continue;
54
+ }
55
+ for (const tag of parseTags(raw)) {
56
+ collected.push(tag);
57
+ }
58
+ }
59
+ return Array.from(new Set(collected)).sort((a, b) => a.localeCompare(b));
60
+ }
61
+ /**
62
+ * Normalize a base tag list to the canonical form pm stores: trimmed,
63
+ * lowercased, non-empty. Existing front-matter tags are almost always already
64
+ * canonical (parseTags lowercases on write), but legacy or hand-edited `.toon`
65
+ * files can carry mixed-case entries — normalizing here keeps additive and
66
+ * subtractive mutations case-insensitive (so `--add-tags beta` dedupes against
67
+ * an existing `Beta`, and `--remove-tags alpha` removes an existing `Alpha`).
68
+ */
69
+ function normalizeBaseTags(baseTags) {
70
+ // Defensive: front-matter parsed from corrupted/hand-edited `.toon` (or an
71
+ // external SDK caller) could pass a non-array or non-string entries despite
72
+ // the `string[]` type — guard the array and skip non-strings rather than
73
+ // throwing on `.filter`/`.trim()`.
74
+ if (!Array.isArray(baseTags)) {
75
+ return [];
76
+ }
77
+ return baseTags
78
+ .filter((tag) => typeof tag === "string")
79
+ .map((tag) => tag.trim().toLowerCase())
80
+ .filter(Boolean);
81
+ }
82
+ /**
83
+ * Apply an additive tag mutation to a base tag list. Used by `pm create` and
84
+ * `pm update` so `--add-tags` extends `--tags` (or the existing tags) without
85
+ * replacing them. Output is sorted + deduped lowercase, matching `parseTags`.
86
+ */
87
+ export function mergeAdditiveTags(baseTags, add) {
88
+ const normalizedBase = normalizeBaseTags(baseTags);
89
+ if (!add || add.length === 0) {
90
+ return Array.from(new Set(normalizedBase)).sort((a, b) => a.localeCompare(b));
91
+ }
92
+ const merged = new Set(normalizedBase);
93
+ for (const tag of collectTagFlagValues(add)) {
94
+ merged.add(tag);
95
+ }
96
+ return Array.from(merged).sort((a, b) => a.localeCompare(b));
97
+ }
98
+ /**
99
+ * Apply a subtractive tag mutation to a base tag list. Used by `pm update` so
100
+ * `--remove-tags x,y` prunes those entries without rewriting the full set.
101
+ * Removal is case-insensitive: both the base list and the removal selectors are
102
+ * normalized to canonical lowercase before matching.
103
+ */
104
+ export function applyTagRemovals(baseTags, remove) {
105
+ const normalizedBase = Array.from(new Set(normalizeBaseTags(baseTags))).sort((a, b) => a.localeCompare(b));
106
+ if (!remove || remove.length === 0) {
107
+ return normalizedBase;
108
+ }
109
+ const removeSet = new Set(collectTagFlagValues(remove));
110
+ if (removeSet.size === 0) {
111
+ return normalizedBase;
112
+ }
113
+ return normalizedBase.filter((tag) => !removeSet.has(tag));
114
+ }
41
115
  // Agents and MCP callers frequently pass --tags as a JSON array (e.g.
42
116
  // `--tags '["a","b"]'`). The MCP server normalizes that upstream, but direct
43
117
  // CLI invocations used to write the raw bracket string into front matter,
@@ -303,4 +377,4 @@ export function parseOptionalNumber(raw, optionName) {
303
377
  return value;
304
378
  }
305
379
  //# sourceMappingURL=parse.js.map
306
- //# debugId=2c3c0fc7-42bc-59f9-b864-f89511f894ec
380
+ //# debugId=d5e00545-4334-546c-8d97-005469be3899
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sources":["core/item/parse.ts"],"sourceRoot":"/","sourcesContent":["import { PmCliError } from \"../shared/errors.js\";\nimport { EXIT_CODE } from \"../shared/constants.js\";\n\nconst STDIN_TOKEN = \"-\";\nconst CONTINUABLE_VALUE_KEYS = new Set([\n \"actual_result\",\n \"body\",\n \"cmd\",\n \"command\",\n \"customer_impact\",\n \"description\",\n \"environment\",\n \"expected_result\",\n \"impact\",\n \"location\",\n \"message\",\n \"note\",\n \"outcome\",\n \"repro_steps\",\n \"resolution\",\n \"text\",\n \"title\",\n \"unblock_note\",\n \"value\",\n \"why_now\",\n]);\n\nexport function parseTags(raw: string): string[] {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n return [];\n }\n const source = coerceJsonTagArray(trimmed) ?? trimmed;\n const tags = source\n .split(\",\")\n .map((tag) => tag.trim())\n .filter(Boolean)\n .map((tag) => tag.toLowerCase());\n return Array.from(new Set(tags)).sort((a, b) => a.localeCompare(b));\n}\n\n// Agents and MCP callers frequently pass --tags as a JSON array (e.g.\n// `--tags '[\"a\",\"b\"]'`). The MCP server normalizes that upstream, but direct\n// CLI invocations used to write the raw bracket string into front matter,\n// silently corrupting tags. Accept JSON arrays of primitives transparently.\nfunction coerceJsonTagArray(trimmed: string): string | null {\n if (!trimmed.startsWith(\"[\")) {\n return null;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return null;\n }\n if (!Array.isArray(parsed)) {\n return null;\n }\n return parsed\n .map((entry) =>\n typeof entry === \"string\" || typeof entry === \"number\" || typeof entry === \"boolean\"\n ? String(entry).replace(/,/g, \" \")\n : \"\",\n )\n .filter((entry) => entry.length > 0)\n .join(\",\");\n}\n\nfunction normalizeLineEndings(value: string): string {\n return value.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction stripCodeFenceEnvelope(value: string): string {\n const normalized = normalizeLineEndings(value).trim();\n if (!normalized.startsWith(\"```\")) {\n return value;\n }\n const lines = normalized.split(\"\\n\");\n if (lines.length < 2) {\n return value;\n }\n if (!lines[0].startsWith(\"```\")) {\n return value;\n }\n if (lines.at(-1)?.trim() !== \"```\") {\n return value;\n }\n return lines.slice(1, -1).join(\"\\n\");\n}\n\nfunction splitCsvSegments(raw: string): string[] {\n const segments: string[] = [];\n let current = \"\";\n let inQuotes = false;\n let escaped = false;\n\n for (const char of raw) {\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n if (char === \"\\\\\") {\n current += char;\n escaped = true;\n continue;\n }\n if (char === \"\\\"\") {\n inQuotes = !inQuotes;\n current += char;\n continue;\n }\n if (char === \",\" && !inQuotes) {\n segments.push(current.trim());\n current = \"\";\n continue;\n }\n current += char;\n }\n if (current.trim()) {\n segments.push(current.trim());\n }\n return segments;\n}\n\nfunction unquoteValue(value: string): string {\n const trimmed = value.trim();\n if (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) {\n return trimmed.slice(1, -1).replace(/\\\\\"/g, \"\\\"\");\n }\n return value;\n}\n\nfunction findKeyValueDelimiter(segment: string): number {\n const equalsIndex = segment.indexOf(\"=\");\n const colonIndex = segment.indexOf(\":\");\n const hasEquals = equalsIndex > 0;\n const hasColon = colonIndex > 0;\n if (hasEquals && hasColon) {\n return Math.min(equalsIndex, colonIndex);\n }\n if (hasEquals) {\n return equalsIndex;\n }\n if (hasColon) {\n return colonIndex;\n }\n return -1;\n}\n\nfunction buildOptionSpecificKvGuidance(raw: string, optionName: string): string {\n if (optionName === \"--add\" || optionName === \"--add-glob\") {\n const looksLikePath = /[./\\\\]/.test(raw) || /\\.[a-z]{1,6}$/i.test(raw.trim());\n if (looksLikePath) {\n return 'For file/doc paths use: path=<file-path>[,scope=project|global]. The scope field is optional and defaults to project (example: path=src/api.ts or path=README.md,scope=project). ';\n }\n }\n if (optionName !== \"--event\") {\n return \"\";\n }\n const lowered = raw.toLowerCase();\n const recurrenceHint =\n lowered.includes(\"recur_\") || lowered.includes(\"recurrence\")\n ? ' Recurrence list values must stay in one field and use \"|\" delimiters (for example recur_by_weekday=mon|wed or recur_by_month_day=1|15).'\n : \"\";\n const weekdayAliasHint = lowered.includes(\"recur_byweekday\")\n ? \" Use recur_by_weekday (with underscores) for weekday recurrence filters.\"\n : \"\";\n return `${recurrenceHint}${weekdayAliasHint}`;\n}\n\nfunction buildInvalidKvMessage(raw: string, optionName: string): string {\n const condensed = raw.replaceAll(/\\s+/g, \" \").trim();\n const preview = condensed.length > 160 ? `${condensed.slice(0, 157)}...` : condensed;\n const optionSpecificGuidance = buildOptionSpecificKvGuidance(raw, optionName);\n return (\n `Invalid ${optionName} value \"${preview}\". Expected key=value entries separated by commas. ` +\n optionSpecificGuidance +\n 'Also accepts markdown-style key/value lines (for example \"- path: README.md\"). ' +\n `Use ${optionName} ${STDIN_TOKEN} to read piped stdin input.`\n );\n}\n\nfunction parseMarkdownKeyValueLines(raw: string): Record<string, string> | null {\n const normalized = stripCodeFenceEnvelope(raw).trim();\n if (normalized.length === 0) {\n return null;\n }\n if (!normalized.includes(\"\\n\") && !normalized.startsWith(\"-\") && !normalized.startsWith(\"*\") && !normalized.startsWith(\"+\")) {\n return null;\n }\n\n const result: Record<string, string> = {};\n let activeKey: string | undefined;\n const lines = normalizeLineEndings(normalized)\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n\n for (const line of lines) {\n const match = line.match(/^(?:[-*+]\\s+)?([a-zA-Z0-9_.-]+)\\s*(=|:)\\s*(.*)$/);\n if (match) {\n const key = match[1].trim();\n result[key] = unquoteValue(match[3].trim());\n activeKey = key;\n continue;\n }\n if (activeKey && CONTINUABLE_VALUE_KEYS.has(activeKey.toLowerCase())) {\n result[activeKey] = `${result[activeKey]}\\n${line}`;\n continue;\n }\n return null;\n }\n\n return Object.keys(result).length > 0 ? result : null;\n}\n\nexport function parseCsvKv(raw: string, optionName: string): Record<string, string> {\n const trimmed = stripCodeFenceEnvelope(raw).trim();\n if (!trimmed) {\n throw new PmCliError(`${optionName} cannot be empty`, EXIT_CODE.USAGE);\n }\n\n const markdownStyle = parseMarkdownKeyValueLines(trimmed);\n if (markdownStyle) {\n return markdownStyle;\n }\n\n const result: Record<string, string> = {};\n let activeKey: string | undefined;\n const segments = splitCsvSegments(trimmed);\n\n for (const segment of segments) {\n const delimiterIndex = findKeyValueDelimiter(segment);\n if (delimiterIndex > 0) {\n const key = segment.slice(0, delimiterIndex).trim();\n if (!key) {\n throw new PmCliError(buildInvalidKvMessage(raw, optionName), EXIT_CODE.USAGE);\n }\n const value = unquoteValue(segment.slice(delimiterIndex + 1).trim());\n result[key] = value;\n activeKey = key;\n continue;\n }\n if (activeKey && CONTINUABLE_VALUE_KEYS.has(activeKey.toLowerCase())) {\n result[activeKey] = `${result[activeKey]},${segment.trim()}`;\n continue;\n }\n throw new PmCliError(buildInvalidKvMessage(raw, optionName), EXIT_CODE.USAGE);\n }\n\n if (Object.keys(result).length === 0) {\n throw new PmCliError(buildInvalidKvMessage(raw, optionName), EXIT_CODE.USAGE);\n }\n\n return result;\n}\n\nasync function readStdinText(optionName: string): Promise<string> {\n if (process.stdin.isTTY === true) {\n throw new PmCliError(\n `${optionName} value \"${STDIN_TOKEN}\" requires piped stdin input. Pipe content into the command, or end manual stdin with Ctrl+D (Unix/macOS) or Ctrl+Z then Enter (Windows).`,\n EXIT_CODE.USAGE,\n );\n }\n process.stdin.setEncoding(\"utf8\");\n return await new Promise<string>((resolve, reject) => {\n let input = \"\";\n process.stdin.on(\"data\", (chunk: string) => {\n input += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(normalizeLineEndings(input));\n });\n process.stdin.on(\"error\", (error) => {\n reject(error);\n });\n });\n}\n\nexport interface StdinTokenResolver {\n resolveValue(value: string | undefined, optionName: string): Promise<string | undefined>;\n resolveList(values: string[] | undefined, optionName: string): Promise<string[] | undefined>;\n}\n\nexport function createStdinTokenResolver(): StdinTokenResolver {\n let stdinValuePromise: Promise<string> | undefined;\n let stdinConsumerOption: string | undefined;\n\n const consumeStdin = async (optionName: string): Promise<string> => {\n if (stdinConsumerOption && stdinConsumerOption !== optionName) {\n throw new PmCliError(\n `Only one option may use \"${STDIN_TOKEN}\" stdin token per command invocation. Already used by ${stdinConsumerOption}.`,\n EXIT_CODE.USAGE,\n );\n }\n stdinConsumerOption = optionName;\n if (!stdinValuePromise) {\n stdinValuePromise = readStdinText(optionName);\n }\n return await stdinValuePromise;\n };\n\n const resolveValue = async (value: string | undefined, optionName: string): Promise<string | undefined> => {\n if (value === undefined) {\n return undefined;\n }\n if (value.trim() !== STDIN_TOKEN) {\n return value;\n }\n return await consumeStdin(optionName);\n };\n\n const resolveList = async (values: string[] | undefined, optionName: string): Promise<string[] | undefined> => {\n if (!values) {\n return undefined;\n }\n const tokenIndexes = values\n .map((entry, index) => (entry.trim() === STDIN_TOKEN ? index : -1))\n .filter((index) => index >= 0);\n if (tokenIndexes.length === 0) {\n return values;\n }\n if (tokenIndexes.length > 1) {\n throw new PmCliError(\n `${optionName} accepts \"${STDIN_TOKEN}\" stdin token at most once per command invocation`,\n EXIT_CODE.USAGE,\n );\n }\n const stdinValue = await consumeStdin(optionName);\n const next = [...values];\n next[tokenIndexes[0]] = stdinValue;\n return next;\n };\n\n return {\n resolveValue,\n resolveList,\n };\n}\n\nexport function parseOptionalNumber(raw: string, optionName: string): number {\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n throw new PmCliError(`Invalid ${optionName} value \"${raw}\"`, EXIT_CODE.USAGE);\n }\n return value;\n}\n"],"names":[],"mappings":"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","debugId":"2c3c0fc7-42bc-59f9-b864-f89511f894ec"}
1
+ {"version":3,"file":"parse.js","sources":["core/item/parse.ts"],"sourceRoot":"/","sourcesContent":["import { PmCliError } from \"../shared/errors.js\";\nimport { EXIT_CODE } from \"../shared/constants.js\";\n\nconst STDIN_TOKEN = \"-\";\nconst CONTINUABLE_VALUE_KEYS = new Set([\n \"actual_result\",\n \"body\",\n \"cmd\",\n \"command\",\n \"customer_impact\",\n \"description\",\n \"environment\",\n \"expected_result\",\n \"impact\",\n \"location\",\n \"message\",\n \"note\",\n \"outcome\",\n \"repro_steps\",\n \"resolution\",\n \"text\",\n \"title\",\n \"unblock_note\",\n \"value\",\n \"why_now\",\n]);\n\nexport function parseTags(raw: string): string[] {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n return [];\n }\n const source = coerceJsonTagArray(trimmed) ?? trimmed;\n const tags = source\n .split(\",\")\n .map((tag) => tag.trim())\n .filter(Boolean)\n .map((tag) => tag.toLowerCase());\n return Array.from(new Set(tags)).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Merge repeated `--add-tags` / `--remove-tags` values into a single normalized\n * tag list. Each entry can itself be CSV or a JSON array, mirroring the format\n * accepted by `--tags`. Returns a deterministically sorted, deduped list.\n */\nexport function collectTagFlagValues(values: readonly string[] | undefined): string[] {\n if (!Array.isArray(values) || values.length === 0) {\n return [];\n }\n const collected: string[] = [];\n for (const raw of values) {\n if (typeof raw !== \"string\") {\n continue;\n }\n for (const tag of parseTags(raw)) {\n collected.push(tag);\n }\n }\n return Array.from(new Set(collected)).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Normalize a base tag list to the canonical form pm stores: trimmed,\n * lowercased, non-empty. Existing front-matter tags are almost always already\n * canonical (parseTags lowercases on write), but legacy or hand-edited `.toon`\n * files can carry mixed-case entries — normalizing here keeps additive and\n * subtractive mutations case-insensitive (so `--add-tags beta` dedupes against\n * an existing `Beta`, and `--remove-tags alpha` removes an existing `Alpha`).\n */\nfunction normalizeBaseTags(baseTags: readonly string[]): string[] {\n // Defensive: front-matter parsed from corrupted/hand-edited `.toon` (or an\n // external SDK caller) could pass a non-array or non-string entries despite\n // the `string[]` type — guard the array and skip non-strings rather than\n // throwing on `.filter`/`.trim()`.\n if (!Array.isArray(baseTags)) {\n return [];\n }\n return baseTags\n .filter((tag): tag is string => typeof tag === \"string\")\n .map((tag) => tag.trim().toLowerCase())\n .filter(Boolean);\n}\n\n/**\n * Apply an additive tag mutation to a base tag list. Used by `pm create` and\n * `pm update` so `--add-tags` extends `--tags` (or the existing tags) without\n * replacing them. Output is sorted + deduped lowercase, matching `parseTags`.\n */\nexport function mergeAdditiveTags(baseTags: readonly string[], add: readonly string[] | undefined): string[] {\n const normalizedBase = normalizeBaseTags(baseTags);\n if (!add || add.length === 0) {\n return Array.from(new Set(normalizedBase)).sort((a, b) => a.localeCompare(b));\n }\n const merged = new Set<string>(normalizedBase);\n for (const tag of collectTagFlagValues(add)) {\n merged.add(tag);\n }\n return Array.from(merged).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Apply a subtractive tag mutation to a base tag list. Used by `pm update` so\n * `--remove-tags x,y` prunes those entries without rewriting the full set.\n * Removal is case-insensitive: both the base list and the removal selectors are\n * normalized to canonical lowercase before matching.\n */\nexport function applyTagRemovals(baseTags: readonly string[], remove: readonly string[] | undefined): string[] {\n const normalizedBase = Array.from(new Set(normalizeBaseTags(baseTags))).sort((a, b) => a.localeCompare(b));\n if (!remove || remove.length === 0) {\n return normalizedBase;\n }\n const removeSet = new Set(collectTagFlagValues(remove));\n if (removeSet.size === 0) {\n return normalizedBase;\n }\n return normalizedBase.filter((tag) => !removeSet.has(tag));\n}\n\n// Agents and MCP callers frequently pass --tags as a JSON array (e.g.\n// `--tags '[\"a\",\"b\"]'`). The MCP server normalizes that upstream, but direct\n// CLI invocations used to write the raw bracket string into front matter,\n// silently corrupting tags. Accept JSON arrays of primitives transparently.\nfunction coerceJsonTagArray(trimmed: string): string | null {\n if (!trimmed.startsWith(\"[\")) {\n return null;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return null;\n }\n if (!Array.isArray(parsed)) {\n return null;\n }\n return parsed\n .map((entry) =>\n typeof entry === \"string\" || typeof entry === \"number\" || typeof entry === \"boolean\"\n ? String(entry).replace(/,/g, \" \")\n : \"\",\n )\n .filter((entry) => entry.length > 0)\n .join(\",\");\n}\n\nfunction normalizeLineEndings(value: string): string {\n return value.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction stripCodeFenceEnvelope(value: string): string {\n const normalized = normalizeLineEndings(value).trim();\n if (!normalized.startsWith(\"```\")) {\n return value;\n }\n const lines = normalized.split(\"\\n\");\n if (lines.length < 2) {\n return value;\n }\n if (!lines[0].startsWith(\"```\")) {\n return value;\n }\n if (lines.at(-1)?.trim() !== \"```\") {\n return value;\n }\n return lines.slice(1, -1).join(\"\\n\");\n}\n\nfunction splitCsvSegments(raw: string): string[] {\n const segments: string[] = [];\n let current = \"\";\n let inQuotes = false;\n let escaped = false;\n\n for (const char of raw) {\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n if (char === \"\\\\\") {\n current += char;\n escaped = true;\n continue;\n }\n if (char === \"\\\"\") {\n inQuotes = !inQuotes;\n current += char;\n continue;\n }\n if (char === \",\" && !inQuotes) {\n segments.push(current.trim());\n current = \"\";\n continue;\n }\n current += char;\n }\n if (current.trim()) {\n segments.push(current.trim());\n }\n return segments;\n}\n\nfunction unquoteValue(value: string): string {\n const trimmed = value.trim();\n if (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) {\n return trimmed.slice(1, -1).replace(/\\\\\"/g, \"\\\"\");\n }\n return value;\n}\n\nfunction findKeyValueDelimiter(segment: string): number {\n const equalsIndex = segment.indexOf(\"=\");\n const colonIndex = segment.indexOf(\":\");\n const hasEquals = equalsIndex > 0;\n const hasColon = colonIndex > 0;\n if (hasEquals && hasColon) {\n return Math.min(equalsIndex, colonIndex);\n }\n if (hasEquals) {\n return equalsIndex;\n }\n if (hasColon) {\n return colonIndex;\n }\n return -1;\n}\n\nfunction buildOptionSpecificKvGuidance(raw: string, optionName: string): string {\n if (optionName === \"--add\" || optionName === \"--add-glob\") {\n const looksLikePath = /[./\\\\]/.test(raw) || /\\.[a-z]{1,6}$/i.test(raw.trim());\n if (looksLikePath) {\n return 'For file/doc paths use: path=<file-path>[,scope=project|global]. The scope field is optional and defaults to project (example: path=src/api.ts or path=README.md,scope=project). ';\n }\n }\n if (optionName !== \"--event\") {\n return \"\";\n }\n const lowered = raw.toLowerCase();\n const recurrenceHint =\n lowered.includes(\"recur_\") || lowered.includes(\"recurrence\")\n ? ' Recurrence list values must stay in one field and use \"|\" delimiters (for example recur_by_weekday=mon|wed or recur_by_month_day=1|15).'\n : \"\";\n const weekdayAliasHint = lowered.includes(\"recur_byweekday\")\n ? \" Use recur_by_weekday (with underscores) for weekday recurrence filters.\"\n : \"\";\n return `${recurrenceHint}${weekdayAliasHint}`;\n}\n\nfunction buildInvalidKvMessage(raw: string, optionName: string): string {\n const condensed = raw.replaceAll(/\\s+/g, \" \").trim();\n const preview = condensed.length > 160 ? `${condensed.slice(0, 157)}...` : condensed;\n const optionSpecificGuidance = buildOptionSpecificKvGuidance(raw, optionName);\n return (\n `Invalid ${optionName} value \"${preview}\". Expected key=value entries separated by commas. ` +\n optionSpecificGuidance +\n 'Also accepts markdown-style key/value lines (for example \"- path: README.md\"). ' +\n `Use ${optionName} ${STDIN_TOKEN} to read piped stdin input.`\n );\n}\n\nfunction parseMarkdownKeyValueLines(raw: string): Record<string, string> | null {\n const normalized = stripCodeFenceEnvelope(raw).trim();\n if (normalized.length === 0) {\n return null;\n }\n if (!normalized.includes(\"\\n\") && !normalized.startsWith(\"-\") && !normalized.startsWith(\"*\") && !normalized.startsWith(\"+\")) {\n return null;\n }\n\n const result: Record<string, string> = {};\n let activeKey: string | undefined;\n const lines = normalizeLineEndings(normalized)\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n\n for (const line of lines) {\n const match = line.match(/^(?:[-*+]\\s+)?([a-zA-Z0-9_.-]+)\\s*(=|:)\\s*(.*)$/);\n if (match) {\n const key = match[1].trim();\n result[key] = unquoteValue(match[3].trim());\n activeKey = key;\n continue;\n }\n if (activeKey && CONTINUABLE_VALUE_KEYS.has(activeKey.toLowerCase())) {\n result[activeKey] = `${result[activeKey]}\\n${line}`;\n continue;\n }\n return null;\n }\n\n return Object.keys(result).length > 0 ? result : null;\n}\n\nexport function parseCsvKv(raw: string, optionName: string): Record<string, string> {\n const trimmed = stripCodeFenceEnvelope(raw).trim();\n if (!trimmed) {\n throw new PmCliError(`${optionName} cannot be empty`, EXIT_CODE.USAGE);\n }\n\n const markdownStyle = parseMarkdownKeyValueLines(trimmed);\n if (markdownStyle) {\n return markdownStyle;\n }\n\n const result: Record<string, string> = {};\n let activeKey: string | undefined;\n const segments = splitCsvSegments(trimmed);\n\n for (const segment of segments) {\n const delimiterIndex = findKeyValueDelimiter(segment);\n if (delimiterIndex > 0) {\n const key = segment.slice(0, delimiterIndex).trim();\n if (!key) {\n throw new PmCliError(buildInvalidKvMessage(raw, optionName), EXIT_CODE.USAGE);\n }\n const value = unquoteValue(segment.slice(delimiterIndex + 1).trim());\n result[key] = value;\n activeKey = key;\n continue;\n }\n if (activeKey && CONTINUABLE_VALUE_KEYS.has(activeKey.toLowerCase())) {\n result[activeKey] = `${result[activeKey]},${segment.trim()}`;\n continue;\n }\n throw new PmCliError(buildInvalidKvMessage(raw, optionName), EXIT_CODE.USAGE);\n }\n\n if (Object.keys(result).length === 0) {\n throw new PmCliError(buildInvalidKvMessage(raw, optionName), EXIT_CODE.USAGE);\n }\n\n return result;\n}\n\nasync function readStdinText(optionName: string): Promise<string> {\n if (process.stdin.isTTY === true) {\n throw new PmCliError(\n `${optionName} value \"${STDIN_TOKEN}\" requires piped stdin input. Pipe content into the command, or end manual stdin with Ctrl+D (Unix/macOS) or Ctrl+Z then Enter (Windows).`,\n EXIT_CODE.USAGE,\n );\n }\n process.stdin.setEncoding(\"utf8\");\n return await new Promise<string>((resolve, reject) => {\n let input = \"\";\n process.stdin.on(\"data\", (chunk: string) => {\n input += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(normalizeLineEndings(input));\n });\n process.stdin.on(\"error\", (error) => {\n reject(error);\n });\n });\n}\n\nexport interface StdinTokenResolver {\n resolveValue(value: string | undefined, optionName: string): Promise<string | undefined>;\n resolveList(values: string[] | undefined, optionName: string): Promise<string[] | undefined>;\n}\n\nexport function createStdinTokenResolver(): StdinTokenResolver {\n let stdinValuePromise: Promise<string> | undefined;\n let stdinConsumerOption: string | undefined;\n\n const consumeStdin = async (optionName: string): Promise<string> => {\n if (stdinConsumerOption && stdinConsumerOption !== optionName) {\n throw new PmCliError(\n `Only one option may use \"${STDIN_TOKEN}\" stdin token per command invocation. Already used by ${stdinConsumerOption}.`,\n EXIT_CODE.USAGE,\n );\n }\n stdinConsumerOption = optionName;\n if (!stdinValuePromise) {\n stdinValuePromise = readStdinText(optionName);\n }\n return await stdinValuePromise;\n };\n\n const resolveValue = async (value: string | undefined, optionName: string): Promise<string | undefined> => {\n if (value === undefined) {\n return undefined;\n }\n if (value.trim() !== STDIN_TOKEN) {\n return value;\n }\n return await consumeStdin(optionName);\n };\n\n const resolveList = async (values: string[] | undefined, optionName: string): Promise<string[] | undefined> => {\n if (!values) {\n return undefined;\n }\n const tokenIndexes = values\n .map((entry, index) => (entry.trim() === STDIN_TOKEN ? index : -1))\n .filter((index) => index >= 0);\n if (tokenIndexes.length === 0) {\n return values;\n }\n if (tokenIndexes.length > 1) {\n throw new PmCliError(\n `${optionName} accepts \"${STDIN_TOKEN}\" stdin token at most once per command invocation`,\n EXIT_CODE.USAGE,\n );\n }\n const stdinValue = await consumeStdin(optionName);\n const next = [...values];\n next[tokenIndexes[0]] = stdinValue;\n return next;\n };\n\n return {\n resolveValue,\n resolveList,\n };\n}\n\nexport function parseOptionalNumber(raw: string, optionName: string): number {\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n throw new PmCliError(`Invalid ${optionName} value \"${raw}\"`, EXIT_CODE.USAGE);\n }\n return value;\n}\n"],"names":[],"mappings":"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","debugId":"d5e00545-4334-546c-8d97-005469be3899"}
@@ -17,7 +17,8 @@ export declare const PRIORITY_ACCEPTED_FORMS_HINT: string;
17
17
  * Accepts:
18
18
  * - numeric strings 0,1,2,3,4 (unchanged from prior behavior)
19
19
  * - named levels (critical/high/medium/low/minimal), case-insensitive
20
+ * - native numbers 0..4 (arrives via MCP tool calls that JSON-encode priority as a number)
20
21
  *
21
22
  * Throws a USAGE error listing BOTH accepted forms for anything else.
22
23
  */
23
- export declare function resolvePriority(raw: string): Priority;
24
+ export declare function resolvePriority(raw: string | number): Priority;
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7535fe39-3a6e-5a1c-86ba-f1c7ca0b2407")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="15a39edd-a843-51f1-8015-880a5071c43f")}catch(e){}}();
3
3
  import { PmCliError } from "../shared/errors.js";
4
4
  import { EXIT_CODE } from "../shared/constants.js";
5
5
  /**
@@ -31,10 +31,20 @@ function priorityUsageError(raw) {
31
31
  * Accepts:
32
32
  * - numeric strings 0,1,2,3,4 (unchanged from prior behavior)
33
33
  * - named levels (critical/high/medium/low/minimal), case-insensitive
34
+ * - native numbers 0..4 (arrives via MCP tool calls that JSON-encode priority as a number)
34
35
  *
35
36
  * Throws a USAGE error listing BOTH accepted forms for anything else.
36
37
  */
37
38
  export function resolvePriority(raw) {
39
+ if (typeof raw === "number") {
40
+ if (Number.isInteger(raw) && raw >= 0 && raw <= 4) {
41
+ return raw;
42
+ }
43
+ throw priorityUsageError(String(raw));
44
+ }
45
+ if (typeof raw !== "string") {
46
+ throw priorityUsageError(String(raw));
47
+ }
38
48
  const trimmed = raw.trim();
39
49
  if (trimmed.length === 0) {
40
50
  throw priorityUsageError(raw);
@@ -52,4 +62,4 @@ export function resolvePriority(raw) {
52
62
  throw priorityUsageError(raw);
53
63
  }
54
64
  //# sourceMappingURL=priority.js.map
55
- //# debugId=7535fe39-3a6e-5a1c-86ba-f1c7ca0b2407
65
+ //# debugId=15a39edd-a843-51f1-8015-880a5071c43f
@@ -1 +1 @@
1
- {"version":3,"file":"priority.js","sources":["core/item/priority.ts"],"sourceRoot":"/","sourcesContent":["import { PmCliError } from \"../shared/errors.js\";\nimport { EXIT_CODE } from \"../shared/constants.js\";\n\nexport type Priority = 0 | 1 | 2 | 3 | 4;\n\n/**\n * Canonical mapping from named priority levels to numeric values. Agents and\n * humans frequently write words (\"high\") instead of numbers, so both create and\n * update accept either form. This single map is the source of truth so the two\n * commands cannot drift apart.\n */\nexport const PRIORITY_NAME_TO_VALUE: Readonly<Record<string, Priority>> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n minimal: 4,\n};\n\nconst PRIORITY_NAME_LIST = Object.keys(PRIORITY_NAME_TO_VALUE);\n\n/**\n * Human-readable description of every accepted priority form. Reused in error\n * messages so the wording stays consistent across commands.\n */\nexport const PRIORITY_ACCEPTED_FORMS_HINT =\n \"numbers 0..4 (0=critical, 1=high, 2=medium, 3=low, 4=minimal) or names \" +\n `(${PRIORITY_NAME_LIST.join(\", \")}), case-insensitive`;\n\nfunction priorityUsageError(raw: string): PmCliError {\n return new PmCliError(\n `Invalid priority \"${raw}\". Accepted values: ${PRIORITY_ACCEPTED_FORMS_HINT}.`,\n EXIT_CODE.USAGE,\n );\n}\n\n/**\n * Resolve a raw `--priority` option value to a numeric 0..4 priority.\n *\n * Accepts:\n * - numeric strings 0,1,2,3,4 (unchanged from prior behavior)\n * - named levels (critical/high/medium/low/minimal), case-insensitive\n *\n * Throws a USAGE error listing BOTH accepted forms for anything else.\n */\nexport function resolvePriority(raw: string): Priority {\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n throw priorityUsageError(raw);\n }\n\n const normalizedName = trimmed.toLowerCase();\n if (Object.prototype.hasOwnProperty.call(PRIORITY_NAME_TO_VALUE, normalizedName)) {\n return PRIORITY_NAME_TO_VALUE[normalizedName as keyof typeof PRIORITY_NAME_TO_VALUE];\n }\n\n // Numeric form: only exact integers 0..4 are valid. Number() would accept\n // forms like \"1.0\" or \" 2 \", but we already trimmed and require an integer\n // match so the contract stays tight.\n if (/^[0-4]$/.test(trimmed)) {\n return Number(trimmed) as Priority;\n }\n\n throw priorityUsageError(raw);\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAInD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACxE,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GACvC,yEAAyE;IACzE,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC;AAEzD,SAAS,kBAAkB,CAAC,GAAW;IACrC,OAAO,IAAI,UAAU,CACnB,qBAAqB,GAAG,uBAAuB,4BAA4B,GAAG,EAC9E,SAAS,CAAC,KAAK,CAChB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAC7C,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,sBAAsB,EAAE,cAAc,CAAC,EAAE,CAAC;QACjF,OAAO,sBAAsB,CAAC,cAAqD,CAAC,CAAC;IACvF,CAAC;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,qCAAqC;IACrC,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAa,CAAC;IACrC,CAAC;IAED,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC","debugId":"7535fe39-3a6e-5a1c-86ba-f1c7ca0b2407"}
1
+ {"version":3,"file":"priority.js","sources":["core/item/priority.ts"],"sourceRoot":"/","sourcesContent":["import { PmCliError } from \"../shared/errors.js\";\nimport { EXIT_CODE } from \"../shared/constants.js\";\n\nexport type Priority = 0 | 1 | 2 | 3 | 4;\n\n/**\n * Canonical mapping from named priority levels to numeric values. Agents and\n * humans frequently write words (\"high\") instead of numbers, so both create and\n * update accept either form. This single map is the source of truth so the two\n * commands cannot drift apart.\n */\nexport const PRIORITY_NAME_TO_VALUE: Readonly<Record<string, Priority>> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n minimal: 4,\n};\n\nconst PRIORITY_NAME_LIST = Object.keys(PRIORITY_NAME_TO_VALUE);\n\n/**\n * Human-readable description of every accepted priority form. Reused in error\n * messages so the wording stays consistent across commands.\n */\nexport const PRIORITY_ACCEPTED_FORMS_HINT =\n \"numbers 0..4 (0=critical, 1=high, 2=medium, 3=low, 4=minimal) or names \" +\n `(${PRIORITY_NAME_LIST.join(\", \")}), case-insensitive`;\n\nfunction priorityUsageError(raw: string): PmCliError {\n return new PmCliError(\n `Invalid priority \"${raw}\". Accepted values: ${PRIORITY_ACCEPTED_FORMS_HINT}.`,\n EXIT_CODE.USAGE,\n );\n}\n\n/**\n * Resolve a raw `--priority` option value to a numeric 0..4 priority.\n *\n * Accepts:\n * - numeric strings 0,1,2,3,4 (unchanged from prior behavior)\n * - named levels (critical/high/medium/low/minimal), case-insensitive\n * - native numbers 0..4 (arrives via MCP tool calls that JSON-encode priority as a number)\n *\n * Throws a USAGE error listing BOTH accepted forms for anything else.\n */\nexport function resolvePriority(raw: string | number): Priority {\n if (typeof raw === \"number\") {\n if (Number.isInteger(raw) && raw >= 0 && raw <= 4) {\n return raw as Priority;\n }\n throw priorityUsageError(String(raw));\n }\n if (typeof raw !== \"string\") {\n throw priorityUsageError(String(raw));\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n throw priorityUsageError(raw);\n }\n\n const normalizedName = trimmed.toLowerCase();\n if (Object.prototype.hasOwnProperty.call(PRIORITY_NAME_TO_VALUE, normalizedName)) {\n return PRIORITY_NAME_TO_VALUE[normalizedName as keyof typeof PRIORITY_NAME_TO_VALUE];\n }\n\n // Numeric form: only exact integers 0..4 are valid. Number() would accept\n // forms like \"1.0\" or \" 2 \", but we already trimmed and require an integer\n // match so the contract stays tight.\n if (/^[0-4]$/.test(trimmed)) {\n return Number(trimmed) as Priority;\n }\n\n throw priorityUsageError(raw);\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAInD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACxE,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GACvC,yEAAyE;IACzE,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC;AAEzD,SAAS,kBAAkB,CAAC,GAAW;IACrC,OAAO,IAAI,UAAU,CACnB,qBAAqB,GAAG,uBAAuB,4BAA4B,GAAG,EAC9E,SAAS,CAAC,KAAK,CAChB,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,GAAoB;IAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YAClD,OAAO,GAAe,CAAC;QACzB,CAAC;QACD,MAAM,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAC7C,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,sBAAsB,EAAE,cAAc,CAAC,EAAE,CAAC;QACjF,OAAO,sBAAsB,CAAC,cAAqD,CAAC,CAAC;IACvF,CAAC;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,qCAAqC;IACrC,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAa,CAAC;IACrC,CAAC;IAED,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC","debugId":"15a39edd-a843-51f1-8015-880a5071c43f"}
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="283a2497-5444-593a-97fa-aeb6fe2d61f4")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fdb3ffd3-61f6-55db-a926-a3fce76e815c")}catch(e){}}();
3
3
  import { executeSearchJsonRequest, normalizeSearchHttpTimeoutMs, resolveSearchHttpFetcher, } from "./http-client.js";
4
4
  import { isFiniteNumberArray, toNonEmptyString, trimTrailingSlashes, } from "../shared/primitives.js";
5
5
  function normalizeOpenAiEmbeddingsEndpoint(baseUrl) {
@@ -13,17 +13,27 @@ function normalizeOpenAiEmbeddingsEndpoint(baseUrl) {
13
13
  }
14
14
  return `${normalizedBaseUrl}/v1/embeddings`;
15
15
  }
16
+ function resolveSearchEmbeddingModelOverride(settings) {
17
+ // `settings.search.embedding_model` is documented as overriding the
18
+ // provider-specific model when set (see CONFIG_KEY_ALIASES for
19
+ // `search_embedding_model` in src/core/config/nested-settings.ts). Each
20
+ // provider resolver picks this up after its own model is read so the
21
+ // override applies to whichever built-in is selected.
22
+ const candidate = settings.search?.embedding_model;
23
+ return toNonEmptyString(candidate) || null;
24
+ }
16
25
  function resolveOpenAiProvider(settings) {
17
26
  const baseUrl = toNonEmptyString(settings.providers?.openai?.base_url);
18
27
  const model = toNonEmptyString(settings.providers?.openai?.model);
19
28
  if (!baseUrl || !model) {
20
29
  return null;
21
30
  }
31
+ const override = resolveSearchEmbeddingModelOverride(settings);
22
32
  const apiKey = toNonEmptyString(settings.providers?.openai?.api_key);
23
33
  return {
24
34
  name: "openai",
25
35
  base_url: baseUrl,
26
- model,
36
+ model: override ?? model,
27
37
  ...(apiKey ? { api_key: apiKey } : {}),
28
38
  };
29
39
  }
@@ -33,10 +43,11 @@ function resolveOllamaProvider(settings) {
33
43
  if (!baseUrl || !model) {
34
44
  return null;
35
45
  }
46
+ const override = resolveSearchEmbeddingModelOverride(settings);
36
47
  return {
37
48
  name: "ollama",
38
49
  base_url: baseUrl,
39
- model,
50
+ model: override ?? model,
40
51
  };
41
52
  }
42
53
  function normalizeEmbeddingInputs(input) {
@@ -95,8 +106,17 @@ export function resolveEmbeddingProviders(settings) {
95
106
  const openAi = resolveOpenAiProvider(settings);
96
107
  const ollama = resolveOllamaProvider(settings);
97
108
  const available = [openAi, ollama].filter((entry) => entry !== null);
109
+ // Honor `settings.search.provider` when set: if both built-in providers are
110
+ // configured, the preferred name wins; otherwise fall back to the first
111
+ // available entry (preserves the previous tie-break: openai > ollama).
112
+ // Match case-insensitively so "OpenAI" / "Ollama" / "OLLAMA" all work.
113
+ const preferredName = toNonEmptyString(settings.search?.provider);
114
+ const preferredKey = preferredName ? preferredName.toLowerCase() : null;
115
+ const preferred = preferredKey
116
+ ? available.find((entry) => entry.name === preferredKey)
117
+ : undefined;
98
118
  return {
99
- active: available[0] ?? null,
119
+ active: preferred ?? available[0] ?? null,
100
120
  available,
101
121
  };
102
122
  }
@@ -196,4 +216,4 @@ export async function executeEmbeddingRequest(provider, input, options = {}) {
196
216
  return dedupedInputs.originalToUniqueIndex.map((uniqueIndex) => [...vectors[uniqueIndex]]);
197
217
  }
198
218
  //# sourceMappingURL=providers.js.map
199
- //# debugId=283a2497-5444-593a-97fa-aeb6fe2d61f4
219
+ //# debugId=fdb3ffd3-61f6-55db-a926-a3fce76e815c
@@ -1 +1 @@
1
- {"version":3,"file":"providers.js","sources":["core/search/providers.ts"],"sourceRoot":"/","sourcesContent":["import type { PmSettings } from \"../../types/index.js\";\nimport {\n executeSearchJsonRequest,\n normalizeSearchHttpTimeoutMs,\n resolveSearchHttpFetcher,\n} from \"./http-client.js\";\nimport type { SearchHttpFetcher, SearchHttpResponse } from \"./http-client.js\";\nimport {\n isFiniteNumberArray,\n toNonEmptyString,\n trimTrailingSlashes,\n} from \"../shared/primitives.js\";\n\nexport type EmbeddingProviderName = \"openai\" | \"ollama\";\n\nexport interface EmbeddingProviderConfig {\n name: EmbeddingProviderName;\n base_url: string;\n model: string;\n api_key?: string;\n}\n\nexport interface EmbeddingProviderResolution {\n active: EmbeddingProviderConfig | null;\n available: EmbeddingProviderConfig[];\n}\n\nexport interface EmbeddingRequestTarget {\n provider: EmbeddingProviderName;\n endpoint: string;\n model: string;\n}\n\nexport interface EmbeddingRequestPlan {\n target: EmbeddingRequestTarget;\n method: \"POST\";\n headers: Record<string, string>;\n body: Record<string, unknown>;\n}\n\nexport type EmbeddingHttpResponse = SearchHttpResponse;\n\nexport type EmbeddingRequestFetcher = SearchHttpFetcher<EmbeddingHttpResponse>;\n\nexport interface ExecuteEmbeddingRequestOptions {\n timeout_ms?: number;\n fetcher?: EmbeddingRequestFetcher;\n}\n\ntype ProviderSettingsInput = {\n providers?: {\n openai?: {\n base_url?: string;\n api_key?: string;\n model?: string;\n };\n ollama?: {\n base_url?: string;\n model?: string;\n };\n };\n};\n\nfunction normalizeOpenAiEmbeddingsEndpoint(baseUrl: string): string {\n const normalizedBaseUrl = trimTrailingSlashes(baseUrl);\n const normalizedLower = normalizedBaseUrl.toLowerCase();\n if (normalizedLower.endsWith(\"/embeddings\")) {\n return normalizedBaseUrl;\n }\n if (normalizedLower.endsWith(\"/v1\")) {\n return `${normalizedBaseUrl}/embeddings`;\n }\n return `${normalizedBaseUrl}/v1/embeddings`;\n}\n\nfunction resolveOpenAiProvider(settings: ProviderSettingsInput): EmbeddingProviderConfig | null {\n const baseUrl = toNonEmptyString(settings.providers?.openai?.base_url);\n const model = toNonEmptyString(settings.providers?.openai?.model);\n if (!baseUrl || !model) {\n return null;\n }\n const apiKey = toNonEmptyString(settings.providers?.openai?.api_key);\n return {\n name: \"openai\",\n base_url: baseUrl,\n model,\n ...(apiKey ? { api_key: apiKey } : {}),\n };\n}\n\nfunction resolveOllamaProvider(settings: ProviderSettingsInput): EmbeddingProviderConfig | null {\n const baseUrl = toNonEmptyString(settings.providers?.ollama?.base_url);\n const model = toNonEmptyString(settings.providers?.ollama?.model);\n if (!baseUrl || !model) {\n return null;\n }\n return {\n name: \"ollama\",\n base_url: baseUrl,\n model,\n };\n}\n\nfunction normalizeEmbeddingInputs(input: string | string[]): string[] {\n const inputs = (Array.isArray(input) ? input : [input])\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (inputs.length === 0) {\n throw new Error(\"Embedding input must include at least one non-empty string\");\n }\n return inputs;\n}\n\ninterface DedupedEmbeddingInputs {\n uniqueInputs: string[];\n originalToUniqueIndex: number[];\n}\n\nfunction dedupeEmbeddingInputs(inputs: string[]): DedupedEmbeddingInputs {\n const uniqueInputs: string[] = [];\n const originalToUniqueIndex: number[] = [];\n const uniqueIndexByInput = new Map<string, number>();\n for (const entry of inputs) {\n const existingUniqueIndex = uniqueIndexByInput.get(entry);\n if (existingUniqueIndex === undefined) {\n const nextUniqueIndex = uniqueInputs.length;\n uniqueInputs.push(entry);\n uniqueIndexByInput.set(entry, nextUniqueIndex);\n originalToUniqueIndex.push(nextUniqueIndex);\n continue;\n }\n originalToUniqueIndex.push(existingUniqueIndex);\n }\n return {\n uniqueInputs,\n originalToUniqueIndex,\n };\n}\n\ninterface OpenAiEmbeddingResponseEntry {\n embedding: unknown;\n index: unknown;\n position: number;\n}\n\nfunction buildOrderedOpenAiEntries(data: unknown[]): OpenAiEmbeddingResponseEntry[] {\n const openAiEntries = data.map((entry, position) => ({\n embedding: (entry as { embedding?: unknown }).embedding,\n index: (entry as { index?: unknown }).index,\n position,\n }));\n const hasExplicitIndex = openAiEntries.some((entry) => entry.index !== undefined);\n if (hasExplicitIndex) {\n for (const entry of openAiEntries) {\n if (!Number.isInteger(entry.index)) {\n throw new TypeError(`OpenAI embedding response entry at position ${entry.position} is missing a valid integer index`);\n }\n }\n return [...openAiEntries].sort((a, b) => {\n const byIndex = (a.index as number) - (b.index as number);\n if (byIndex !== 0) {\n return byIndex;\n }\n return a.position - b.position;\n });\n }\n return openAiEntries;\n}\n\nexport function resolveEmbeddingProviders(settings: PmSettings | ProviderSettingsInput): EmbeddingProviderResolution {\n const openAi = resolveOpenAiProvider(settings);\n const ollama = resolveOllamaProvider(settings);\n const available = [openAi, ollama].filter((entry): entry is EmbeddingProviderConfig => entry !== null);\n return {\n active: available[0] ?? null,\n available,\n };\n}\n\nexport function resolveEmbeddingRequestTarget(provider: EmbeddingProviderConfig): EmbeddingRequestTarget {\n const baseUrl = trimTrailingSlashes(provider.base_url);\n if (provider.name === \"openai\") {\n return {\n provider: \"openai\",\n endpoint: normalizeOpenAiEmbeddingsEndpoint(baseUrl),\n model: provider.model,\n };\n }\n return {\n provider: \"ollama\",\n endpoint: `${baseUrl}/api/embed`,\n model: provider.model,\n };\n}\n\nexport function buildEmbeddingRequestPlan(provider: EmbeddingProviderConfig, input: string | string[]): EmbeddingRequestPlan {\n const normalizedInputs = normalizeEmbeddingInputs(input);\n if (provider.name === \"openai\") {\n return {\n target: resolveEmbeddingRequestTarget(provider),\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...(provider.api_key ? { authorization: `Bearer ${provider.api_key}` } : {}),\n },\n body: {\n model: provider.model,\n input: normalizedInputs.length === 1 ? normalizedInputs[0] : normalizedInputs,\n },\n };\n }\n return {\n target: resolveEmbeddingRequestTarget(provider),\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: {\n model: provider.model,\n input: normalizedInputs,\n },\n };\n}\n\nexport function normalizeEmbeddingResponse(provider: EmbeddingProviderConfig, response: unknown): number[][] {\n if (provider.name === \"openai\") {\n const data = (response as { data?: unknown }).data;\n if (!Array.isArray(data) || data.length === 0) {\n throw new Error(\"OpenAI embedding response must include a non-empty data array\");\n }\n const orderedEntries = buildOrderedOpenAiEntries(data);\n\n return orderedEntries.map((entry, index) => {\n const embedding = entry.embedding;\n if (!isFiniteNumberArray(embedding)) {\n throw new Error(`OpenAI embedding response entry at index ${index} is missing a numeric embedding vector`);\n }\n return [...embedding];\n });\n }\n\n const singleEmbedding = (response as { embedding?: unknown }).embedding;\n if (isFiniteNumberArray(singleEmbedding)) {\n return [[...singleEmbedding]];\n }\n\n const multipleEmbeddings = (response as { embeddings?: unknown }).embeddings;\n if (Array.isArray(multipleEmbeddings) && multipleEmbeddings.length > 0) {\n return multipleEmbeddings.map((entry, index) => {\n if (!isFiniteNumberArray(entry)) {\n throw new Error(`Ollama embedding response entry at index ${index} is missing a numeric embedding vector`);\n }\n return [...entry];\n });\n }\n\n throw new Error(\"Ollama embedding response must include embedding or embeddings vectors\");\n}\n\nexport async function executeEmbeddingRequest(\n provider: EmbeddingProviderConfig,\n input: string | string[],\n options: ExecuteEmbeddingRequestOptions = {},\n): Promise<number[][]> {\n const timeoutMs = normalizeSearchHttpTimeoutMs(options.timeout_ms, \"Embedding request\");\n const fetcher = resolveSearchHttpFetcher(options.fetcher, \"Embedding request\");\n const normalizedInputs = normalizeEmbeddingInputs(input);\n const dedupedInputs = dedupeEmbeddingInputs(normalizedInputs);\n const requestPlan = buildEmbeddingRequestPlan(provider, dedupedInputs.uniqueInputs);\n const payload = await executeSearchJsonRequest({\n endpoint: requestPlan.target.endpoint,\n method: requestPlan.method,\n headers: requestPlan.headers,\n body: requestPlan.body,\n timeoutMs,\n fetcher,\n requestLabel: \"Embedding request\",\n responseLabel: \"Embedding response\",\n });\n const vectors = normalizeEmbeddingResponse(provider, payload);\n if (vectors.length !== dedupedInputs.uniqueInputs.length) {\n throw new Error(\n `Embedding response cardinality mismatch: expected ${dedupedInputs.uniqueInputs.length} vector(s), received ${vectors.length}`,\n );\n }\n return dedupedInputs.originalToUniqueIndex.map((uniqueIndex) => [...vectors[uniqueIndex]]);\n}\n"],"names":[],"mappings":"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","debugId":"283a2497-5444-593a-97fa-aeb6fe2d61f4"}
1
+ {"version":3,"file":"providers.js","sources":["core/search/providers.ts"],"sourceRoot":"/","sourcesContent":["import type { PmSettings } from \"../../types/index.js\";\nimport {\n executeSearchJsonRequest,\n normalizeSearchHttpTimeoutMs,\n resolveSearchHttpFetcher,\n} from \"./http-client.js\";\nimport type { SearchHttpFetcher, SearchHttpResponse } from \"./http-client.js\";\nimport {\n isFiniteNumberArray,\n toNonEmptyString,\n trimTrailingSlashes,\n} from \"../shared/primitives.js\";\n\nexport type EmbeddingProviderName = \"openai\" | \"ollama\";\n\nexport interface EmbeddingProviderConfig {\n name: EmbeddingProviderName;\n base_url: string;\n model: string;\n api_key?: string;\n}\n\nexport interface EmbeddingProviderResolution {\n active: EmbeddingProviderConfig | null;\n available: EmbeddingProviderConfig[];\n}\n\nexport interface EmbeddingRequestTarget {\n provider: EmbeddingProviderName;\n endpoint: string;\n model: string;\n}\n\nexport interface EmbeddingRequestPlan {\n target: EmbeddingRequestTarget;\n method: \"POST\";\n headers: Record<string, string>;\n body: Record<string, unknown>;\n}\n\nexport type EmbeddingHttpResponse = SearchHttpResponse;\n\nexport type EmbeddingRequestFetcher = SearchHttpFetcher<EmbeddingHttpResponse>;\n\nexport interface ExecuteEmbeddingRequestOptions {\n timeout_ms?: number;\n fetcher?: EmbeddingRequestFetcher;\n}\n\ntype ProviderSettingsInput = {\n providers?: {\n openai?: {\n base_url?: string;\n api_key?: string;\n model?: string;\n };\n ollama?: {\n base_url?: string;\n model?: string;\n };\n };\n};\n\nfunction normalizeOpenAiEmbeddingsEndpoint(baseUrl: string): string {\n const normalizedBaseUrl = trimTrailingSlashes(baseUrl);\n const normalizedLower = normalizedBaseUrl.toLowerCase();\n if (normalizedLower.endsWith(\"/embeddings\")) {\n return normalizedBaseUrl;\n }\n if (normalizedLower.endsWith(\"/v1\")) {\n return `${normalizedBaseUrl}/embeddings`;\n }\n return `${normalizedBaseUrl}/v1/embeddings`;\n}\n\nfunction resolveSearchEmbeddingModelOverride(settings: ProviderSettingsInput): string | null {\n // `settings.search.embedding_model` is documented as overriding the\n // provider-specific model when set (see CONFIG_KEY_ALIASES for\n // `search_embedding_model` in src/core/config/nested-settings.ts). Each\n // provider resolver picks this up after its own model is read so the\n // override applies to whichever built-in is selected.\n const candidate = (settings as { search?: { embedding_model?: unknown } }).search?.embedding_model;\n return toNonEmptyString(candidate) || null;\n}\n\nfunction resolveOpenAiProvider(settings: ProviderSettingsInput): EmbeddingProviderConfig | null {\n const baseUrl = toNonEmptyString(settings.providers?.openai?.base_url);\n const model = toNonEmptyString(settings.providers?.openai?.model);\n if (!baseUrl || !model) {\n return null;\n }\n const override = resolveSearchEmbeddingModelOverride(settings);\n const apiKey = toNonEmptyString(settings.providers?.openai?.api_key);\n return {\n name: \"openai\",\n base_url: baseUrl,\n model: override ?? model,\n ...(apiKey ? { api_key: apiKey } : {}),\n };\n}\n\nfunction resolveOllamaProvider(settings: ProviderSettingsInput): EmbeddingProviderConfig | null {\n const baseUrl = toNonEmptyString(settings.providers?.ollama?.base_url);\n const model = toNonEmptyString(settings.providers?.ollama?.model);\n if (!baseUrl || !model) {\n return null;\n }\n const override = resolveSearchEmbeddingModelOverride(settings);\n return {\n name: \"ollama\",\n base_url: baseUrl,\n model: override ?? model,\n };\n}\n\nfunction normalizeEmbeddingInputs(input: string | string[]): string[] {\n const inputs = (Array.isArray(input) ? input : [input])\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (inputs.length === 0) {\n throw new Error(\"Embedding input must include at least one non-empty string\");\n }\n return inputs;\n}\n\ninterface DedupedEmbeddingInputs {\n uniqueInputs: string[];\n originalToUniqueIndex: number[];\n}\n\nfunction dedupeEmbeddingInputs(inputs: string[]): DedupedEmbeddingInputs {\n const uniqueInputs: string[] = [];\n const originalToUniqueIndex: number[] = [];\n const uniqueIndexByInput = new Map<string, number>();\n for (const entry of inputs) {\n const existingUniqueIndex = uniqueIndexByInput.get(entry);\n if (existingUniqueIndex === undefined) {\n const nextUniqueIndex = uniqueInputs.length;\n uniqueInputs.push(entry);\n uniqueIndexByInput.set(entry, nextUniqueIndex);\n originalToUniqueIndex.push(nextUniqueIndex);\n continue;\n }\n originalToUniqueIndex.push(existingUniqueIndex);\n }\n return {\n uniqueInputs,\n originalToUniqueIndex,\n };\n}\n\ninterface OpenAiEmbeddingResponseEntry {\n embedding: unknown;\n index: unknown;\n position: number;\n}\n\nfunction buildOrderedOpenAiEntries(data: unknown[]): OpenAiEmbeddingResponseEntry[] {\n const openAiEntries = data.map((entry, position) => ({\n embedding: (entry as { embedding?: unknown }).embedding,\n index: (entry as { index?: unknown }).index,\n position,\n }));\n const hasExplicitIndex = openAiEntries.some((entry) => entry.index !== undefined);\n if (hasExplicitIndex) {\n for (const entry of openAiEntries) {\n if (!Number.isInteger(entry.index)) {\n throw new TypeError(`OpenAI embedding response entry at position ${entry.position} is missing a valid integer index`);\n }\n }\n return [...openAiEntries].sort((a, b) => {\n const byIndex = (a.index as number) - (b.index as number);\n if (byIndex !== 0) {\n return byIndex;\n }\n return a.position - b.position;\n });\n }\n return openAiEntries;\n}\n\nexport function resolveEmbeddingProviders(settings: PmSettings | ProviderSettingsInput): EmbeddingProviderResolution {\n const openAi = resolveOpenAiProvider(settings);\n const ollama = resolveOllamaProvider(settings);\n const available = [openAi, ollama].filter((entry): entry is EmbeddingProviderConfig => entry !== null);\n // Honor `settings.search.provider` when set: if both built-in providers are\n // configured, the preferred name wins; otherwise fall back to the first\n // available entry (preserves the previous tie-break: openai > ollama).\n // Match case-insensitively so \"OpenAI\" / \"Ollama\" / \"OLLAMA\" all work.\n const preferredName = toNonEmptyString(\n (settings as { search?: { provider?: unknown } }).search?.provider,\n );\n const preferredKey = preferredName ? preferredName.toLowerCase() : null;\n const preferred = preferredKey\n ? available.find((entry) => entry.name === preferredKey)\n : undefined;\n return {\n active: preferred ?? available[0] ?? null,\n available,\n };\n}\n\nexport function resolveEmbeddingRequestTarget(provider: EmbeddingProviderConfig): EmbeddingRequestTarget {\n const baseUrl = trimTrailingSlashes(provider.base_url);\n if (provider.name === \"openai\") {\n return {\n provider: \"openai\",\n endpoint: normalizeOpenAiEmbeddingsEndpoint(baseUrl),\n model: provider.model,\n };\n }\n return {\n provider: \"ollama\",\n endpoint: `${baseUrl}/api/embed`,\n model: provider.model,\n };\n}\n\nexport function buildEmbeddingRequestPlan(provider: EmbeddingProviderConfig, input: string | string[]): EmbeddingRequestPlan {\n const normalizedInputs = normalizeEmbeddingInputs(input);\n if (provider.name === \"openai\") {\n return {\n target: resolveEmbeddingRequestTarget(provider),\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...(provider.api_key ? { authorization: `Bearer ${provider.api_key}` } : {}),\n },\n body: {\n model: provider.model,\n input: normalizedInputs.length === 1 ? normalizedInputs[0] : normalizedInputs,\n },\n };\n }\n return {\n target: resolveEmbeddingRequestTarget(provider),\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: {\n model: provider.model,\n input: normalizedInputs,\n },\n };\n}\n\nexport function normalizeEmbeddingResponse(provider: EmbeddingProviderConfig, response: unknown): number[][] {\n if (provider.name === \"openai\") {\n const data = (response as { data?: unknown }).data;\n if (!Array.isArray(data) || data.length === 0) {\n throw new Error(\"OpenAI embedding response must include a non-empty data array\");\n }\n const orderedEntries = buildOrderedOpenAiEntries(data);\n\n return orderedEntries.map((entry, index) => {\n const embedding = entry.embedding;\n if (!isFiniteNumberArray(embedding)) {\n throw new Error(`OpenAI embedding response entry at index ${index} is missing a numeric embedding vector`);\n }\n return [...embedding];\n });\n }\n\n const singleEmbedding = (response as { embedding?: unknown }).embedding;\n if (isFiniteNumberArray(singleEmbedding)) {\n return [[...singleEmbedding]];\n }\n\n const multipleEmbeddings = (response as { embeddings?: unknown }).embeddings;\n if (Array.isArray(multipleEmbeddings) && multipleEmbeddings.length > 0) {\n return multipleEmbeddings.map((entry, index) => {\n if (!isFiniteNumberArray(entry)) {\n throw new Error(`Ollama embedding response entry at index ${index} is missing a numeric embedding vector`);\n }\n return [...entry];\n });\n }\n\n throw new Error(\"Ollama embedding response must include embedding or embeddings vectors\");\n}\n\nexport async function executeEmbeddingRequest(\n provider: EmbeddingProviderConfig,\n input: string | string[],\n options: ExecuteEmbeddingRequestOptions = {},\n): Promise<number[][]> {\n const timeoutMs = normalizeSearchHttpTimeoutMs(options.timeout_ms, \"Embedding request\");\n const fetcher = resolveSearchHttpFetcher(options.fetcher, \"Embedding request\");\n const normalizedInputs = normalizeEmbeddingInputs(input);\n const dedupedInputs = dedupeEmbeddingInputs(normalizedInputs);\n const requestPlan = buildEmbeddingRequestPlan(provider, dedupedInputs.uniqueInputs);\n const payload = await executeSearchJsonRequest({\n endpoint: requestPlan.target.endpoint,\n method: requestPlan.method,\n headers: requestPlan.headers,\n body: requestPlan.body,\n timeoutMs,\n fetcher,\n requestLabel: \"Embedding request\",\n responseLabel: \"Embedding response\",\n });\n const vectors = normalizeEmbeddingResponse(provider, payload);\n if (vectors.length !== dedupedInputs.uniqueInputs.length) {\n throw new Error(\n `Embedding response cardinality mismatch: expected ${dedupedInputs.uniqueInputs.length} vector(s), received ${vectors.length}`,\n );\n }\n return dedupedInputs.originalToUniqueIndex.map((uniqueIndex) => [...vectors[uniqueIndex]]);\n}\n"],"names":[],"mappings":"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","debugId":"fdb3ffd3-61f6-55db-a926-a3fce76e815c"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Vectorization-ledger staleness helpers.
3
+ *
4
+ * The vectorization status ledger at `search/vectorization-status.json`
5
+ * records the `updated_at` of every item that has been embedded into the
6
+ * vector store. When an item's current `updated_at` differs from the
7
+ * ledger's recorded value (or the item is missing from the ledger
8
+ * entirely), the vector store is stale for that item and a `pm reindex`
9
+ * is needed.
10
+ *
11
+ * This module exposes the comparison helper as a tiny pure function so it
12
+ * can be reused by `pm health` (gates), `pm reindex`, and `pm search`
13
+ * (query-time staleness warning) without re-importing each other.
14
+ */
15
+ export interface ItemWithUpdatedAt {
16
+ id: string;
17
+ updated_at: string;
18
+ }
19
+ /**
20
+ * Return the sorted list of item IDs whose current `updated_at` does not
21
+ * match the ledger entry. Missing ledger entries count as stale.
22
+ */
23
+ export declare function collectStaleVectorizationIds<T extends ItemWithUpdatedAt>(items: readonly T[], ledgerEntries: Readonly<Record<string, string>> | null | undefined): string[];
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Vectorization-ledger staleness helpers.
3
+ *
4
+ * The vectorization status ledger at `search/vectorization-status.json`
5
+ * records the `updated_at` of every item that has been embedded into the
6
+ * vector store. When an item's current `updated_at` differs from the
7
+ * ledger's recorded value (or the item is missing from the ledger
8
+ * entirely), the vector store is stale for that item and a `pm reindex`
9
+ * is needed.
10
+ *
11
+ * This module exposes the comparison helper as a tiny pure function so it
12
+ * can be reused by `pm health` (gates), `pm reindex`, and `pm search`
13
+ * (query-time staleness warning) without re-importing each other.
14
+ */
15
+ /**
16
+ * Return the sorted list of item IDs whose current `updated_at` does not
17
+ * match the ledger entry. Missing ledger entries count as stale.
18
+ */
19
+
20
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5dd8a7df-7ce7-5fed-a22d-f64e288ba34c")}catch(e){}}();
21
+ export function collectStaleVectorizationIds(items, ledgerEntries) {
22
+ // Tolerate a missing / corrupted / partially-written ledger by treating
23
+ // unknown items as stale (the same as having no entry).
24
+ const entries = ledgerEntries ?? {};
25
+ return items
26
+ .filter((item) => {
27
+ const trackedUpdatedAt = entries[item.id];
28
+ return trackedUpdatedAt !== item.updated_at;
29
+ })
30
+ .map((item) => item.id)
31
+ .sort((left, right) => left.localeCompare(right));
32
+ }
33
+ //# sourceMappingURL=staleness.js.map
34
+ //# debugId=5dd8a7df-7ce7-5fed-a22d-f64e288ba34c
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staleness.js","sources":["core/search/staleness.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Vectorization-ledger staleness helpers.\n *\n * The vectorization status ledger at `search/vectorization-status.json`\n * records the `updated_at` of every item that has been embedded into the\n * vector store. When an item's current `updated_at` differs from the\n * ledger's recorded value (or the item is missing from the ledger\n * entirely), the vector store is stale for that item and a `pm reindex`\n * is needed.\n *\n * This module exposes the comparison helper as a tiny pure function so it\n * can be reused by `pm health` (gates), `pm reindex`, and `pm search`\n * (query-time staleness warning) without re-importing each other.\n */\n\nexport interface ItemWithUpdatedAt {\n id: string;\n updated_at: string;\n}\n\n/**\n * Return the sorted list of item IDs whose current `updated_at` does not\n * match the ledger entry. Missing ledger entries count as stale.\n */\nexport function collectStaleVectorizationIds<T extends ItemWithUpdatedAt>(\n items: readonly T[],\n ledgerEntries: Readonly<Record<string, string>> | null | undefined,\n): string[] {\n // Tolerate a missing / corrupted / partially-written ledger by treating\n // unknown items as stale (the same as having no entry).\n const entries = ledgerEntries ?? {};\n return items\n .filter((item) => {\n const trackedUpdatedAt = entries[item.id];\n return trackedUpdatedAt !== item.updated_at;\n })\n .map((item) => item.id)\n .sort((left, right) => left.localeCompare(right));\n}\n"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH;;;GAGG;;;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAAmB,EACnB,aAAkE;IAElE,wEAAwE;IACxE,wDAAwD;IACxD,MAAM,OAAO,GAAG,aAAa,IAAI,EAAE,CAAC;IACpC,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QACf,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1C,OAAO,gBAAgB,KAAK,IAAI,CAAC,UAAU,CAAC;IAC9C,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;SACtB,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AACtD,CAAC","debugId":"5dd8a7df-7ce7-5fed-a22d-f64e288ba34c"}
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7e81fcbb-b493-5774-862f-30107a96e0ce")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1fc8fa51-3aee-5a13-b07a-4b6a91b781ba")}catch(e){}}();
3
3
  import { mkdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
4
4
  import { basename, dirname, join, resolve } from "node:path";
5
5
  import { executeSearchJsonRequest, normalizeSearchHttpTimeoutMs, resolveSearchHttpFetcher, } from "./http-client.js";
@@ -318,8 +318,17 @@ export function resolveVectorStores(settings) {
318
318
  const qdrant = resolveQdrantStore(settings);
319
319
  const lancedb = resolveLanceDbStore(settings);
320
320
  const available = [qdrant, lancedb].filter((entry) => entry !== null);
321
+ // Honor `settings.vector_store.adapter` when set: if both built-in stores
322
+ // are configured, the preferred adapter wins; otherwise fall back to the
323
+ // first available entry (preserves the previous tie-break: qdrant > lancedb).
324
+ // Match case-insensitively so "Qdrant" / "LanceDB" / "lancedb" all work.
325
+ const preferredName = toNonEmptyString(settings.vector_store?.adapter);
326
+ const preferredKey = preferredName ? preferredName.toLowerCase() : null;
327
+ const preferred = preferredKey
328
+ ? available.find((entry) => entry.name === preferredKey)
329
+ : undefined;
321
330
  return {
322
- active: available[0] ?? null,
331
+ active: preferred ?? available[0] ?? null,
323
332
  available,
324
333
  };
325
334
  }
@@ -532,4 +541,4 @@ export async function executeVectorDelete(store, ids, options = {}) {
532
541
  return normalizeQdrantUpsertResponse(payload);
533
542
  }
534
543
  //# sourceMappingURL=vector-stores.js.map
535
- //# debugId=7e81fcbb-b493-5774-862f-30107a96e0ce
544
+ //# debugId=1fc8fa51-3aee-5a13-b07a-4b6a91b781ba