@kubbisec/ai-linux-x64 0.1.22 → 0.1.23

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 (109) hide show
  1. package/bin/kubbisec +0 -0
  2. package/bundled/components/kubbisec-model-selector.d.ts +47 -34
  3. package/bundled/components/kubbisec-model-selector.js +187 -177
  4. package/bundled/config/config.d.ts +6 -6
  5. package/bundled/config/config.js +54 -52
  6. package/bundled/config/detect-local-llm-providers.d.ts +26 -16
  7. package/bundled/config/detect-local-llm-providers.js +130 -142
  8. package/bundled/config/ensure-kbs-project-settings.d.ts +8 -8
  9. package/bundled/config/ensure-kbs-project-settings.js +27 -28
  10. package/bundled/config/ensure-kubbisec-project-settings.d.ts +9 -9
  11. package/bundled/config/ensure-kubbisec-project-settings.js +62 -67
  12. package/bundled/config/extended-context.d.ts +5 -6
  13. package/bundled/config/extended-context.js +23 -22
  14. package/bundled/config/feature-flags.d.ts +10 -2
  15. package/bundled/config/feature-flags.js +8 -2
  16. package/bundled/config/format-kubbisec-footer-status.d.ts +1 -1
  17. package/bundled/config/format-kubbisec-footer-status.js +26 -31
  18. package/bundled/config/kubbisec-extension-manifest.d.ts +21 -2
  19. package/bundled/config/kubbisec-extension-manifest.js +19 -19
  20. package/bundled/config/llm-config-mutations.d.ts +51 -25
  21. package/bundled/config/llm-config-mutations.js +173 -182
  22. package/bundled/config/llm-config.d.ts +54 -41
  23. package/bundled/config/llm-config.js +199 -199
  24. package/bundled/config/llm-provider-catalog.d.ts +18 -15
  25. package/bundled/config/llm-provider-catalog.js +45 -46
  26. package/bundled/config/materialize-kubbisec-pi-resources.d.ts +1 -1
  27. package/bundled/config/materialize-kubbisec-pi-resources.js +173 -182
  28. package/bundled/config/register-custom-llm-providers.d.ts +11 -5
  29. package/bundled/config/register-custom-llm-providers.js +17 -15
  30. package/bundled/config/register-kubbisec-llm-provider.d.ts +14 -10
  31. package/bundled/config/register-kubbisec-llm-provider.js +50 -42
  32. package/bundled/config/resolve-agents-context-file.d.ts +1 -1
  33. package/bundled/config/resolve-agents-context-file.js +33 -34
  34. package/bundled/config/resource-budget.d.ts +12 -12
  35. package/bundled/config/resource-budget.js +28 -28
  36. package/bundled/config/sync-kubbisec-pi-models.d.ts +6 -3
  37. package/bundled/config/sync-kubbisec-pi-models.js +58 -58
  38. package/bundled/copy/cli-reference-index.d.ts +1 -1
  39. package/bundled/copy/cli-reference-index.js +1 -1
  40. package/bundled/copy/kubbisec-shell-copy.d.ts +11 -6
  41. package/bundled/copy/kubbisec-shell-copy.js +1 -1
  42. package/bundled/extensions/cli-local-shared.d.ts +56 -32
  43. package/bundled/extensions/cli-local-shared.js +135 -125
  44. package/bundled/extensions/kubbisec-aspm-local.extension.d.ts +18 -15
  45. package/bundled/extensions/kubbisec-aspm-local.extension.js +109 -106
  46. package/bundled/extensions/kubbisec-brand.extension.d.ts +1 -1
  47. package/bundled/extensions/kubbisec-brand.extension.js +25 -25
  48. package/bundled/extensions/kubbisec-byok-provider.extension.d.ts +1 -1
  49. package/bundled/extensions/kubbisec-byok-provider.extension.js +2 -2
  50. package/bundled/extensions/kubbisec-clarify.extension.d.ts +64 -35
  51. package/bundled/extensions/kubbisec-clarify.extension.js +323 -305
  52. package/bundled/extensions/kubbisec-exit.extension.d.ts +1 -1
  53. package/bundled/extensions/kubbisec-exit.extension.js +29 -32
  54. package/bundled/extensions/kubbisec-extended-context.extension.d.ts +1 -1
  55. package/bundled/extensions/kubbisec-extended-context.extension.js +56 -43
  56. package/bundled/extensions/kubbisec-footer.extension.d.ts +14 -14
  57. package/bundled/extensions/kubbisec-footer.extension.js +205 -215
  58. package/bundled/extensions/kubbisec-github-local.extension.d.ts +26 -18
  59. package/bundled/extensions/kubbisec-github-local.extension.js +430 -417
  60. package/bundled/extensions/kubbisec-llm-config.extension.d.ts +1 -1
  61. package/bundled/extensions/kubbisec-llm-config.extension.js +200 -181
  62. package/bundled/extensions/kubbisec-memory.extension.d.ts +9 -7
  63. package/bundled/extensions/kubbisec-memory.extension.js +88 -95
  64. package/bundled/extensions/kubbisec-naus-local.extension.d.ts +18 -15
  65. package/bundled/extensions/kubbisec-naus-local.extension.js +123 -103
  66. package/bundled/extensions/kubbisec-platform-tools.extension.d.ts +31 -21
  67. package/bundled/extensions/kubbisec-platform-tools.extension.js +152 -152
  68. package/bundled/extensions/kubbisec-runtime-status.extension.d.ts +10 -8
  69. package/bundled/extensions/kubbisec-runtime-status.extension.js +15 -13
  70. package/bundled/extensions/kubbisec-scope.extension.d.ts +12 -7
  71. package/bundled/extensions/kubbisec-scope.extension.js +13 -13
  72. package/bundled/extensions/kubbisec-skill-mentions.extension.d.ts +27 -16
  73. package/bundled/extensions/kubbisec-skill-mentions.extension.js +74 -64
  74. package/bundled/extensions/kubbisec-skill-telemetry.extension.d.ts +2 -3
  75. package/bundled/extensions/kubbisec-skill-telemetry.extension.js +59 -64
  76. package/bundled/extensions/kubbisec-theme-lock.extension.d.ts +1 -1
  77. package/bundled/extensions/kubbisec-theme-lock.extension.js +33 -34
  78. package/bundled/extensions/kubbisec-ui.extension.d.ts +1 -1
  79. package/bundled/extensions/kubbisec-ui.extension.js +90 -92
  80. package/bundled/extensions/kubbisec-workflow.extension.d.ts +20 -18
  81. package/bundled/extensions/kubbisec-workflow.extension.js +138 -140
  82. package/bundled/resolve-bundled-dist-root.js +121 -130
  83. package/bundled/skills/at-path-mentions.d.ts +1 -1
  84. package/bundled/skills/at-path-mentions.js +146 -153
  85. package/bundled/skills/chat-mention-render.d.ts +2 -2
  86. package/bundled/skills/chat-mention-render.js +121 -126
  87. package/bundled/skills/chat-mentions.d.ts +17 -8
  88. package/bundled/skills/chat-mentions.js +76 -76
  89. package/bundled/skills/list-bundled-skills.d.ts +3 -3
  90. package/bundled/skills/list-bundled-skills.js +33 -35
  91. package/bundled/skills/skill-mention.d.ts +10 -2
  92. package/bundled/skills/skill-mention.js +10 -2
  93. package/bundled/theme/clear-terminal.d.ts +1 -1
  94. package/bundled/theme/clear-terminal.js +3 -4
  95. package/bundled/theme/footer-render-hook.d.ts +1 -1
  96. package/bundled/theme/footer-render-hook.js +3 -3
  97. package/bundled/theme/kubbisec-brand-fg.d.ts +1 -1
  98. package/bundled/theme/kubbisec-brand-fg.js +2 -2
  99. package/bundled/theme/kubbisec-menu-themes.d.ts +7 -7
  100. package/bundled/theme/kubbisec-menu-themes.js +30 -31
  101. package/bundled/theme/kubbisec-theme-name.d.ts +1 -1
  102. package/bundled/theme/kubbisec-theme-name.js +1 -1
  103. package/bundled/theme/patch-pi-settings-theme.runtime.d.ts +1 -1
  104. package/bundled/theme/patch-pi-settings-theme.runtime.js +11 -10
  105. package/bundled/theme/render-compact-header.d.ts +13 -5
  106. package/bundled/theme/render-compact-header.js +126 -128
  107. package/bundled/workflow/session-workflow-mode.d.ts +1 -1
  108. package/bundled/workflow/session-workflow-mode.js +33 -33
  109. package/package.json +1 -1
