@hasna/terminal 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.js +17 -2
- package/package.json +1 -1
- package/src/ai.ts +22 -3
package/dist/ai.js
CHANGED
|
@@ -50,6 +50,10 @@ const IRREVERSIBLE_PATTERNS = [
|
|
|
50
50
|
const SAFE_OVERRIDES = [
|
|
51
51
|
/^\s*git\s+(log|show|diff|branch|status|blame|tag|remote|stash\s+list)\b/,
|
|
52
52
|
/^\s*git\s+log\b/,
|
|
53
|
+
// find -exec with read-only tools is safe
|
|
54
|
+
/\bfind\b.*-exec\s+(wc|cat|head|tail|grep|stat|file|du|ls)\b/,
|
|
55
|
+
// find without -exec is always safe
|
|
56
|
+
/^\s*find\b(?!.*-exec\s+(rm|mv|chmod|chown|sed))/,
|
|
53
57
|
];
|
|
54
58
|
export function isIrreversible(command) {
|
|
55
59
|
// Safe overrides take priority
|
|
@@ -119,10 +123,19 @@ function detectProjectContext() {
|
|
|
119
123
|
// Top-level dirs
|
|
120
124
|
const topLevel = execSync("ls -1", { cwd, encoding: "utf8", timeout: 2000 }).trim();
|
|
121
125
|
parts.push(`Top-level: ${topLevel.split("\n").join(", ")}`);
|
|
126
|
+
// Detect monorepo (packages/ or workspaces in package.json)
|
|
127
|
+
const isMonorepo = existsSync(join(cwd, "packages")) || existsSync(join(cwd, "apps"));
|
|
128
|
+
if (isMonorepo) {
|
|
129
|
+
const pkgDirs = execSync(`ls -d packages/*/src 2>/dev/null || ls -d apps/*/src 2>/dev/null || echo ""`, { cwd, encoding: "utf8", timeout: 2000 }).trim();
|
|
130
|
+
if (pkgDirs) {
|
|
131
|
+
parts.push(`MONOREPO: Source is in packages/*/src/, NOT src/. Search packages/ not src/.`);
|
|
132
|
+
parts.push(`Package sources:\n${pkgDirs}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
122
135
|
// src/ structure — include FILES so AI knows exact filenames + extensions
|
|
123
|
-
for (const srcDir of ["src", "lib", "app"]) {
|
|
136
|
+
for (const srcDir of isMonorepo ? ["packages"] : ["src", "lib", "app"]) {
|
|
124
137
|
if (existsSync(join(cwd, srcDir))) {
|
|
125
|
-
const tree = execSync(`find ${srcDir} -maxdepth 3 -not -path '*/node_modules/*' -not -path '*/dist/*' -not -name '*.test.*' -not -name '*.spec.*' 2>/dev/null | sort | head -
|
|
138
|
+
const tree = execSync(`find ${srcDir} -maxdepth ${isMonorepo ? 4 : 3} -not -path '*/node_modules/*' -not -path '*/dist/*' -not -name '*.test.*' -not -name '*.spec.*' 2>/dev/null | sort | head -80`, { cwd, encoding: "utf8", timeout: 3000 }).trim();
|
|
126
139
|
if (tree)
|
|
127
140
|
parts.push(`Files in ${srcDir}/:\n${tree}`);
|
|
128
141
|
break;
|
|
@@ -203,6 +216,8 @@ SEMANTIC MAPPING: When the user references a concept, search the file tree for R
|
|
|
203
216
|
- When uncertain: grep -rn "keyword" src/ --include="*.ts" -l (list matching files)
|
|
204
217
|
|
|
205
218
|
ACTION vs CONCEPTUAL: If the prompt starts with "run", "execute", "check", "test", "build", "show output of" — ALWAYS generate an executable command. NEVER read README for action requests. Only read docs for "explain why", "what does X mean", "how was X designed".
|
|
219
|
+
|
|
220
|
+
MONOREPO: If the project context says "MONOREPO", search packages/ or apps/ NOT src/. Use: grep -rn "pattern" packages/ --include="*.ts". For specific packages, use packages/PKGNAME/src/.
|
|
206
221
|
cwd: ${process.cwd()}
|
|
207
222
|
shell: zsh / macOS${projectContext}${restrictionBlock}${contextBlock}`;
|
|
208
223
|
}
|
package/package.json
CHANGED
package/src/ai.ts
CHANGED
|
@@ -59,6 +59,10 @@ const IRREVERSIBLE_PATTERNS = [
|
|
|
59
59
|
const SAFE_OVERRIDES = [
|
|
60
60
|
/^\s*git\s+(log|show|diff|branch|status|blame|tag|remote|stash\s+list)\b/,
|
|
61
61
|
/^\s*git\s+log\b/,
|
|
62
|
+
// find -exec with read-only tools is safe
|
|
63
|
+
/\bfind\b.*-exec\s+(wc|cat|head|tail|grep|stat|file|du|ls)\b/,
|
|
64
|
+
// find without -exec is always safe
|
|
65
|
+
/^\s*find\b(?!.*-exec\s+(rm|mv|chmod|chown|sed))/,
|
|
62
66
|
];
|
|
63
67
|
|
|
64
68
|
export function isIrreversible(command: string): boolean {
|
|
@@ -148,12 +152,25 @@ function detectProjectContext(): string {
|
|
|
148
152
|
const topLevel = execSync("ls -1", { cwd, encoding: "utf8", timeout: 2000 }).trim();
|
|
149
153
|
parts.push(`Top-level: ${topLevel.split("\n").join(", ")}`);
|
|
150
154
|
|
|
155
|
+
// Detect monorepo (packages/ or workspaces in package.json)
|
|
156
|
+
const isMonorepo = existsSync(join(cwd, "packages")) || existsSync(join(cwd, "apps"));
|
|
157
|
+
if (isMonorepo) {
|
|
158
|
+
const pkgDirs = execSync(
|
|
159
|
+
`ls -d packages/*/src 2>/dev/null || ls -d apps/*/src 2>/dev/null || echo ""`,
|
|
160
|
+
{ cwd, encoding: "utf8", timeout: 2000 }
|
|
161
|
+
).trim();
|
|
162
|
+
if (pkgDirs) {
|
|
163
|
+
parts.push(`MONOREPO: Source is in packages/*/src/, NOT src/. Search packages/ not src/.`);
|
|
164
|
+
parts.push(`Package sources:\n${pkgDirs}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
151
168
|
// src/ structure — include FILES so AI knows exact filenames + extensions
|
|
152
|
-
for (const srcDir of ["src", "lib", "app"]) {
|
|
169
|
+
for (const srcDir of isMonorepo ? ["packages"] : ["src", "lib", "app"]) {
|
|
153
170
|
if (existsSync(join(cwd, srcDir))) {
|
|
154
171
|
const tree = execSync(
|
|
155
|
-
`find ${srcDir} -maxdepth 3 -not -path '*/node_modules/*' -not -path '*/dist/*' -not -name '*.test.*' -not -name '*.spec.*' 2>/dev/null | sort | head -
|
|
156
|
-
{ cwd, encoding: "utf8", timeout:
|
|
172
|
+
`find ${srcDir} -maxdepth ${isMonorepo ? 4 : 3} -not -path '*/node_modules/*' -not -path '*/dist/*' -not -name '*.test.*' -not -name '*.spec.*' 2>/dev/null | sort | head -80`,
|
|
173
|
+
{ cwd, encoding: "utf8", timeout: 3000 }
|
|
157
174
|
).trim();
|
|
158
175
|
if (tree) parts.push(`Files in ${srcDir}/:\n${tree}`);
|
|
159
176
|
break;
|
|
@@ -238,6 +255,8 @@ SEMANTIC MAPPING: When the user references a concept, search the file tree for R
|
|
|
238
255
|
- When uncertain: grep -rn "keyword" src/ --include="*.ts" -l (list matching files)
|
|
239
256
|
|
|
240
257
|
ACTION vs CONCEPTUAL: If the prompt starts with "run", "execute", "check", "test", "build", "show output of" — ALWAYS generate an executable command. NEVER read README for action requests. Only read docs for "explain why", "what does X mean", "how was X designed".
|
|
258
|
+
|
|
259
|
+
MONOREPO: If the project context says "MONOREPO", search packages/ or apps/ NOT src/. Use: grep -rn "pattern" packages/ --include="*.ts". For specific packages, use packages/PKGNAME/src/.
|
|
241
260
|
cwd: ${process.cwd()}
|
|
242
261
|
shell: zsh / macOS${projectContext}${restrictionBlock}${contextBlock}`;
|
|
243
262
|
}
|