@kubbisec/ai-linux-arm64 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/clarify/clarify-gate-state.d.ts +1 -1
- package/bundled/clarify/clarify-gate-state.js +3 -3
- package/bundled/clarify/clarify-gate.d.ts +21 -14
- package/bundled/clarify/clarify-gate.js +118 -111
- package/bundled/clarify/clarify-select-panel.d.ts +16 -9
- package/bundled/clarify/clarify-select-panel.js +65 -67
- package/bundled/clarify/clarify-ui-state.d.ts +12 -10
- package/bundled/clarify/clarify-ui-state.js +26 -26
- package/bundled/clarify/parse-clarify-answer.d.ts +29 -18
- package/bundled/clarify/parse-clarify-answer.js +39 -45
- package/bundled/clarify/question-format.d.ts +34 -23
- package/bundled/clarify/question-format.js +112 -119
- package/bundled/clarify/questionnaire-tool.d.ts +28 -17
- package/bundled/clarify/questionnaire-tool.js +180 -144
- package/bundled/clarify/scope-discovery.d.ts +8 -5
- package/bundled/clarify/scope-discovery.js +102 -110
- package/bundled/clarify/session-questionnaire.d.ts +48 -13
- package/bundled/clarify/session-questionnaire.js +304 -312
- package/bundled/clarify/session-questionnaire.types.d.ts +29 -27
- package/bundled/clarify/session-questionnaire.types.js +10 -10
- package/bundled/components/kubbisec-model-selector.d.ts +47 -34
- package/bundled/components/kubbisec-model-selector.js +187 -177
- package/bundled/config/config.d.ts +6 -6
- package/bundled/config/config.js +55 -55
- package/bundled/config/detect-local-llm-providers.d.ts +26 -16
- package/bundled/config/detect-local-llm-providers.js +130 -142
- package/bundled/config/ensure-kubbisec-project-settings.d.ts +9 -9
- package/bundled/config/ensure-kubbisec-project-settings.js +44 -48
- package/bundled/config/extended-context.d.ts +5 -6
- package/bundled/config/extended-context.js +23 -22
- package/bundled/config/feature-flags.d.ts +10 -2
- package/bundled/config/feature-flags.js +8 -2
- package/bundled/config/format-kubbisec-footer-status.d.ts +1 -1
- package/bundled/config/format-kubbisec-footer-status.js +26 -31
- package/bundled/config/kubbisec-extension-manifest.d.ts +22 -2
- package/bundled/config/kubbisec-extension-manifest.js +20 -20
- package/bundled/config/llm-config-mutations.d.ts +51 -25
- package/bundled/config/llm-config-mutations.js +173 -182
- package/bundled/config/llm-config.d.ts +54 -41
- package/bundled/config/llm-config.js +199 -199
- package/bundled/config/llm-provider-catalog.d.ts +18 -15
- package/bundled/config/llm-provider-catalog.js +45 -46
- package/bundled/config/materialize-kubbisec-pi-resources.d.ts +1 -1
- package/bundled/config/materialize-kubbisec-pi-resources.js +174 -183
- package/bundled/config/register-custom-llm-providers.d.ts +11 -5
- package/bundled/config/register-custom-llm-providers.js +17 -15
- package/bundled/config/register-kubbisec-llm-provider.d.ts +14 -10
- package/bundled/config/register-kubbisec-llm-provider.js +50 -42
- package/bundled/config/resolve-agents-context-file.d.ts +1 -1
- package/bundled/config/resolve-agents-context-file.js +33 -34
- package/bundled/config/resource-budget.d.ts +12 -12
- package/bundled/config/resource-budget.js +28 -28
- package/bundled/config/sync-kubbisec-pi-models.d.ts +6 -3
- package/bundled/config/sync-kubbisec-pi-models.js +58 -58
- package/bundled/copy/cli-reference-index.d.ts +3 -2
- package/bundled/copy/cli-reference-index.js +1 -1
- package/bundled/copy/kubbisec-shell-copy.d.ts +11 -6
- package/bundled/copy/kubbisec-shell-copy.js +1 -1
- package/bundled/extensions/cli-local-shared.d.ts +45 -26
- package/bundled/extensions/cli-local-shared.js +128 -118
- package/bundled/extensions/kubbisec-aspm-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-aspm-local.extension.js +118 -114
- package/bundled/extensions/kubbisec-brand.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-brand.extension.js +25 -25
- package/bundled/extensions/kubbisec-byok-provider.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-byok-provider.extension.js +2 -2
- package/bundled/extensions/kubbisec-clarify.extension.d.ts +64 -35
- package/bundled/extensions/kubbisec-clarify.extension.js +323 -305
- package/bundled/extensions/kubbisec-exit.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-exit.extension.js +29 -32
- package/bundled/extensions/kubbisec-extended-context.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-extended-context.extension.js +56 -43
- package/bundled/extensions/kubbisec-footer.extension.d.ts +14 -14
- package/bundled/extensions/kubbisec-footer.extension.js +205 -215
- package/bundled/extensions/kubbisec-github-local.extension.d.ts +26 -18
- package/bundled/extensions/kubbisec-github-local.extension.js +123 -116
- package/bundled/extensions/kubbisec-llm-config.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-llm-config.extension.js +200 -181
- package/bundled/extensions/kubbisec-memory.extension.d.ts +9 -7
- package/bundled/extensions/kubbisec-memory.extension.js +88 -95
- package/bundled/extensions/kubbisec-naus-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-naus-local.extension.js +132 -111
- package/bundled/extensions/kubbisec-platform-tools.extension.d.ts +31 -21
- package/bundled/extensions/kubbisec-platform-tools.extension.js +152 -152
- package/bundled/extensions/kubbisec-runtime-status.extension.d.ts +10 -8
- package/bundled/extensions/kubbisec-runtime-status.extension.js +15 -13
- package/bundled/extensions/kubbisec-scope.extension.d.ts +12 -7
- package/bundled/extensions/kubbisec-scope.extension.js +13 -13
- package/bundled/extensions/kubbisec-skill-mentions.extension.d.ts +27 -16
- package/bundled/extensions/kubbisec-skill-mentions.extension.js +73 -63
- package/bundled/extensions/kubbisec-skill-telemetry.extension.d.ts +2 -3
- package/bundled/extensions/kubbisec-skill-telemetry.extension.js +59 -64
- package/bundled/extensions/kubbisec-theme-lock.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-theme-lock.extension.js +33 -34
- package/bundled/extensions/kubbisec-ui.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-ui.extension.js +114 -109
- package/bundled/extensions/kubbisec-workflow.extension.d.ts +20 -18
- package/bundled/extensions/kubbisec-workflow.extension.js +138 -140
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.d.ts +2 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.d.ts.map +1 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.js +626 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.js.map +1 -0
- package/bundled/resolve-bundled-dist-root.js +122 -131
- package/bundled/skills/at-path-mentions.d.ts +1 -1
- package/bundled/skills/at-path-mentions.js +146 -153
- package/bundled/skills/chat-mention-render.d.ts +2 -2
- package/bundled/skills/chat-mention-render.js +121 -126
- package/bundled/skills/chat-mentions.d.ts +17 -8
- package/bundled/skills/chat-mentions.js +76 -76
- package/bundled/skills/list-bundled-skills.d.ts +3 -3
- package/bundled/skills/list-bundled-skills.js +33 -35
- package/bundled/skills/skill-mention.d.ts +10 -2
- package/bundled/skills/skill-mention.js +10 -2
- package/bundled/theme/clear-terminal.d.ts +1 -1
- package/bundled/theme/clear-terminal.js +3 -4
- package/bundled/theme/footer-render-hook.d.ts +1 -1
- package/bundled/theme/footer-render-hook.js +3 -3
- package/bundled/theme/kubbisec-brand-fg.d.ts +1 -1
- package/bundled/theme/kubbisec-brand-fg.js +2 -2
- package/bundled/theme/kubbisec-menu-themes.d.ts +7 -7
- package/bundled/theme/kubbisec-menu-themes.js +30 -31
- package/bundled/theme/kubbisec-theme-name.d.ts +1 -1
- package/bundled/theme/kubbisec-theme-name.js +1 -1
- package/bundled/theme/patch-pi-settings-theme.runtime.d.ts +1 -1
- package/bundled/theme/patch-pi-settings-theme.runtime.js +11 -10
- package/bundled/theme/render-compact-header.d.ts +13 -5
- package/bundled/theme/render-compact-header.js +127 -129
- package/bundled/workflow/session-workflow-mode.d.ts +1 -1
- package/bundled/workflow/session-workflow-mode.js +33 -33
- package/package.json +1 -1
|
@@ -3,165 +3,156 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { getAiStateDir } from "@kubbisec/home";
|
|
6
|
+
|
|
6
7
|
const BUNDLED_ASSET_DIRS = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
"extensions",
|
|
9
|
+
"skills",
|
|
10
|
+
"theme",
|
|
11
|
+
"assets",
|
|
12
|
+
"copy",
|
|
13
|
+
"config",
|
|
14
|
+
"clarify",
|
|
15
|
+
"components",
|
|
16
|
+
"workflow",
|
|
16
17
|
];
|
|
17
18
|
const BUNDLED_ROOT_FILES = ["resolve-bundled-dist-root.js"];
|
|
18
19
|
const MARKER_EXTENSION = "kubbisec-brand.extension.js";
|
|
19
20
|
/** True when this process runs from a pkg / @yao-pkg/pkg native binary. */
|
|
20
21
|
export function isPkgBundledCli() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
22
|
+
if (process.pkg) return true;
|
|
23
|
+
try {
|
|
24
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
25
|
+
return selfPath.includes("/snapshot/") || selfPath.includes("\\snapshot\\");
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
30
29
|
}
|
|
31
30
|
function hasCompiledBundledAssets(distDir) {
|
|
32
|
-
|
|
31
|
+
return fs.existsSync(path.join(distDir, "extensions", MARKER_EXTENSION));
|
|
33
32
|
}
|
|
34
33
|
/** Dist directory inside the bundle (extensions/, skills/, …). */
|
|
35
34
|
export function resolveSnapshotBundledDistDir() {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return packageDist;
|
|
43
|
-
}
|
|
35
|
+
const entryDir = path.dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
if (hasCompiledBundledAssets(entryDir)) {
|
|
37
|
+
return entryDir;
|
|
38
|
+
}
|
|
39
|
+
const packageDist = path.join(entryDir, "..", "dist");
|
|
40
|
+
if (hasCompiledBundledAssets(packageDist)) {
|
|
44
41
|
return packageDist;
|
|
42
|
+
}
|
|
43
|
+
return packageDist;
|
|
45
44
|
}
|
|
46
45
|
function fingerprintBundledDist(distDir) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
hash.update(name);
|
|
77
|
-
hash.update(fs.readFileSync(path.join(distDir, name)));
|
|
78
|
-
}
|
|
79
|
-
return hash.digest("hex").slice(0, 16);
|
|
46
|
+
const hash = crypto.createHash("sha256");
|
|
47
|
+
for (const dir of BUNDLED_ASSET_DIRS) {
|
|
48
|
+
const base = path.join(distDir, dir);
|
|
49
|
+
if (!fs.existsSync(base)) continue;
|
|
50
|
+
for (const rel of listFilesRecursive(base)) {
|
|
51
|
+
hash.update(rel);
|
|
52
|
+
hash.update(fs.readFileSync(path.join(base, rel)));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (const file of BUNDLED_ROOT_FILES) {
|
|
56
|
+
const full = path.join(distDir, file);
|
|
57
|
+
if (!fs.existsSync(full)) continue;
|
|
58
|
+
hash.update(file);
|
|
59
|
+
hash.update(fs.readFileSync(full));
|
|
60
|
+
}
|
|
61
|
+
for (const scope of ["@kubbisec", "@aspm"]) {
|
|
62
|
+
const scopeModules = path.join(distDir, "node_modules", scope);
|
|
63
|
+
if (!fs.existsSync(scopeModules)) continue;
|
|
64
|
+
for (const rel of listFilesRecursive(scopeModules)) {
|
|
65
|
+
hash.update(`${scope}/${rel}`);
|
|
66
|
+
hash.update(fs.readFileSync(path.join(scopeModules, rel)));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const name of fs.readdirSync(distDir)) {
|
|
70
|
+
if (!name.endsWith(".md")) continue;
|
|
71
|
+
hash.update(name);
|
|
72
|
+
hash.update(fs.readFileSync(path.join(distDir, name)));
|
|
73
|
+
}
|
|
74
|
+
return hash.digest("hex").slice(0, 16);
|
|
80
75
|
}
|
|
81
76
|
function listFilesRecursive(root, prefix = "") {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return out;
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const entry of fs.readdirSync(path.join(root, prefix), { withFileTypes: true })) {
|
|
79
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
80
|
+
if (entry.isDirectory()) {
|
|
81
|
+
out.push(...listFilesRecursive(root, rel));
|
|
82
|
+
} else {
|
|
83
|
+
out.push(rel);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
93
87
|
}
|
|
94
88
|
function copyBundledDist(sourceDist, targetDist) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
continue;
|
|
115
|
-
fs.copyFileSync(path.join(sourceDist, name), path.join(targetDist, name));
|
|
116
|
-
}
|
|
89
|
+
fs.mkdirSync(targetDist, { recursive: true, mode: 0o755 });
|
|
90
|
+
for (const dir of BUNDLED_ASSET_DIRS) {
|
|
91
|
+
const src = path.join(sourceDist, dir);
|
|
92
|
+
if (!fs.existsSync(src)) continue;
|
|
93
|
+
fs.cpSync(src, path.join(targetDist, dir), { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
for (const file of BUNDLED_ROOT_FILES) {
|
|
96
|
+
const src = path.join(sourceDist, file);
|
|
97
|
+
if (!fs.existsSync(src)) continue;
|
|
98
|
+
fs.copyFileSync(src, path.join(targetDist, file));
|
|
99
|
+
}
|
|
100
|
+
const modulesSrc = path.join(sourceDist, "node_modules");
|
|
101
|
+
if (fs.existsSync(modulesSrc)) {
|
|
102
|
+
fs.cpSync(modulesSrc, path.join(targetDist, "node_modules"), { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
for (const name of fs.readdirSync(sourceDist)) {
|
|
105
|
+
if (!name.endsWith(".md")) continue;
|
|
106
|
+
fs.copyFileSync(path.join(sourceDist, name), path.join(targetDist, name));
|
|
107
|
+
}
|
|
117
108
|
}
|
|
118
109
|
export function materializeBundledDistForHost(snapshotDist) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
110
|
+
const version =
|
|
111
|
+
process.env.KUBBISEC_AI_VERSION?.trim() || process.env.npm_package_version?.trim() || "bundled";
|
|
112
|
+
const fingerprint = fingerprintBundledDist(snapshotDist);
|
|
113
|
+
const targetDist = path.join(getAiStateDir(), "bundled", version, fingerprint);
|
|
114
|
+
const marker = path.join(targetDist, "extensions", MARKER_EXTENSION);
|
|
115
|
+
const stampPath = path.join(targetDist, ".fingerprint");
|
|
116
|
+
if (fs.existsSync(marker)) {
|
|
117
|
+
try {
|
|
118
|
+
if (fs.readFileSync(stampPath, "utf8").trim() === fingerprint) {
|
|
119
|
+
return targetDist;
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
/* re-materialize */
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (fs.existsSync(targetDist)) {
|
|
126
|
+
fs.rmSync(targetDist, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
copyBundledDist(snapshotDist, targetDist);
|
|
129
|
+
fs.writeFileSync(stampPath, `${fingerprint}\n`, "utf8");
|
|
130
|
+
return targetDist;
|
|
140
131
|
}
|
|
141
132
|
/** Assets shipped next to the platform npm binary (`../bundled` from `bin/kubbisec`). */
|
|
142
133
|
export function resolvePackagedBundledDistDir() {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
134
|
+
const packaged = path.join(path.dirname(process.execPath), "..", "bundled");
|
|
135
|
+
if (hasCompiledBundledAssets(packaged)) {
|
|
136
|
+
return packaged;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
148
139
|
}
|
|
149
140
|
/**
|
|
150
141
|
* Directory containing extensions/, skills/, theme/, assets/ for Pi `-e` / `--skill`.
|
|
151
142
|
* Native CLI: prefer `../bundled` beside the executable; else copy pkg snapshot assets to ~/.kubbisec/ai/bundled/.
|
|
152
143
|
*/
|
|
153
144
|
export function resolveBundledDistRoot() {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return snapshotDist;
|
|
161
|
-
}
|
|
162
|
-
if (hasCompiledBundledAssets(snapshotDist)) {
|
|
163
|
-
return materializeBundledDistForHost(snapshotDist);
|
|
164
|
-
}
|
|
145
|
+
const packaged = resolvePackagedBundledDistDir();
|
|
146
|
+
if (packaged) {
|
|
147
|
+
return packaged;
|
|
148
|
+
}
|
|
149
|
+
const snapshotDist = resolveSnapshotBundledDistDir();
|
|
150
|
+
if (!isPkgBundledCli()) {
|
|
165
151
|
return snapshotDist;
|
|
152
|
+
}
|
|
153
|
+
if (hasCompiledBundledAssets(snapshotDist)) {
|
|
154
|
+
return materializeBundledDistForHost(snapshotDist);
|
|
155
|
+
}
|
|
156
|
+
return snapshotDist;
|
|
166
157
|
}
|
|
167
|
-
//# sourceMappingURL=resolve-bundled-dist-root.js.map
|
|
158
|
+
//# sourceMappingURL=resolve-bundled-dist-root.js.map
|
|
@@ -4,4 +4,4 @@ export declare function isAtFileAttachmentPrefix(atPrefix: string | null): boole
|
|
|
4
4
|
/** List cwd-scoped entries for `@` / `@path` (Pi getFileSuggestions semantics). */
|
|
5
5
|
export declare function getAtPathFileSuggestions(cwd: string, atPrefix: string): AutocompleteItem[];
|
|
6
6
|
export declare function extractAtFilePrefix(textBeforeCursor: string): string | null;
|
|
7
|
-
//# sourceMappingURL=at-path-mentions.d.ts.map
|
|
7
|
+
//# sourceMappingURL=at-path-mentions.d.ts.map
|
|
@@ -1,184 +1,177 @@
|
|
|
1
1
|
import { readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, relative } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
extractAtPrefix,
|
|
5
|
+
parsePlanMentionPrefix,
|
|
6
|
+
parseSkillMentionPrefix,
|
|
7
|
+
} from "./chat-mentions.js";
|
|
8
|
+
|
|
4
9
|
function toDisplayPath(value) {
|
|
5
|
-
|
|
10
|
+
return value.replace(/\\/g, "/");
|
|
6
11
|
}
|
|
7
12
|
function parsePathPrefix(prefix) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|