@@ -1,184 +1,177 @@
1
1
  import { readdirSync, statSync } from "node:fs";
2
2
  import { basename, dirname, join, relative } from "node:path";
3
- import { extractAtPrefix, parsePlanMentionPrefix, parseSkillMentionPrefix, } from "./chat-mentions.js";
3
+ import {
4
+ extractAtPrefix,
5
+ parsePlanMentionPrefix,
6
+ parseSkillMentionPrefix,
7
+ } from "./chat-mentions.js";
8
+
4
9
  function toDisplayPath(value) {
5
- return value.replace(/\\/g, "/");
10
+ return value.replace(/\\/g, "/");
6
11
  }
7
12
  function parsePathPrefix(prefix) {
8
- if (prefix.startsWith('@"')) {
9
- return { rawPrefix: prefix.slice(2), isAtPrefix: true, isQuotedPrefix: true };
10
- }
11
- if (prefix.startsWith('"')) {
12
- return { rawPrefix: prefix.slice(1), isAtPrefix: false, isQuotedPrefix: true };
13
- }
14
- if (prefix.startsWith("@")) {
15
- return { rawPrefix: prefix.slice(1), isAtPrefix: true, isQuotedPrefix: false };
16
- }
17
- return { rawPrefix: prefix, isAtPrefix: false, isQuotedPrefix: false };
13
+ if (prefix.startsWith('@"')) {
14
+ return { rawPrefix: prefix.slice(2), isAtPrefix: true, isQuotedPrefix: true };
15
+ }
16
+ if (prefix.startsWith('"')) {
17
+ return { rawPrefix: prefix.slice(1), isAtPrefix: false, isQuotedPrefix: true };
18
+ }
19
+ if (prefix.startsWith("@")) {
20
+ return { rawPrefix: prefix.slice(1), isAtPrefix: true, isQuotedPrefix: false };
21
+ }
22
+ return { rawPrefix: prefix, isAtPrefix: false, isQuotedPrefix: false };
18
23
  }
