@tyvm/knowhow 0.0.108 → 0.0.109-dev.86123ed
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/README.md +45 -0
- package/package.json +9 -4
- package/scripts/build-for-node.sh +10 -24
- package/scripts/publish.sh +86 -0
- package/src/agents/base/base.ts +10 -0
- package/src/agents/tools/execCommand.ts +49 -6
- package/src/agents/tools/index.ts +0 -1
- package/src/agents/tools/list.ts +2 -4
- package/src/chat/CliChatService.ts +11 -2
- package/src/chat/modules/AgentModule.ts +61 -31
- package/src/chat/modules/SessionsModule.ts +47 -3
- package/src/chat/modules/SystemModule.ts +2 -2
- package/src/chat/renderer/CompactRenderer.ts +20 -0
- package/src/chat/renderer/ConsoleRenderer.ts +19 -0
- package/src/chat/renderer/FancyRenderer.ts +19 -0
- package/src/chat/renderer/types.ts +11 -0
- package/src/cli.ts +91 -659
- package/src/clients/anthropic.ts +18 -17
- package/src/clients/index.ts +31 -11
- package/src/clients/openai.ts +8 -5
- package/src/clients/types.ts +48 -10
- package/src/clients/withRetry.ts +89 -0
- package/src/cloudWorker.ts +175 -113
- package/src/commands/agent.ts +246 -0
- package/src/commands/misc.ts +174 -0
- package/src/commands/modules.ts +217 -0
- package/src/commands/services.ts +77 -0
- package/src/commands/workers.ts +168 -0
- package/src/config.ts +38 -1
- package/src/fileSync.ts +70 -29
- package/src/hashes.ts +35 -13
- package/src/index.ts +18 -0
- package/src/logger.ts +197 -0
- package/src/plugins/embedding.ts +11 -6
- package/src/plugins/plugins.ts +0 -21
- package/src/plugins/vim.ts +5 -16
- package/src/processors/JsonCompressor.ts +6 -6
- package/src/services/EventService.ts +61 -1
- package/src/services/KnowhowClient.ts +34 -4
- package/src/services/MediaProcessorService.ts +3 -2
- package/src/services/modules/index.ts +95 -51
- package/src/services/modules/types.ts +6 -0
- package/src/tunnel.ts +216 -0
- package/src/types.ts +0 -1
- package/src/worker.ts +105 -312
- package/src/workers/auth/WsMiddleware.ts +99 -0
- package/src/workers/auth/authMiddleware.ts +104 -0
- package/src/workers/auth/types.ts +14 -2
- package/src/workers/tools/index.ts +2 -0
- package/src/workers/tools/reloadConfig.ts +84 -0
- package/tests/services/WorkerReloadConfig.test.ts +141 -0
- package/tests/unit/clients/AIClient.test.ts +446 -0
- package/tests/unit/clients/withRetry.test.ts +319 -0
- package/tests/unit/commands/github-credentials.test.ts +210 -0
- package/tests/unit/modules/moduleLoading.test.ts +39 -37
- package/tests/unit/plugins/pluginLoading.test.ts +0 -85
- package/ts_build/package.json +9 -4
- package/ts_build/src/agents/base/base.js +11 -0
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/tools/execCommand.d.ts +1 -1
- package/ts_build/src/agents/tools/execCommand.js +39 -5
- package/ts_build/src/agents/tools/execCommand.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +0 -1
- package/ts_build/src/agents/tools/index.js +0 -1
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +2 -4
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/chat/CliChatService.js +14 -2
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +43 -20
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/SessionsModule.js +37 -3
- package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
- package/ts_build/src/chat/modules/SystemModule.js +2 -2
- package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
- package/ts_build/src/chat/renderer/CompactRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js +16 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/ConsoleRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js +16 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/FancyRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js +16 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/types.d.ts +2 -0
- package/ts_build/src/cli.js +47 -519
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +5 -5
- package/ts_build/src/clients/anthropic.js +18 -17
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/index.js +9 -10
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/openai.js +4 -4
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +15 -8
- package/ts_build/src/clients/withRetry.d.ts +2 -0
- package/ts_build/src/clients/withRetry.js +60 -0
- package/ts_build/src/clients/withRetry.js.map +1 -0
- package/ts_build/src/cloudWorker.d.ts +14 -0
- package/ts_build/src/cloudWorker.js +105 -66
- package/ts_build/src/cloudWorker.js.map +1 -1
- package/ts_build/src/commands/agent.d.ts +6 -0
- package/ts_build/src/commands/agent.js +229 -0
- package/ts_build/src/commands/agent.js.map +1 -0
- package/ts_build/src/commands/misc.d.ts +10 -0
- package/ts_build/src/commands/misc.js +197 -0
- package/ts_build/src/commands/misc.js.map +1 -0
- package/ts_build/src/commands/modules.d.ts +3 -0
- package/ts_build/src/commands/modules.js +207 -0
- package/ts_build/src/commands/modules.js.map +1 -0
- package/ts_build/src/commands/services.d.ts +5 -0
- package/ts_build/src/commands/services.js +87 -0
- package/ts_build/src/commands/services.js.map +1 -0
- package/ts_build/src/commands/workers.d.ts +6 -0
- package/ts_build/src/commands/workers.js +168 -0
- package/ts_build/src/commands/workers.js.map +1 -0
- package/ts_build/src/config.d.ts +1 -0
- package/ts_build/src/config.js +33 -1
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/fileSync.d.ts +6 -0
- package/ts_build/src/fileSync.js +50 -23
- package/ts_build/src/fileSync.js.map +1 -1
- package/ts_build/src/hashes.d.ts +2 -2
- package/ts_build/src/hashes.js +35 -9
- package/ts_build/src/hashes.js.map +1 -1
- package/ts_build/src/index.d.ts +1 -0
- package/ts_build/src/index.js +17 -1
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/logger.d.ts +21 -0
- package/ts_build/src/logger.js +106 -0
- package/ts_build/src/logger.js.map +1 -0
- package/ts_build/src/plugins/embedding.js +4 -3
- package/ts_build/src/plugins/embedding.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +0 -2
- package/ts_build/src/plugins/plugins.js +0 -11
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/vim.js +3 -9
- package/ts_build/src/plugins/vim.js.map +1 -1
- package/ts_build/src/processors/JsonCompressor.js +4 -4
- package/ts_build/src/processors/JsonCompressor.js.map +1 -1
- package/ts_build/src/services/EventService.d.ts +6 -1
- package/ts_build/src/services/EventService.js +29 -0
- package/ts_build/src/services/EventService.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +13 -1
- package/ts_build/src/services/KnowhowClient.js +19 -2
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/MediaProcessorService.d.ts +2 -1
- package/ts_build/src/services/MediaProcessorService.js +2 -1
- package/ts_build/src/services/MediaProcessorService.js.map +1 -1
- package/ts_build/src/services/modules/index.d.ts +33 -0
- package/ts_build/src/services/modules/index.js +67 -47
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/services/modules/types.d.ts +6 -0
- package/ts_build/src/tunnel.d.ts +27 -0
- package/ts_build/src/tunnel.js +112 -0
- package/ts_build/src/tunnel.js.map +1 -0
- package/ts_build/src/types.d.ts +0 -1
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/worker.d.ts +1 -4
- package/ts_build/src/worker.js +59 -227
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/src/workers/auth/WsMiddleware.d.ts +8 -0
- package/ts_build/src/workers/auth/WsMiddleware.js +65 -0
- package/ts_build/src/workers/auth/WsMiddleware.js.map +1 -0
- package/ts_build/src/workers/auth/authMiddleware.d.ts +3 -0
- package/ts_build/src/workers/auth/authMiddleware.js +60 -0
- package/ts_build/src/workers/auth/authMiddleware.js.map +1 -0
- package/ts_build/src/workers/auth/types.d.ts +8 -1
- package/ts_build/src/workers/tools/index.d.ts +2 -0
- package/ts_build/src/workers/tools/index.js +4 -1
- package/ts_build/src/workers/tools/index.js.map +1 -1
- package/ts_build/src/workers/tools/reloadConfig.d.ts +14 -0
- package/ts_build/src/workers/tools/reloadConfig.js +48 -0
- package/ts_build/src/workers/tools/reloadConfig.js.map +1 -0
- package/ts_build/tests/services/WorkerReloadConfig.test.d.ts +1 -0
- package/ts_build/tests/services/WorkerReloadConfig.test.js +86 -0
- package/ts_build/tests/services/WorkerReloadConfig.test.js.map +1 -0
- package/ts_build/tests/unit/clients/AIClient.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/AIClient.test.js +339 -0
- package/ts_build/tests/unit/clients/AIClient.test.js.map +1 -0
- package/ts_build/tests/unit/clients/withRetry.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/withRetry.test.js +225 -0
- package/ts_build/tests/unit/clients/withRetry.test.js.map +1 -0
- package/ts_build/tests/unit/commands/github-credentials.test.d.ts +1 -0
- package/ts_build/tests/unit/commands/github-credentials.test.js +145 -0
- package/ts_build/tests/unit/commands/github-credentials.test.js.map +1 -0
- package/ts_build/tests/unit/modules/moduleLoading.test.js +20 -26
- package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -1
- package/ts_build/tests/unit/plugins/pluginLoading.test.js +0 -65
- package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
- package/src/agents/tools/executeScript/README.md +0 -94
- package/src/agents/tools/executeScript/definition.ts +0 -79
- package/src/agents/tools/executeScript/examples/dependency-injection-validation.ts +0 -272
- package/src/agents/tools/executeScript/examples/quick-test.ts +0 -74
- package/src/agents/tools/executeScript/examples/serialization-test.ts +0 -321
- package/src/agents/tools/executeScript/examples/test-runner.ts +0 -197
- package/src/agents/tools/executeScript/index.ts +0 -98
- package/src/services/script-execution/SandboxContext.ts +0 -282
- package/src/services/script-execution/ScriptExecutor.ts +0 -441
- package/src/services/script-execution/ScriptPolicy.ts +0 -194
- package/src/services/script-execution/ScriptTracer.ts +0 -249
- package/src/services/script-execution/types.ts +0 -134
- package/ts_build/src/agents/tools/executeScript/definition.d.ts +0 -2
- package/ts_build/src/agents/tools/executeScript/definition.js +0 -76
- package/ts_build/src/agents/tools/executeScript/definition.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.d.ts +0 -18
- package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.js +0 -192
- package/ts_build/src/agents/tools/executeScript/examples/dependency-injection-validation.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/quick-test.d.ts +0 -3
- package/ts_build/src/agents/tools/executeScript/examples/quick-test.js +0 -64
- package/ts_build/src/agents/tools/executeScript/examples/quick-test.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/serialization-test.d.ts +0 -15
- package/ts_build/src/agents/tools/executeScript/examples/serialization-test.js +0 -266
- package/ts_build/src/agents/tools/executeScript/examples/serialization-test.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/examples/test-runner.d.ts +0 -4
- package/ts_build/src/agents/tools/executeScript/examples/test-runner.js +0 -208
- package/ts_build/src/agents/tools/executeScript/examples/test-runner.js.map +0 -1
- package/ts_build/src/agents/tools/executeScript/index.d.ts +0 -28
- package/ts_build/src/agents/tools/executeScript/index.js +0 -72
- package/ts_build/src/agents/tools/executeScript/index.js.map +0 -1
- package/ts_build/src/services/script-execution/SandboxContext.d.ts +0 -34
- package/ts_build/src/services/script-execution/SandboxContext.js +0 -189
- package/ts_build/src/services/script-execution/SandboxContext.js.map +0 -1
- package/ts_build/src/services/script-execution/ScriptExecutor.d.ts +0 -19
- package/ts_build/src/services/script-execution/ScriptExecutor.js +0 -269
- package/ts_build/src/services/script-execution/ScriptExecutor.js.map +0 -1
- package/ts_build/src/services/script-execution/ScriptPolicy.d.ts +0 -28
- package/ts_build/src/services/script-execution/ScriptPolicy.js +0 -115
- package/ts_build/src/services/script-execution/ScriptPolicy.js.map +0 -1
- package/ts_build/src/services/script-execution/ScriptTracer.d.ts +0 -19
- package/ts_build/src/services/script-execution/ScriptTracer.js +0 -186
- package/ts_build/src/services/script-execution/ScriptTracer.js.map +0 -1
- package/ts_build/src/services/script-execution/types.d.ts +0 -108
- package/ts_build/src/services/script-execution/types.js +0 -3
- package/ts_build/src/services/script-execution/types.js.map +0 -1
package/src/fileSync.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
+
import * as os from "os";
|
|
3
4
|
import { KnowhowSimpleClient, KNOWHOW_API_URL } from "./services/KnowhowClient";
|
|
4
5
|
import { loadJwt } from "./login";
|
|
5
6
|
import { getConfig } from "./config";
|
|
6
7
|
import { services } from "./services";
|
|
7
8
|
import { S3Service } from "./services/S3";
|
|
8
|
-
import { getHashes, hasFileChangedSinceUpload, saveUploadHash, isLocalFileMatchingRemote, isLocalFileMatchingDownloadHash, saveDownloadHash } from "./hashes";
|
|
9
|
+
import { getHashes, saveHashes, hasFileChangedSinceUpload, saveUploadHash, isLocalFileMatchingRemote, isLocalFileMatchingDownloadHash, saveDownloadHash } from "./hashes";
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_BATCH_SIZE = 5;
|
|
9
12
|
|
|
10
13
|
export interface FileSyncOptions {
|
|
11
14
|
upload?: boolean;
|
|
@@ -15,6 +18,33 @@ export interface FileSyncOptions {
|
|
|
15
18
|
dryRun?: boolean;
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Run an array of async tasks in batches of `batchSize` at a time.
|
|
23
|
+
* Returns results in the same order as the input tasks.
|
|
24
|
+
*/
|
|
25
|
+
export async function batchRun<T>(
|
|
26
|
+
tasks: (() => Promise<T>)[],
|
|
27
|
+
batchSize: number = DEFAULT_BATCH_SIZE
|
|
28
|
+
): Promise<T[]> {
|
|
29
|
+
const results: T[] = [];
|
|
30
|
+
for (let i = 0; i < tasks.length; i += batchSize) {
|
|
31
|
+
const batch = tasks.slice(i, i + batchSize);
|
|
32
|
+
const batchResults = await Promise.all(batch.map((t) => t()));
|
|
33
|
+
results.push(...batchResults);
|
|
34
|
+
}
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Expands a leading ~ to the user's home directory
|
|
40
|
+
*/
|
|
41
|
+
function expandHome(p: string): string {
|
|
42
|
+
if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
|
|
43
|
+
return path.join(os.homedir(), p.slice(1));
|
|
44
|
+
}
|
|
45
|
+
return p;
|
|
46
|
+
}
|
|
47
|
+
|
|
18
48
|
/**
|
|
19
49
|
* Returns true if the path looks like a directory (ends with /)
|
|
20
50
|
*/
|
|
@@ -25,7 +55,7 @@ function isDirectoryPath(p: string): boolean {
|
|
|
25
55
|
/**
|
|
26
56
|
* Recursively list all files in a local directory, returning relative paths
|
|
27
57
|
*/
|
|
28
|
-
function listFilesRecursively(dir: string): string[] {
|
|
58
|
+
export function listFilesRecursively(dir: string): string[] {
|
|
29
59
|
const results: string[] = [];
|
|
30
60
|
if (!fs.existsSync(dir)) return results;
|
|
31
61
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
@@ -83,7 +113,8 @@ export async function fileSync(options: FileSyncOptions = {}) {
|
|
|
83
113
|
|
|
84
114
|
// Process each file mount
|
|
85
115
|
for (const mount of config.files) {
|
|
86
|
-
const { remotePath, localPath, direction = "download" } = mount;
|
|
116
|
+
const { remotePath, localPath: rawLocalPath, direction = "download" } = mount;
|
|
117
|
+
const localPath = expandHome(rawLocalPath);
|
|
87
118
|
|
|
88
119
|
// Determine actual direction based on flags and config
|
|
89
120
|
let actualDirection = direction;
|
|
@@ -126,16 +157,16 @@ export async function fileSync(options: FileSyncOptions = {}) {
|
|
|
126
157
|
}
|
|
127
158
|
}
|
|
128
159
|
|
|
129
|
-
|
|
130
160
|
/**
|
|
131
161
|
* Download a file from Knowhow FS to local filesystem
|
|
132
162
|
*/
|
|
133
|
-
async function downloadFile(
|
|
163
|
+
export async function downloadFile(
|
|
134
164
|
client: KnowhowSimpleClient,
|
|
135
165
|
s3Service: S3Service,
|
|
136
166
|
remotePath: string,
|
|
137
167
|
localPath: string,
|
|
138
|
-
dryRun: boolean
|
|
168
|
+
dryRun: boolean,
|
|
169
|
+
hashes?: any
|
|
139
170
|
): Promise<void> {
|
|
140
171
|
console.log(`⬇️ Downloading ${remotePath} → ${localPath}`);
|
|
141
172
|
|
|
@@ -146,8 +177,7 @@ async function downloadFile(
|
|
|
146
177
|
|
|
147
178
|
try {
|
|
148
179
|
// Fast-path: check stored download hash before hitting the API
|
|
149
|
-
|
|
150
|
-
if (await isLocalFileMatchingDownloadHash(localPath, hashes)) {
|
|
180
|
+
if (hashes && await isLocalFileMatchingDownloadHash(localPath, hashes)) {
|
|
151
181
|
console.log(` ✓ Skipping ${localPath} (matches stored download hash)`);
|
|
152
182
|
return;
|
|
153
183
|
}
|
|
@@ -159,7 +189,7 @@ async function downloadFile(
|
|
|
159
189
|
if (isLocalFileMatchingRemote(localPath, checksumSHA256)) {
|
|
160
190
|
console.log(` ✓ Skipping ${localPath} (matches remote checksum)`);
|
|
161
191
|
// Store the hash so future syncs can skip without hitting the API
|
|
162
|
-
await saveDownloadHash(localPath);
|
|
192
|
+
await saveDownloadHash(localPath, hashes);
|
|
163
193
|
return;
|
|
164
194
|
}
|
|
165
195
|
|
|
@@ -173,7 +203,7 @@ async function downloadFile(
|
|
|
173
203
|
await s3Service.downloadFromPresignedUrl(downloadUrl, localPath);
|
|
174
204
|
|
|
175
205
|
// Save download hash so we can skip unchanged files next time
|
|
176
|
-
await saveDownloadHash(localPath);
|
|
206
|
+
await saveDownloadHash(localPath, hashes);
|
|
177
207
|
|
|
178
208
|
// Get file size for logging
|
|
179
209
|
const stats = fs.statSync(localPath);
|
|
@@ -186,12 +216,13 @@ async function downloadFile(
|
|
|
186
216
|
/**
|
|
187
217
|
* Upload a file from local filesystem to Knowhow FS
|
|
188
218
|
*/
|
|
189
|
-
async function uploadFile(
|
|
219
|
+
export async function uploadFile(
|
|
190
220
|
client: KnowhowSimpleClient,
|
|
191
221
|
s3Service: S3Service,
|
|
192
222
|
remotePath: string,
|
|
193
223
|
localPath: string,
|
|
194
|
-
dryRun: boolean
|
|
224
|
+
dryRun: boolean,
|
|
225
|
+
hashes?: any
|
|
195
226
|
): Promise<void> {
|
|
196
227
|
console.log(`⬆️ Uploading ${localPath} → ${remotePath}`);
|
|
197
228
|
|
|
@@ -207,15 +238,14 @@ async function uploadFile(
|
|
|
207
238
|
}
|
|
208
239
|
|
|
209
240
|
// Skip upload if file hasn't changed since last upload
|
|
210
|
-
const
|
|
211
|
-
const changed = await hasFileChangedSinceUpload(localPath, hashes);
|
|
241
|
+
const changed = hashes ? await hasFileChangedSinceUpload(localPath, hashes) : true;
|
|
212
242
|
if (!changed) {
|
|
213
243
|
console.log(` ✓ Skipping ${localPath} (unchanged since last upload)`);
|
|
214
244
|
return;
|
|
215
245
|
}
|
|
216
246
|
|
|
217
247
|
// Get presigned upload URL
|
|
218
|
-
const presignedUrl = await client.getOrgFilePresignedUploadUrl(remotePath);
|
|
248
|
+
const presignedUrl = await client.getOrgFilePresignedUploadUrl(remotePath, localPath);
|
|
219
249
|
|
|
220
250
|
// Upload file using presigned URL
|
|
221
251
|
await s3Service.uploadToPresignedUrl(presignedUrl, localPath);
|
|
@@ -224,7 +254,7 @@ async function uploadFile(
|
|
|
224
254
|
await client.markOrgFileUploadComplete(remotePath);
|
|
225
255
|
|
|
226
256
|
// Save upload hash so we can skip unchanged files next time
|
|
227
|
-
await saveUploadHash(localPath);
|
|
257
|
+
await saveUploadHash(localPath, hashes);
|
|
228
258
|
|
|
229
259
|
const stats = fs.statSync(localPath);
|
|
230
260
|
console.log(` ✓ Uploaded ${stats.size} bytes`);
|
|
@@ -246,6 +276,8 @@ export async function uploadDirectory(
|
|
|
246
276
|
|
|
247
277
|
console.log(`⬆️ Uploading directory ${localDir} → ${remoteDir}`);
|
|
248
278
|
|
|
279
|
+
const hashes = await getHashes();
|
|
280
|
+
|
|
249
281
|
if (!fs.existsSync(localDir)) {
|
|
250
282
|
console.warn(` ⚠️ Local directory not found: ${localDir}`);
|
|
251
283
|
return 0;
|
|
@@ -261,26 +293,30 @@ export async function uploadDirectory(
|
|
|
261
293
|
|
|
262
294
|
console.log(` Found ${localFiles.length} local file(s)`);
|
|
263
295
|
|
|
264
|
-
|
|
265
|
-
for (const relFile of localFiles) {
|
|
296
|
+
const tasks = localFiles.map((relFile) => async () => {
|
|
266
297
|
const localFilePath = localDir + relFile;
|
|
267
298
|
const remoteFilePath = remoteDir + relFile;
|
|
268
299
|
try {
|
|
269
|
-
await uploadFile(client, s3Service, remoteFilePath, localFilePath, dryRun);
|
|
270
|
-
|
|
300
|
+
await uploadFile(client, s3Service, remoteFilePath, localFilePath, dryRun, hashes);
|
|
301
|
+
return 1;
|
|
271
302
|
} catch (error) {
|
|
272
303
|
console.error(
|
|
273
304
|
` ❌ Failed to upload ${localFilePath}, skipping: ${error.message}`
|
|
274
305
|
);
|
|
306
|
+
return 0;
|
|
275
307
|
}
|
|
276
|
-
}
|
|
277
|
-
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const counts = await batchRun(tasks);
|
|
311
|
+
await saveHashes(hashes);
|
|
312
|
+
|
|
313
|
+
return counts.reduce((sum, n) => sum + n, 0);
|
|
278
314
|
}
|
|
279
315
|
|
|
280
316
|
/**
|
|
281
317
|
* Download all files from a remote directory path to a local directory
|
|
282
318
|
*/
|
|
283
|
-
async function downloadDirectory(
|
|
319
|
+
export async function downloadDirectory(
|
|
284
320
|
client: KnowhowSimpleClient,
|
|
285
321
|
s3Service: S3Service,
|
|
286
322
|
remotePath: string,
|
|
@@ -293,6 +329,8 @@ async function downloadDirectory(
|
|
|
293
329
|
|
|
294
330
|
console.log(`⬇️ Downloading directory ${remoteDir} → ${localDir}`);
|
|
295
331
|
|
|
332
|
+
const hashes = await getHashes();
|
|
333
|
+
|
|
296
334
|
// List all org files and find those in the remote directory
|
|
297
335
|
const response = await client.listOrgFiles();
|
|
298
336
|
const allFiles = response.data;
|
|
@@ -313,16 +351,19 @@ async function downloadDirectory(
|
|
|
313
351
|
|
|
314
352
|
console.log(` Found ${matchingFiles.length} remote file(s)`);
|
|
315
353
|
|
|
316
|
-
|
|
317
|
-
for (const f of matchingFiles) {
|
|
354
|
+
const tasks = matchingFiles.map((f) => async () => {
|
|
318
355
|
const fullRemotePath = f.folderPath.endsWith("/")
|
|
319
356
|
? f.folderPath + f.fileName
|
|
320
357
|
: f.folderPath + "/" + f.fileName;
|
|
321
358
|
// Strip the base remote dir prefix to get relative path
|
|
322
359
|
const relativePath = fullRemotePath.slice(remoteDir.length);
|
|
323
360
|
const localFilePath = localDir + relativePath;
|
|
324
|
-
await downloadFile(client, s3Service, fullRemotePath, localFilePath, dryRun);
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
|
|
361
|
+
await downloadFile(client, s3Service, fullRemotePath, localFilePath, dryRun, hashes);
|
|
362
|
+
return 1;
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const counts = await batchRun(tasks);
|
|
366
|
+
await saveHashes(hashes);
|
|
367
|
+
|
|
368
|
+
return counts.reduce((sum, n) => sum + n, 0);
|
|
328
369
|
}
|
package/src/hashes.ts
CHANGED
|
@@ -1,16 +1,35 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import * as crypto from "crypto";
|
|
3
3
|
import { Hashes } from "./types";
|
|
4
|
-
import { readFile
|
|
4
|
+
import { readFile } from "./utils";
|
|
5
5
|
import { convertToText } from "./conversion";
|
|
6
6
|
|
|
7
7
|
export async function getHashes() {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
try {
|
|
9
|
+
const hashes = JSON.parse(await readFile(".knowhow/.hashes.json", "utf8"));
|
|
10
|
+
return hashes as Hashes;
|
|
11
|
+
} catch (err: any) {
|
|
12
|
+
if (err.code === "ENOENT") {
|
|
13
|
+
return {} as Hashes;
|
|
14
|
+
}
|
|
15
|
+
throw err;
|
|
16
|
+
}
|
|
10
17
|
}
|
|
11
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Atomically save hashes to disk — writes to a temp file then renames,
|
|
21
|
+
* preventing concurrent writes from producing corrupted/truncated JSON.
|
|
22
|
+
*/
|
|
12
23
|
export async function saveHashes(hashes: any) {
|
|
13
|
-
|
|
24
|
+
const target = ".knowhow/.hashes.json";
|
|
25
|
+
const tmp = `${target}.tmp.${process.pid}`;
|
|
26
|
+
try {
|
|
27
|
+
fs.writeFileSync(tmp, JSON.stringify(hashes, null, 2));
|
|
28
|
+
fs.renameSync(tmp, target);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
try { fs.unlinkSync(tmp); } catch (_) {}
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
14
33
|
}
|
|
15
34
|
|
|
16
35
|
export async function md5Hash(str: string) {
|
|
@@ -90,17 +109,19 @@ export async function hasFileChangedSinceUpload(
|
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
/**
|
|
93
|
-
*
|
|
112
|
+
* Mutates the provided hashes object with the upload hash for localPath.
|
|
113
|
+
* If no hashes object is provided, loads, mutates, and saves independently.
|
|
94
114
|
*/
|
|
95
|
-
export async function saveUploadHash(localPath: string) {
|
|
96
|
-
const
|
|
115
|
+
export async function saveUploadHash(localPath: string, hashes?: any) {
|
|
116
|
+
const standalone = !hashes;
|
|
117
|
+
if (standalone) hashes = await getHashes();
|
|
97
118
|
const content = fs.readFileSync(localPath);
|
|
98
119
|
const currentHash = crypto.createHash("md5").update(content).digest("hex");
|
|
99
120
|
if (!hashes[localPath]) {
|
|
100
121
|
hashes[localPath] = { fileHash: currentHash, promptHash: "" };
|
|
101
122
|
}
|
|
102
123
|
hashes[localPath][UPLOAD_KEY] = currentHash;
|
|
103
|
-
await saveHashes(hashes);
|
|
124
|
+
if (standalone) await saveHashes(hashes);
|
|
104
125
|
}
|
|
105
126
|
|
|
106
127
|
/**
|
|
@@ -120,18 +141,19 @@ export async function isLocalFileMatchingDownloadHash(
|
|
|
120
141
|
}
|
|
121
142
|
|
|
122
143
|
/**
|
|
123
|
-
*
|
|
124
|
-
*
|
|
144
|
+
* Mutates the provided hashes object with the download hash for localPath.
|
|
145
|
+
* If no hashes object is provided, loads, mutates, and saves independently.
|
|
125
146
|
*/
|
|
126
|
-
export async function saveDownloadHash(localPath: string) {
|
|
127
|
-
const
|
|
147
|
+
export async function saveDownloadHash(localPath: string, hashes?: any) {
|
|
148
|
+
const standalone = !hashes;
|
|
149
|
+
if (standalone) hashes = await getHashes();
|
|
128
150
|
const content = fs.readFileSync(localPath);
|
|
129
151
|
const currentHash = crypto.createHash("sha256").update(content).digest("base64");
|
|
130
152
|
if (!hashes[localPath]) {
|
|
131
153
|
hashes[localPath] = { fileHash: currentHash, promptHash: "" };
|
|
132
154
|
}
|
|
133
155
|
hashes[localPath][DOWNLOAD_KEY] = currentHash;
|
|
134
|
-
await saveHashes(hashes);
|
|
156
|
+
if (standalone) await saveHashes(hashes);
|
|
135
157
|
}
|
|
136
158
|
|
|
137
159
|
/**
|
package/src/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ export * as ai from "./ai";
|
|
|
53
53
|
|
|
54
54
|
// Export module system types for external modules
|
|
55
55
|
export * from "./services/modules/types";
|
|
56
|
+
export { ModulesService } from "./services/modules";
|
|
56
57
|
// Export plugin types for external plugins
|
|
57
58
|
export { PluginBase } from "./plugins/PluginBase";
|
|
58
59
|
export { PluginMeta, Plugin, PluginContext } from "./plugins/types";
|
|
@@ -138,6 +139,23 @@ export async function upload() {
|
|
|
138
139
|
if (!source.remoteId) {
|
|
139
140
|
throw new Error("remoteId is required for knowhow uploads");
|
|
140
141
|
}
|
|
142
|
+
// Warn if the local embeddingModel differs from the one stored on the backend
|
|
143
|
+
try {
|
|
144
|
+
const remoteEmbedding = await knowhowApiClient.getOrgEmbedding(source.remoteId);
|
|
145
|
+
const localModel = config.embeddingModel || EmbeddingModels.openai.EmbeddingAda2;
|
|
146
|
+
const remoteModel = remoteEmbedding?.modelName;
|
|
147
|
+
if (remoteModel && remoteModel !== localModel) {
|
|
148
|
+
console.warn(
|
|
149
|
+
`⚠️ WARNING: Embedding model mismatch for "${remoteEmbedding.name}" (remoteId: ${source.remoteId}).\n` +
|
|
150
|
+
` Local config.embeddingModel: ${localModel}\n` +
|
|
151
|
+
` Backend embedding modelName: ${remoteModel}\n` +
|
|
152
|
+
` Vectors generated with different models are not comparable — search results will be incorrect.\n` +
|
|
153
|
+
` Update your config.embeddingModel to "${remoteModel}" or update the backend embedding to "${localModel}".`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
} catch (e) {
|
|
157
|
+
// Non-fatal — don't block upload if metadata fetch fails
|
|
158
|
+
}
|
|
141
159
|
const url = await knowhowApiClient.getPresignedUploadUrl(source);
|
|
142
160
|
console.log("Uploading to", url);
|
|
143
161
|
await AwsS3.uploadToPresignedUrl(url, source.output);
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { LogLevel } from "./services/EventService";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* App-wide logger utility.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* 1. `logger.info/warn/error(source, message)` — routes through EventService
|
|
8
|
+
* 2. `Logger.of("ClassName")` — creates a bound logger so you don't repeat the source
|
|
9
|
+
* 3. `logger.installConsoleOverload()` — replaces console.log/warn/error/info with
|
|
10
|
+
* our closure, so ALL output (including third-party modules) goes through us
|
|
11
|
+
* 4. `logger.silence()` / `logger.unsilence()` — suppress all output, useful for
|
|
12
|
+
* commands that need clean stdout (e.g. github-credentials)
|
|
13
|
+
*
|
|
14
|
+
* Usage (module-level):
|
|
15
|
+
* import { logger } from "../logger";
|
|
16
|
+
* logger.info("MyService", "Something happened");
|
|
17
|
+
*
|
|
18
|
+
* Usage (class-level):
|
|
19
|
+
* import { Logger } from "../logger";
|
|
20
|
+
* class MyClass {
|
|
21
|
+
* private logger = Logger.of("MyClass");
|
|
22
|
+
* doThing() { this.logger.info("Something happened"); }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* Silence mode (for clean-stdout commands):
|
|
26
|
+
* logger.silence(); // suppress everything
|
|
27
|
+
* // ... do work that must produce clean stdout ...
|
|
28
|
+
* logger.unsilence(); // restore
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
// ---- Internal state ---------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
let silenced = false;
|
|
34
|
+
|
|
35
|
+
// Original console methods — saved before any overload is installed
|
|
36
|
+
const _originalConsole = {
|
|
37
|
+
log: console.log.bind(console),
|
|
38
|
+
warn: console.warn.bind(console),
|
|
39
|
+
error: console.error.bind(console),
|
|
40
|
+
info: console.info.bind(console),
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
let consoleOverloadInstalled = false;
|
|
44
|
+
|
|
45
|
+
// ---- EventService lazy accessor ---------------------------------------------
|
|
46
|
+
|
|
47
|
+
function getEvents() {
|
|
48
|
+
try {
|
|
49
|
+
const { services } = require("./services") as typeof import("./services");
|
|
50
|
+
return services().Events;
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---- Core emit logic --------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
function emit(source: string, message: string, level: LogLevel): void {
|
|
59
|
+
if (silenced) return;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const events = getEvents();
|
|
63
|
+
if (events) {
|
|
64
|
+
events.log(source, message, level);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
} catch {
|
|
68
|
+
// fall through to direct console output
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Fallback: use original console methods (bypasses any overload we installed)
|
|
72
|
+
const prefix = source ? `[${source}] ` : "";
|
|
73
|
+
if (level === "warn") _originalConsole.warn(`${prefix}${message}`);
|
|
74
|
+
else if (level === "error") _originalConsole.error(`${prefix}${message}`);
|
|
75
|
+
else _originalConsole.log(`${prefix}${message}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ---- Bound logger (returned by Logger.of) -----------------------------------
|
|
79
|
+
|
|
80
|
+
export interface BoundLogger {
|
|
81
|
+
log(message: string, level?: LogLevel): void;
|
|
82
|
+
info(message: string): void;
|
|
83
|
+
warn(message: string): void;
|
|
84
|
+
error(message: string): void;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function makeBoundLogger(source: string): BoundLogger {
|
|
88
|
+
return {
|
|
89
|
+
log(message: string, level: LogLevel = "info"): void {
|
|
90
|
+
emit(source, message, level);
|
|
91
|
+
},
|
|
92
|
+
info(message: string): void {
|
|
93
|
+
emit(source, message, "info");
|
|
94
|
+
},
|
|
95
|
+
warn(message: string): void {
|
|
96
|
+
emit(source, message, "warn");
|
|
97
|
+
},
|
|
98
|
+
error(message: string): void {
|
|
99
|
+
emit(source, message, "error");
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ---- Public API -------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
export const logger = {
|
|
107
|
+
log(source: string, message: string, level: LogLevel = "info"): void {
|
|
108
|
+
emit(source, message, level);
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
info(source: string, message: string): void {
|
|
112
|
+
emit(source, message, "info");
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
warn(source: string, message: string): void {
|
|
116
|
+
emit(source, message, "warn");
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
error(source: string, message: string): void {
|
|
120
|
+
emit(source, message, "error");
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Suppress all log output. Useful for commands that need clean stdout
|
|
125
|
+
* (e.g. git credential helpers). All logger.* calls and overloaded
|
|
126
|
+
* console.* calls become no-ops until unsilence() is called.
|
|
127
|
+
*/
|
|
128
|
+
silence(): void {
|
|
129
|
+
silenced = true;
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Restore log output after a silence() call.
|
|
134
|
+
*/
|
|
135
|
+
unsilence(): void {
|
|
136
|
+
silenced = false;
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns true if the logger is currently silenced.
|
|
141
|
+
*/
|
|
142
|
+
isSilenced(): boolean {
|
|
143
|
+
return silenced;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Install console overload. After this call, console.log/warn/error/info
|
|
148
|
+
* all route through our closure (respecting silence mode).
|
|
149
|
+
* Safe to call multiple times — only installs once.
|
|
150
|
+
*
|
|
151
|
+
* Call this early in CLI startup (before any modules are loaded) to ensure
|
|
152
|
+
* third-party module logs don't bypass the silence mechanism.
|
|
153
|
+
*/
|
|
154
|
+
installConsoleOverload(): void {
|
|
155
|
+
if (consoleOverloadInstalled) return;
|
|
156
|
+
consoleOverloadInstalled = true;
|
|
157
|
+
|
|
158
|
+
const route = (originalFn: (...args: any[]) => void, args: any[]) => {
|
|
159
|
+
if (silenced) return;
|
|
160
|
+
originalFn(...args);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
console.log = (...args: any[]) => route(_originalConsole.log, args);
|
|
164
|
+
console.info = (...args: any[]) => route(_originalConsole.info, args);
|
|
165
|
+
console.warn = (...args: any[]) => route(_originalConsole.warn, args);
|
|
166
|
+
// Note: console.error is intentionally NOT overloaded — real errors (stack
|
|
167
|
+
// traces, crash reports) should always be visible. Only suppress via silence().
|
|
168
|
+
// If you want to suppress errors too, call logger.silence() which checks the flag
|
|
169
|
+
// before the overloaded console.warn/log routes reach here anyway.
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Remove the console overload and restore original console methods.
|
|
174
|
+
*/
|
|
175
|
+
uninstallConsoleOverload(): void {
|
|
176
|
+
if (!consoleOverloadInstalled) return;
|
|
177
|
+
console.log = _originalConsole.log;
|
|
178
|
+
console.info = _originalConsole.info;
|
|
179
|
+
console.warn = _originalConsole.warn;
|
|
180
|
+
consoleOverloadInstalled = false;
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Factory for creating a bound logger with a fixed source name.
|
|
186
|
+
* Ideal for class-level loggers:
|
|
187
|
+
*
|
|
188
|
+
* class MyClass {
|
|
189
|
+
* private logger = Logger.of("MyClass");
|
|
190
|
+
* doThing() { this.logger.info("hello"); }
|
|
191
|
+
* }
|
|
192
|
+
*/
|
|
193
|
+
export const Logger = {
|
|
194
|
+
of(source: string): BoundLogger {
|
|
195
|
+
return makeBoundLogger(source);
|
|
196
|
+
},
|
|
197
|
+
};
|
package/src/plugins/embedding.ts
CHANGED
|
@@ -20,9 +20,12 @@ export class EmbeddingPlugin extends PluginBase {
|
|
|
20
20
|
|
|
21
21
|
constructor(context) {
|
|
22
22
|
super(context);
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
// Subscribe to file:post-edit events
|
|
25
|
-
this.context.Events.on(
|
|
25
|
+
this.context.Events.on(
|
|
26
|
+
"file:post-edit",
|
|
27
|
+
this.handleFilePostEdit.bind(this)
|
|
28
|
+
);
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
async embed() {
|
|
@@ -68,10 +71,12 @@ export class EmbeddingPlugin extends PluginBase {
|
|
|
68
71
|
this.log(`Reading entry ${entry.id}`);
|
|
69
72
|
}
|
|
70
73
|
|
|
71
|
-
const
|
|
74
|
+
const ids = context.map((entry) => entry.id);
|
|
75
|
+
|
|
76
|
+
const contextLength = JSON.stringify(ids).split(" ").length;
|
|
72
77
|
this.log(`Found ${context.length} entries. Loading ${contextLength} words`);
|
|
73
78
|
|
|
74
|
-
return `EMBEDDING PLUGIN: Our knowledgebase
|
|
75
|
-
${JSON.stringify(
|
|
79
|
+
return `EMBEDDING PLUGIN: Our knowledgebase indicates these embedding entries may be related to the question:
|
|
80
|
+
${JSON.stringify(ids)}`;
|
|
76
81
|
}
|
|
77
|
-
}
|
|
82
|
+
}
|
package/src/plugins/plugins.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Plugin, PluginContext } from "./types";
|
|
2
|
-
import { Config } from "../types";
|
|
3
2
|
import { VimPlugin } from "./vim";
|
|
4
3
|
import { LinterPlugin } from "./LinterPlugin";
|
|
5
4
|
import { LanguagePlugin } from "./language";
|
|
@@ -49,26 +48,6 @@ export class PluginService {
|
|
|
49
48
|
return instance.meta.key;
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
/**
|
|
53
|
-
* Load plugins from config's pluginPackages map.
|
|
54
|
-
* Each entry maps a plugin key to an npm package name or file path.
|
|
55
|
-
* Errors are caught and logged as warnings without crashing.
|
|
56
|
-
*/
|
|
57
|
-
async loadPluginsFromConfig(config: Config): Promise<void> {
|
|
58
|
-
const pluginPackages = config.pluginPackages || {};
|
|
59
|
-
for (const [key, spec] of Object.entries(pluginPackages)) {
|
|
60
|
-
try {
|
|
61
|
-
await this.loadPlugin(spec);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
this.events?.log(
|
|
64
|
-
"PluginService",
|
|
65
|
-
`Failed to load plugin "${key}" from "${spec}": ${error instanceof Error ? error.message : error}`,
|
|
66
|
-
"warn"
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
51
|
/** Disable a plugin by its key; returns `true` if found. */
|
|
73
52
|
disablePlugin(key: string): boolean {
|
|
74
53
|
const p = this.pluginMap.get(key);
|
package/src/plugins/vim.ts
CHANGED
|
@@ -73,22 +73,11 @@ export class VimPlugin extends PluginBase {
|
|
|
73
73
|
|
|
74
74
|
async call() {
|
|
75
75
|
const vimFiles = await this.getVimFiles();
|
|
76
|
-
const fileContents =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
loaded.content.length > 1000
|
|
82
|
-
? loaded.content.slice(0, 1000) +
|
|
83
|
-
"... file trimmed, read file for full content"
|
|
84
|
-
: loaded.content;
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
sourceFile: loaded.filePath,
|
|
88
|
-
content: loaded.content.slice(0, 1000),
|
|
89
|
-
};
|
|
90
|
-
})
|
|
91
|
-
);
|
|
76
|
+
const fileContents = vimFiles.map((f) => {
|
|
77
|
+
return {
|
|
78
|
+
sourceFile: f,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
92
81
|
if (fileContents.length === 0) {
|
|
93
82
|
return "VIM PLUGIN: No files open in vim";
|
|
94
83
|
}
|