19
24
  function buildCompletionValue(path, options) {
20
- const needsQuotes = options.isQuotedPrefix || path.includes(" ");
21
- const prefix = options.isAtPrefix ? "@" : "";
22
- if (!needsQuotes) {
23
- return `${prefix}${path}`;
24
- }
25
- const openQuote = `${prefix}"`;
26
- return `${openQuote}${path}"`;
25
+ const needsQuotes = options.isQuotedPrefix || path.includes(" ");
26
+ const prefix = options.isAtPrefix ? "@" : "";
27
+ if (!needsQuotes) {
28
+ return `${prefix}${path}`;
29
+ }
30
+ const openQuote = `${prefix}"`;
31
+ return `${openQuote}${path}"`;
27
32
  }
28
33
  const DEPRIORITIZED_AT_PATH_NAMES = new Set([
29
- "node_modules",
30
- "dist",
31
- "dist-bin",
32
- ".turbo",
33
- ".git",
34
- "coverage",
35
- "build",
36
- ".next",
37
- ".cache",
38
- "tmp",
39
- ".venv",
40
- "target",
34
+ "node_modules",
35
+ "dist",
36
+ "dist-bin",
37
+ ".turbo",
38
+ ".git",
39
+ "coverage",
40
+ "build",
41
+ ".next",
42
+ ".cache",
43
+ "tmp",
44
+ ".venv",
45
+ "target",
41
46
  ]);
42
47
  const PRIORITY_AT_PATH_DIRS = [
43
- "src",
44
- "lib",
45
- "apps",
46
- "packages",
47
- "scripts",
48
- "test",
49
- "tests",
50
- "docs",
51
- "spec",
48
+ "src",
49
+ "lib",
50
+ "apps",
51
+ "packages",
52
+ "scripts",
53
+ "test",
54
+ "tests",
55
+ "docs",
56
+ "spec",
52
57
  ];
53
58
  const PRIORITY_AT_PATH_FILES = [
54
- "package.json",
55
- "README.md",
56
- "readme.md",
57
- "tsconfig.json",
58
- "vitest.config.ts",
59
- "Cargo.toml",
60
- "go.mod",
61
- "pyproject.toml",
62
- "Makefile",
59
+ "package.json",
60
+ "README.md",
61
+ "readme.md",
62
+ "tsconfig.json",
63
+ "vitest.config.ts",
64
+ "Cargo.toml",
65
+ "go.mod",
66
+ "pyproject.toml",
67
+ "Makefile",
63
68
  ];
64
69
  function atPathSuggestionRank(label) {
65
- const name = label.replace(/\/$/, "");
66
- if (PRIORITY_AT_PATH_DIRS.includes(name) ||
67
- PRIORITY_AT_PATH_FILES.includes(name)) {
68
- return 0;
69
- }
70
- if (DEPRIORITIZED_AT_PATH_NAMES.has(name)) {
71
- return 3;
72
- }
73
- if (label.endsWith("/")) {
74
- return 1;
75
- }
76
- return 2;
70
+ const name = label.replace(/\/$/, "");
71
+ if (PRIORITY_AT_PATH_DIRS.includes(name) || PRIORITY_AT_PATH_FILES.includes(name)) {
72
+ return 0;
73
+ }
74
+ if (DEPRIORITIZED_AT_PATH_NAMES.has(name)) {
75
+ return 3;
76
+ }
77
+ if (label.endsWith("/")) {
78
+ return 1;
79
+ }
80
+ return 2;
77
81
  }
78
82
  function sortAtPathSuggestions(items, rawPrefix) {
79
- if (rawPrefix !== "") {
80
- return items.sort((a, b) => {
81
- const aIsDir = a.label.endsWith("/");
82
- const bIsDir = b.label.endsWith("/");
83
- if (aIsDir && !bIsDir)
84
- return -1;
85
- if (!aIsDir && bIsDir)
86
- return 1;
87
- return a.label.localeCompare(b.label);
88
- });
89
- }
83
+ if (rawPrefix !== "") {
90
84
  return items.sort((a, b) => {
91
- const rankDiff = atPathSuggestionRank(a.label) - atPathSuggestionRank(b.label);
92
- if (rankDiff !== 0)
93
- return rankDiff;
94
- return a.label.localeCompare(b.label);
85
+ const aIsDir = a.label.endsWith("/");
86
+ const bIsDir = b.label.endsWith("/");
87
+ if (aIsDir && !bIsDir) return -1;
88
+ if (!aIsDir && bIsDir) return 1;
89
+ return a.label.localeCompare(b.label);
95
90
  });
91
+ }
92
+ return items.sort((a, b) => {
93
+ const rankDiff = atPathSuggestionRank(a.label) - atPathSuggestionRank(b.label);
94
+ if (rankDiff !== 0) return rankDiff;
95
+ return a.label.localeCompare(b.label);
96
+ });
96
97
  }
97
98
  /** `@` file attachment (not `@skill` / `@plan`). */
98
99
  export function isAtFileAttachmentPrefix(atPrefix) {
99
- if (!atPrefix)
100
- return false;
101
- if (parseSkillMentionPrefix(atPrefix))
102
- return false;
103
- if (parsePlanMentionPrefix(atPrefix))
104
- return false;
105
- return atPrefix.startsWith("@");
100
+ if (!atPrefix) return false;
101
+ if (parseSkillMentionPrefix(atPrefix)) return false;
102
+ if (parsePlanMentionPrefix(atPrefix)) return false;
103
+ return atPrefix.startsWith("@");
106
104
  }
107
105
  /** List cwd-scoped entries for `@` / `@path` (Pi getFileSuggestions semantics). */
108
106
  export function getAtPathFileSuggestions(cwd, atPrefix) {
109
- try {
110
- const { rawPrefix, isAtPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);
111
- if (!isAtPrefix)
112
- return [];
113
- let searchDir;
114
- let searchPrefix;
115
- const expandedPrefix = rawPrefix;
116
- const isRootPrefix = rawPrefix === "" ||
117
- rawPrefix === "./" ||
118
- rawPrefix === "../" ||
119
- rawPrefix === "/" ||
120
- (isAtPrefix && rawPrefix === "");
121
- if (isRootPrefix) {
122
- searchDir = join(cwd, expandedPrefix);
123
- searchPrefix = "";
124
- }
125
- else if (rawPrefix.endsWith("/")) {
126
- searchDir = join(cwd, expandedPrefix);
127
- searchPrefix = "";
128
- }
129
- else {
130
- searchDir = join(cwd, dirname(expandedPrefix));
131
- searchPrefix = basename(expandedPrefix);
107
+ try {
108
+ const { rawPrefix, isAtPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);
109
+ if (!isAtPrefix) return [];
110
+ let searchDir;
111
+ let searchPrefix;
112
+ const expandedPrefix = rawPrefix;
113
+ const isRootPrefix =
114
+ rawPrefix === "" ||
115
+ rawPrefix === "./" ||
116
+ rawPrefix === "../" ||
117
+ rawPrefix === "/" ||
118
+ (isAtPrefix && rawPrefix === "");
119
+ if (isRootPrefix) {
120
+ searchDir = join(cwd, expandedPrefix);
121
+ searchPrefix = "";
122
+ } else if (rawPrefix.endsWith("/")) {
123
+ searchDir = join(cwd, expandedPrefix);
124
+ searchPrefix = "";
125
+ } else {
126
+ searchDir = join(cwd, dirname(expandedPrefix));
127
+ searchPrefix = basename(expandedPrefix);
128
+ }
129
+ const entries = readdirSync(searchDir, { withFileTypes: true });
130
+ const suggestions = [];
131
+ const cwdLabel = toDisplayPath(relative(cwd, searchDir) || ".");
132
+ for (const entry of entries) {
133
+ if (!entry.name.toLowerCase().startsWith(searchPrefix.toLowerCase())) {
134
+ continue;
135
+ }
136
+ let isDirectory = entry.isDirectory();
137
+ if (!isDirectory && entry.isSymbolicLink()) {
138
+ try {
139
+ isDirectory = statSync(join(searchDir, entry.name)).isDirectory();
140
+ } catch {
141
+ // broken symlink — treat as file
132
142
  }
133
- const entries = readdirSync(searchDir, { withFileTypes: true });
134
- const suggestions = [];
135
- const cwdLabel = toDisplayPath(relative(cwd, searchDir) || ".");
136
- for (const entry of entries) {
137
- if (!entry.name.toLowerCase().startsWith(searchPrefix.toLowerCase())) {
138
- continue;
139
- }
140
- let isDirectory = entry.isDirectory();
141
- if (!isDirectory && entry.isSymbolicLink()) {
142
- try {
143
- isDirectory = statSync(join(searchDir, entry.name)).isDirectory();
144
- }
145
- catch {
146
- // broken symlink — treat as file
147
- }
148
- }
149
- let relativePath;
150
- const displayPrefix = rawPrefix;
151
- const name = entry.name;
152
- if (displayPrefix.endsWith("/")) {
153
- relativePath = displayPrefix + name;
154
- }
155
- else if (displayPrefix.includes("/")) {
156
- relativePath = join(dirname(displayPrefix), name);
157
- if (displayPrefix.startsWith("./") && !relativePath.startsWith("./")) {
158
- relativePath = `./${relativePath}`;
159
- }
160
- }
161
- else {
162
- relativePath = name;
163
- }
164
- relativePath = toDisplayPath(relativePath);
165
- const pathValue = isDirectory ? `${relativePath}/` : relativePath;
166
- const value = buildCompletionValue(pathValue, { isAtPrefix, isQuotedPrefix });
167
- const entryRelative = toDisplayPath(relative(cwd, join(searchDir, entry.name)));
168
- suggestions.push({
169
- value,
170
- label: name + (isDirectory ? "/" : ""),
171
- description: searchDir === cwd && rawPrefix === "" ? entryRelative : `${cwdLabel}/${entryRelative}`,
172
- });
143
+ }
144
+ let relativePath;
145
+ const displayPrefix = rawPrefix;
146
+ const name = entry.name;
147
+ if (displayPrefix.endsWith("/")) {
148
+ relativePath = displayPrefix + name;
149
+ } else if (displayPrefix.includes("/")) {
150
+ relativePath = join(dirname(displayPrefix), name);
151
+ if (displayPrefix.startsWith("./") && !relativePath.startsWith("./")) {
152
+ relativePath = `./${relativePath}`;
173
153
  }
174
- return sortAtPathSuggestions(suggestions, rawPrefix);
175
- }
176
- catch {
177
- return [];
154
+ } else {
155
+ relativePath = name;
156
+ }
157
+ relativePath = toDisplayPath(relativePath);
158
+ const pathValue = isDirectory ? `${relativePath}/` : relativePath;
159
+ const value = buildCompletionValue(pathValue, { isAtPrefix, isQuotedPrefix });
160
+ const entryRelative = toDisplayPath(relative(cwd, join(searchDir, entry.name)));
161
+ suggestions.push({
162
+ value,
163
+ label: name + (isDirectory ? "/" : ""),
164
+ description:
165
+ searchDir === cwd && rawPrefix === "" ? entryRelative : `${cwdLabel}/${entryRelative}`,
166
+ });
178
167
  }
168
+ return sortAtPathSuggestions(suggestions, rawPrefix);
169
+ } catch {
170
+ return [];
171
+ }
179
172
  }
180
173
  export function extractAtFilePrefix(textBeforeCursor) {
181
- const atPrefix = extractAtPrefix(textBeforeCursor);
182
- return isAtFileAttachmentPrefix(atPrefix) ? atPrefix : null;
174
+ const atPrefix = extractAtPrefix(textBeforeCursor);
175
+ return isAtFileAttachmentPrefix(atPrefix) ? atPrefix : null;
183
176
  }
184
- //# sourceMappingURL=at-path-mentions.js.map
177
+ //# sourceMappingURL=at-path-mentions.js.map
@@ -1,7 +1,7 @@
1
1
  export type MentionChipTheme = {
2
- fg: (role: string, text: string) => string;
2
+ fg: (role: string, text: string) => string;
3
3
  };
4
4
  export declare function renderLineWithMentionChips(line: string, theme: MentionChipTheme): string;
5
5
  export declare function logicalToVisibleCol(line: string, logicalCol: number): number;
6
6
  export declare function visibleToLogicalCol(line: string, visibleCol: number): number;
7
- //# sourceMappingURL=chat-mention-render.d.ts.map
7
+ //# sourceMappingURL=chat-mention-render.d.ts.map
@@ -1,160 +1,155 @@
1
1
  import { visibleWidth } from "@earendil-works/pi-tui";
2
2
  import { PLAN_MENTION_ALIASES } from "./chat-mentions.js";
3
+
3
4
  const SKILL_SLASH_RE = /\/skill:([a-z0-9_-]+)/gi;
4
5
  const AT_SKILL_RE = /@skill\s+([^\s@/]+)/gi;
5
6
  const PLAN_TOKEN_RE = /\/mode:plan\b/gi;
6
7
  const AT_PLAN_PATTERN = PLAN_MENTION_ALIASES.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
7
- .sort((a, b) => b.length - a.length)
8
- .join("|");
8
+ .sort((a, b) => b.length - a.length)
9
+ .join("|");
9
10
  const AT_PLAN_RE = new RegExp(`(?:^|[\\s"'=])(${AT_PLAN_PATTERN})(?=\\s|$)`, "gi");
10
11
  const PLAN_VISIBLE_LABEL = "@plan";
11
12
  function findNextMentionMatch(line, cursor) {
12
- const candidates = [];
13
- SKILL_SLASH_RE.lastIndex = cursor;
14
- const slashMatch = SKILL_SLASH_RE.exec(line);
15
- if (slashMatch?.index !== undefined) {
16
- candidates.push({
17
- index: slashMatch.index,
18
- length: slashMatch[0].length,
19
- span: { kind: "skill", name: slashMatch[1] ?? "", source: "slash" },
20
- });
21
- }
22
- AT_SKILL_RE.lastIndex = cursor;
23
- const atMatch = AT_SKILL_RE.exec(line);
24
- if (atMatch?.index !== undefined) {
25
- candidates.push({
26
- index: atMatch.index,
27
- length: atMatch[0].length,
28
- span: { kind: "skill", name: atMatch[1] ?? "", source: "at" },
29
- });
30
- }
31
- PLAN_TOKEN_RE.lastIndex = cursor;
32
- const planMatch = PLAN_TOKEN_RE.exec(line);
33
- if (planMatch?.index !== undefined) {
34
- candidates.push({
35
- index: planMatch.index,
36
- length: planMatch[0].length,
37
- span: { kind: "plan", logicalToken: planMatch[0] },
38
- });
39
- }
40
- AT_PLAN_RE.lastIndex = cursor;
41
- const atPlanMatch = AT_PLAN_RE.exec(line);
42
- if (atPlanMatch?.index !== undefined) {
43
- const token = atPlanMatch[1] ?? "@plan";
44
- const leading = atPlanMatch[0].length - token.length;
45
- const index = atPlanMatch.index + leading;
46
- candidates.push({
47
- index,
48
- length: token.length,
49
- span: { kind: "plan", logicalToken: token },
50
- });
51
- }
52
- if (candidates.length === 0)
53
- return null;
54
- return candidates.reduce((earliest, candidate) => candidate.index < earliest.index ? candidate : earliest);
13
+ const candidates = [];
14
+ SKILL_SLASH_RE.lastIndex = cursor;
15
+ const slashMatch = SKILL_SLASH_RE.exec(line);
16
+ if (slashMatch?.index !== undefined) {
17
+ candidates.push({
18
+ index: slashMatch.index,
19
+ length: slashMatch[0].length,
20
+ span: { kind: "skill", name: slashMatch[1] ?? "", source: "slash" },
21
+ });
22
+ }
23
+ AT_SKILL_RE.lastIndex = cursor;
24
+ const atMatch = AT_SKILL_RE.exec(line);
25
+ if (atMatch?.index !== undefined) {
26
+ candidates.push({
27
+ index: atMatch.index,
28
+ length: atMatch[0].length,
29
+ span: { kind: "skill", name: atMatch[1] ?? "", source: "at" },
30
+ });
31
+ }
32
+ PLAN_TOKEN_RE.lastIndex = cursor;
33
+ const planMatch = PLAN_TOKEN_RE.exec(line);
34
+ if (planMatch?.index !== undefined) {
35
+ candidates.push({
36
+ index: planMatch.index,
37
+ length: planMatch[0].length,
38
+ span: { kind: "plan", logicalToken: planMatch[0] },
39
+ });
40
+ }
41
+ AT_PLAN_RE.lastIndex = cursor;
42
+ const atPlanMatch = AT_PLAN_RE.exec(line);
43
+ if (atPlanMatch?.index !== undefined) {
44
+ const token = atPlanMatch[1] ?? "@plan";
45
+ const leading = atPlanMatch[0].length - token.length;
46
+ const index = atPlanMatch.index + leading;
47
+ candidates.push({
48
+ index,
49
+ length: token.length,
50
+ span: { kind: "plan", logicalToken: token },
51
+ });
52
+ }
53
+ if (candidates.length === 0) return null;
54
+ return candidates.reduce((earliest, candidate) =>
55
+ candidate.index < earliest.index ? candidate : earliest,
56
+ );
55
57
  }
56
58
  function parseMentionSpans(line) {
57
- const spans = [];
58
- let cursor = 0;
59
- while (cursor < line.length) {
60
- const nextMatch = findNextMentionMatch(line, cursor);
61
- if (!nextMatch) {
62
- spans.push({ kind: "text", value: line.slice(cursor) });
63
- break;
64
- }
65
- if (nextMatch.index > cursor) {
66
- spans.push({ kind: "text", value: line.slice(cursor, nextMatch.index) });
67
- }
68
- spans.push(nextMatch.span);
69
- cursor = nextMatch.index + nextMatch.length;
59
+ const spans = [];
60
+ let cursor = 0;
61
+ while (cursor < line.length) {
62
+ const nextMatch = findNextMentionMatch(line, cursor);
63
+ if (!nextMatch) {
64
+ spans.push({ kind: "text", value: line.slice(cursor) });
65
+ break;
70
66
  }
71
- if (spans.length === 0) {
72
- spans.push({ kind: "text", value: line });
67
+ if (nextMatch.index > cursor) {
68
+ spans.push({ kind: "text", value: line.slice(cursor, nextMatch.index) });
73
69
  }
74
- return spans;
70
+ spans.push(nextMatch.span);
71
+ cursor = nextMatch.index + nextMatch.length;
72
+ }
73
+ if (spans.length === 0) {
74
+ spans.push({ kind: "text", value: line });
75
+ }
76
+ return spans;
75
77
  }
76
78
  function skillVisibleText(span) {
77
- return span.source === "at" ? `@${span.name}` : span.name;
79
+ return span.source === "at" ? `@${span.name}` : span.name;
78
80
  }
79
81
  function skillLogicalText(span) {
80
- return span.source === "at" ? `@skill ${span.name}` : `/skill:${span.name}`;
82
+ return span.source === "at" ? `@skill ${span.name}` : `/skill:${span.name}`;
81
83
  }
82
84
  function renderSpan(span, theme) {
83
- if (span.kind === "text")
84
- return span.value;
85
- if (span.kind === "skill") {
86
- const text = skillVisibleText(span);
87
- try {
88
- return theme.fg("accent", text);
89
- }
90
- catch {
91
- return theme.fg("text", text);
92
- }
93
- }
85
+ if (span.kind === "text") return span.value;
86
+ if (span.kind === "skill") {
87
+ const text = skillVisibleText(span);
94
88
  try {
95
- return theme.fg("planAccent", PLAN_VISIBLE_LABEL);
96
- }
97
- catch {
98
- return theme.fg("text", PLAN_VISIBLE_LABEL);
89
+ return theme.fg("accent", text);
90
+ } catch {
91
+ return theme.fg("text", text);
99
92
  }
93
+ }
94
+ try {
95
+ return theme.fg("planAccent", PLAN_VISIBLE_LABEL);
96
+ } catch {
97
+ return theme.fg("text", PLAN_VISIBLE_LABEL);
98
+ }
100
99
  }
101
100
  function spanLogicalWidth(span) {
102
- if (span.kind === "text")
103
- return span.value.length;
104
- if (span.kind === "skill")
105
- return skillLogicalText(span).length;
106
- return span.logicalToken.length;
101
+ if (span.kind === "text") return span.value.length;
102
+ if (span.kind === "skill") return skillLogicalText(span).length;
103
+ return span.logicalToken.length;
107
104
  }
108
105
  function spanVisibleText(span) {
109
- if (span.kind === "text")
110
- return span.value;
111
- if (span.kind === "skill")
112
- return skillVisibleText(span);
113
- return PLAN_VISIBLE_LABEL;
106
+ if (span.kind === "text") return span.value;
107
+ if (span.kind === "skill") return skillVisibleText(span);
108
+ return PLAN_VISIBLE_LABEL;
114
109
  }
115
110
  export function renderLineWithMentionChips(line, theme) {
116
- return parseMentionSpans(line)
117
- .map((span) => renderSpan(span, theme))
118
- .join("");
111
+ return parseMentionSpans(line)
112
+ .map((span) => renderSpan(span, theme))
113
+ .join("");
119
114
  }
120
115
  export function logicalToVisibleCol(line, logicalCol) {
121
- const clamped = Math.max(0, Math.min(logicalCol, line.length));
122
- let logical = 0;
123
- let visible = 0;
124
- for (const span of parseMentionSpans(line)) {
125
- const logicalLen = spanLogicalWidth(span);
126
- const visibleLen = visibleWidth(spanVisibleText(span));
127
- if (logical + logicalLen >= clamped) {
128
- const offset = clamped - logical;
129
- if (span.kind === "text") {
130
- return visible + offset;
131
- }
132
- const ratio = logicalLen > 0 ? offset / logicalLen : 0;
133
- return visible + Math.round(visibleLen * ratio);
134
- }
135
- logical += logicalLen;
136
- visible += visibleLen;
116
+ const clamped = Math.max(0, Math.min(logicalCol, line.length));
117
+ let logical = 0;
118
+ let visible = 0;
119
+ for (const span of parseMentionSpans(line)) {
120
+ const logicalLen = spanLogicalWidth(span);
121
+ const visibleLen = visibleWidth(spanVisibleText(span));
122
+ if (logical + logicalLen >= clamped) {
123
+ const offset = clamped - logical;
124
+ if (span.kind === "text") {
125
+ return visible + offset;
126
+ }
127
+ const ratio = logicalLen > 0 ? offset / logicalLen : 0;
128
+ return visible + Math.round(visibleLen * ratio);
137
129
  }
138
- return visible;
130
+ logical += logicalLen;
131
+ visible += visibleLen;
132
+ }
133
+ return visible;
139
134
  }
140
135
  export function visibleToLogicalCol(line, visibleCol) {
141
- const clamped = Math.max(0, visibleCol);
142
- let logical = 0;
143
- let visible = 0;
144
- for (const span of parseMentionSpans(line)) {
145
- const logicalLen = spanLogicalWidth(span);
146
- const visibleLen = visibleWidth(spanVisibleText(span));
147
- if (visible + visibleLen >= clamped) {
148
- const offset = clamped - visible;
149
- if (span.kind === "text") {
150
- return logical + offset;
151
- }
152
- const ratio = visibleLen > 0 ? offset / visibleLen : 0;
153
- return logical + Math.round(logicalLen * ratio);
154
- }
155
- logical += logicalLen;
156
- visible += visibleLen;
136
+ const clamped = Math.max(0, visibleCol);
137
+ let logical = 0;
138
+ let visible = 0;
139
+ for (const span of parseMentionSpans(line)) {
140
+ const logicalLen = spanLogicalWidth(span);
141
+ const visibleLen = visibleWidth(spanVisibleText(span));
142
+ if (visible + visibleLen >= clamped) {
143
+ const offset = clamped - visible;
144
+ if (span.kind === "text") {
145
+ return logical + offset;
146
+ }
147
+ const ratio = visibleLen > 0 ? offset / visibleLen : 0;
148
+ return logical + Math.round(logicalLen * ratio);
157
149
  }
158
- return line.length;
150
+ logical += logicalLen;
151
+ visible += visibleLen;
152
+ }
153
+ return line.length;
159
154
  }
160
- //# sourceMappingURL=chat-mention-render.js.map
155
+ //# sourceMappingURL=chat-mention-render.js.map
@@ -7,12 +7,15 @@ export declare function extractAtPrefix(textBeforeCursor: string): string | null
7
7
  /** KubbiSec: `@skill` may include a space and partial name (not only the last @ token). */
8
8
  export declare function extractSkillMentionPrefix(textBeforeCursor: string): string | null;
9
9
  export declare function parseSkillMentionPrefix(atPrefix: string | null): {
10
- query: string;
10
+ query: string;
11
11
  } | null;
12
12
  export declare function parsePlanMentionPrefix(atPrefix: string | null): {
13
- query: string;
13
+ query: string;
14
14
  } | null;
15
- export declare function filterSkillSuggestions(skills: KubbisecSkillEntry[], query: string): AutocompleteItem[];
15
+ export declare function filterSkillSuggestions(
16
+ skills: KubbisecSkillEntry[],
17
+ query: string,
18
+ ): AutocompleteItem[];
16
19
  /** Pi expands `/skill:name` — map `@skill name` before submit. */
17
20
  export declare function transformAtSkillMentions(text: string): string;
18
21
  /** Legacy: map `@plan` / `@planejar` to `/mode:plan` (prefer session state + visible @plan). */
@@ -20,9 +23,15 @@ export declare function transformAtPlanMentions(text: string): string;
20
23
  /** Apply @skill → /skill:name only. @plan stays visible; plan mode is set via session state. */
21
24
  export declare function transformChatMentions(text: string): string;
22
25
  export declare function messageActivatesPlanMode(text: string): boolean;
23
- export declare function applySkillMentionCompletion(lines: string[], cursorLine: number, cursorCol: number, item: AutocompleteItem, prefix: string): {
24
- lines: string[];
25
- cursorLine: number;
26
- cursorCol: number;
26
+ export declare function applySkillMentionCompletion(
27
+ lines: string[],
28
+ cursorLine: number,
29
+ cursorCol: number,
30
+ item: AutocompleteItem,
31
+ prefix: string,
32
+ ): {
33
+ lines: string[];
34
+ cursorLine: number;
35
+ cursorCol: number;
27
36
  };
28
- //# sourceMappingURL=chat-mentions.d.ts.map
37
+ //# sourceMappingURL=chat-mentions.d.ts.map