@jinion/core 0.3.0 → 0.4.0
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/agent/claude/backend.d.ts +4 -0
- package/dist/agent/claude/backend.d.ts.map +1 -1
- package/dist/agent/claude/backend.js.map +1 -1
- package/dist/agent/claude/events.js +1 -1
- package/dist/agent/claude/events.js.map +1 -1
- package/dist/agent/claude/guard.d.ts.map +1 -1
- package/dist/agent/claude/guard.js +2 -1
- package/dist/agent/claude/guard.js.map +1 -1
- package/dist/agent/claude/jinion-tools.d.ts +9 -1
- package/dist/agent/claude/jinion-tools.d.ts.map +1 -1
- package/dist/agent/claude/jinion-tools.js +14 -2
- package/dist/agent/claude/jinion-tools.js.map +1 -1
- package/dist/agent/claude/mcp.d.ts.map +1 -1
- package/dist/agent/claude/mcp.js +21 -1
- package/dist/agent/claude/mcp.js.map +1 -1
- package/dist/agent/claude/options.d.ts +9 -1
- package/dist/agent/claude/options.d.ts.map +1 -1
- package/dist/agent/claude/options.js +5 -3
- package/dist/agent/claude/options.js.map +1 -1
- package/dist/agent/claude/paths.d.ts +0 -3
- package/dist/agent/claude/paths.d.ts.map +1 -1
- package/dist/agent/claude/paths.js +1 -7
- package/dist/agent/claude/paths.js.map +1 -1
- package/dist/agent/claude/permissions.js +1 -1
- package/dist/agent/claude/permissions.js.map +1 -1
- package/dist/agent/claude/prompt.d.ts +2 -1
- package/dist/agent/claude/prompt.d.ts.map +1 -1
- package/dist/agent/claude/prompt.js +10 -5
- package/dist/agent/claude/prompt.js.map +1 -1
- package/dist/agent/claude/review.d.ts +4 -1
- package/dist/agent/claude/review.d.ts.map +1 -1
- package/dist/agent/claude/review.js +5 -2
- package/dist/agent/claude/review.js.map +1 -1
- package/dist/agent/claude/session.d.ts +7 -0
- package/dist/agent/claude/session.d.ts.map +1 -1
- package/dist/agent/claude/session.js +6 -1
- package/dist/agent/claude/session.js.map +1 -1
- package/dist/agent/claude/tool-calls.d.ts.map +1 -1
- package/dist/agent/claude/tool-calls.js +11 -2
- package/dist/agent/claude/tool-calls.js.map +1 -1
- package/dist/agent/codex/backend.d.ts +4 -0
- package/dist/agent/codex/backend.d.ts.map +1 -1
- package/dist/agent/codex/backend.js.map +1 -1
- package/dist/agent/codex/events.d.ts.map +1 -1
- package/dist/agent/codex/events.js +15 -1
- package/dist/agent/codex/events.js.map +1 -1
- package/dist/agent/codex/jinion-tools.d.ts +38 -4
- package/dist/agent/codex/jinion-tools.d.ts.map +1 -1
- package/dist/agent/codex/jinion-tools.js +57 -10
- package/dist/agent/codex/jinion-tools.js.map +1 -1
- package/dist/agent/codex/mcp.d.ts.map +1 -1
- package/dist/agent/codex/mcp.js +4 -0
- package/dist/agent/codex/mcp.js.map +1 -1
- package/dist/agent/codex/rewind.js +1 -47
- package/dist/agent/codex/rewind.js.map +1 -1
- package/dist/agent/codex/session.d.ts +9 -2
- package/dist/agent/codex/session.d.ts.map +1 -1
- package/dist/agent/codex/session.js +21 -7
- package/dist/agent/codex/session.js.map +1 -1
- package/dist/agent/demo/mcp.d.ts +2 -0
- package/dist/agent/demo/mcp.d.ts.map +1 -1
- package/dist/agent/demo/mcp.js +14 -0
- package/dist/agent/demo/mcp.js.map +1 -1
- package/dist/agent/demo/scenarios/pricing-card.d.ts +3 -0
- package/dist/agent/demo/scenarios/pricing-card.d.ts.map +1 -0
- package/dist/agent/demo/scenarios/pricing-card.js +43 -0
- package/dist/agent/demo/scenarios/pricing-card.js.map +1 -0
- package/dist/agent/demo/script.d.ts +6 -0
- package/dist/agent/demo/script.d.ts.map +1 -1
- package/dist/agent/demo/tasks.d.ts +3 -0
- package/dist/agent/demo/tasks.d.ts.map +1 -1
- package/dist/agent/events.d.ts +3 -0
- package/dist/agent/events.d.ts.map +1 -1
- package/dist/agent/events.js +2 -0
- package/dist/agent/events.js.map +1 -1
- package/dist/agent/mcp.d.ts +5 -0
- package/dist/agent/mcp.d.ts.map +1 -1
- package/dist/agent/mcp.js +2 -0
- package/dist/agent/mcp.js.map +1 -1
- package/dist/agent/patches.d.ts +5 -0
- package/dist/agent/patches.d.ts.map +1 -1
- package/dist/agent/patches.js +49 -0
- package/dist/agent/patches.js.map +1 -1
- package/dist/agent/review-tools.d.ts +15 -0
- package/dist/agent/review-tools.d.ts.map +1 -0
- package/dist/agent/review-tools.js +13 -0
- package/dist/agent/review-tools.js.map +1 -0
- package/dist/agent/review.d.ts +18 -6
- package/dist/agent/review.d.ts.map +1 -1
- package/dist/agent/review.js +52 -17
- package/dist/agent/review.js.map +1 -1
- package/dist/api/client.d.ts +15 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +14 -3
- package/dist/api/client.js.map +1 -1
- package/dist/api/connection.d.ts +5 -0
- package/dist/api/connection.d.ts.map +1 -1
- package/dist/api/connection.js +6 -0
- package/dist/api/connection.js.map +1 -1
- package/dist/api/fields.d.ts +3 -1
- package/dist/api/fields.d.ts.map +1 -1
- package/dist/api/fields.js +3 -2
- package/dist/api/fields.js.map +1 -1
- package/dist/api/json-schema.d.ts +592 -89
- package/dist/api/json-schema.d.ts.map +1 -1
- package/dist/api/json-schema.js +2 -1
- package/dist/api/json-schema.js.map +1 -1
- package/dist/api/methods/accounts.d.ts.map +1 -1
- package/dist/api/methods/accounts.js +1 -2
- package/dist/api/methods/accounts.js.map +1 -1
- package/dist/api/methods/app.d.ts.map +1 -1
- package/dist/api/methods/app.js +9 -5
- package/dist/api/methods/app.js.map +1 -1
- package/dist/api/methods/files.d.ts +3 -1
- package/dist/api/methods/files.d.ts.map +1 -1
- package/dist/api/methods/files.js +75 -2
- package/dist/api/methods/files.js.map +1 -1
- package/dist/api/methods/git.d.ts.map +1 -1
- package/dist/api/methods/git.js +54 -6
- package/dist/api/methods/git.js.map +1 -1
- package/dist/api/methods/lsp.d.ts +7 -0
- package/dist/api/methods/lsp.d.ts.map +1 -0
- package/dist/api/methods/lsp.js +68 -0
- package/dist/api/methods/lsp.js.map +1 -0
- package/dist/api/methods/preview.d.ts +4 -1
- package/dist/api/methods/preview.d.ts.map +1 -1
- package/dist/api/methods/preview.js +19 -3
- package/dist/api/methods/preview.js.map +1 -1
- package/dist/api/methods/terminals.d.ts.map +1 -1
- package/dist/api/methods/terminals.js +7 -1
- package/dist/api/methods/terminals.js.map +1 -1
- package/dist/api/protocol.d.ts +762 -7
- package/dist/api/protocol.d.ts.map +1 -1
- package/dist/api/protocol.js +126 -8
- package/dist/api/protocol.js.map +1 -1
- package/dist/api/schemas.d.ts +7 -0
- package/dist/api/schemas.d.ts.map +1 -1
- package/dist/api/schemas.js +4 -0
- package/dist/api/schemas.js.map +1 -1
- package/dist/api/screen.d.ts +2 -0
- package/dist/api/screen.d.ts.map +1 -1
- package/dist/api/screen.js +3 -0
- package/dist/api/screen.js.map +1 -1
- package/dist/api/server.d.ts +2 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +13 -0
- package/dist/api/server.js.map +1 -1
- package/dist/commands/builtin.d.ts.map +1 -1
- package/dist/commands/builtin.js +2 -0
- package/dist/commands/builtin.js.map +1 -1
- package/dist/commands/conversation.d.ts.map +1 -1
- package/dist/commands/conversation.js +2 -0
- package/dist/commands/conversation.js.map +1 -1
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +1 -0
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/notifications.d.ts.map +1 -1
- package/dist/commands/notifications.js +5 -3
- package/dist/commands/notifications.js.map +1 -1
- package/dist/commands/registry.d.ts +3 -0
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +14 -0
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/skill.d.ts +5 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +30 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/views.d.ts.map +1 -1
- package/dist/commands/views.js +5 -1
- package/dist/commands/views.js.map +1 -1
- package/dist/controllers/accounts.d.ts +5 -2
- package/dist/controllers/accounts.d.ts.map +1 -1
- package/dist/controllers/accounts.js +11 -8
- package/dist/controllers/accounts.js.map +1 -1
- package/dist/controllers/context.d.ts +2 -0
- package/dist/controllers/context.d.ts.map +1 -1
- package/dist/controllers/context.js.map +1 -1
- package/dist/controllers/feedback.d.ts +1 -1
- package/dist/controllers/feedback.d.ts.map +1 -1
- package/dist/controllers/feedback.js +4 -1
- package/dist/controllers/feedback.js.map +1 -1
- package/dist/controllers/input.d.ts.map +1 -1
- package/dist/controllers/input.js +2 -0
- package/dist/controllers/input.js.map +1 -1
- package/dist/controllers/jinion.d.ts +7 -0
- package/dist/controllers/jinion.d.ts.map +1 -1
- package/dist/controllers/jinion.js +7 -0
- package/dist/controllers/jinion.js.map +1 -1
- package/dist/controllers/mcp.d.ts +7 -2
- package/dist/controllers/mcp.d.ts.map +1 -1
- package/dist/controllers/mcp.js +23 -7
- package/dist/controllers/mcp.js.map +1 -1
- package/dist/controllers/session.d.ts.map +1 -1
- package/dist/controllers/session.js +4 -0
- package/dist/controllers/session.js.map +1 -1
- package/dist/conversation/activity.d.ts +5 -0
- package/dist/conversation/activity.d.ts.map +1 -0
- package/dist/conversation/activity.js +41 -0
- package/dist/conversation/activity.js.map +1 -0
- package/dist/conversation/apply-event.d.ts.map +1 -1
- package/dist/conversation/apply-event.js +2 -1
- package/dist/conversation/apply-event.js.map +1 -1
- package/dist/conversation/edits.d.ts +5 -0
- package/dist/conversation/edits.d.ts.map +1 -1
- package/dist/conversation/edits.js +10 -0
- package/dist/conversation/edits.js.map +1 -1
- package/dist/conversation/reducer.d.ts +9 -0
- package/dist/conversation/reducer.d.ts.map +1 -1
- package/dist/design/guides.d.ts +78 -5
- package/dist/design/guides.d.ts.map +1 -1
- package/dist/design/guides.js +78 -5
- package/dist/design/guides.js.map +1 -1
- package/dist/design/prompt.d.ts +1 -1
- package/dist/design/prompt.d.ts.map +1 -1
- package/dist/design/prompt.js +2 -2
- package/dist/design/prompt.js.map +1 -1
- package/dist/design/tools.d.ts +2 -0
- package/dist/design/tools.d.ts.map +1 -1
- package/dist/design/tools.js +6 -2
- package/dist/design/tools.js.map +1 -1
- package/dist/directions/directions.d.ts +42 -0
- package/dist/directions/directions.d.ts.map +1 -0
- package/dist/directions/directions.js +120 -0
- package/dist/directions/directions.js.map +1 -0
- package/dist/directions/store.d.ts +34 -0
- package/dist/directions/store.d.ts.map +1 -0
- package/dist/directions/store.js +61 -0
- package/dist/directions/store.js.map +1 -0
- package/dist/directions/tools.d.ts +29 -0
- package/dist/directions/tools.d.ts.map +1 -0
- package/dist/directions/tools.js +57 -0
- package/dist/directions/tools.js.map +1 -0
- package/dist/directions/viewer.d.ts +6 -0
- package/dist/directions/viewer.d.ts.map +1 -0
- package/dist/directions/viewer.js +266 -0
- package/dist/directions/viewer.js.map +1 -0
- package/dist/files/names.d.ts +6 -0
- package/dist/files/names.d.ts.map +1 -0
- package/dist/files/names.js +18 -0
- package/dist/files/names.js.map +1 -0
- package/dist/files/operations.d.ts +54 -0
- package/dist/files/operations.d.ts.map +1 -0
- package/dist/files/operations.js +173 -0
- package/dist/files/operations.js.map +1 -0
- package/dist/files/search.d.ts +11 -0
- package/dist/files/search.d.ts.map +1 -0
- package/dist/files/search.js +112 -0
- package/dist/files/search.js.map +1 -0
- package/dist/files/trash.d.ts +11 -0
- package/dist/files/trash.d.ts.map +1 -0
- package/dist/files/trash.js +64 -0
- package/dist/files/trash.js.map +1 -0
- package/dist/files/types.d.ts +112 -0
- package/dist/files/types.d.ts.map +1 -0
- package/dist/files/types.js +47 -0
- package/dist/files/types.js.map +1 -0
- package/dist/files/watch.d.ts +26 -0
- package/dist/files/watch.d.ts.map +1 -0
- package/dist/files/watch.js +107 -0
- package/dist/files/watch.js.map +1 -0
- package/dist/git/blame.d.ts +10 -0
- package/dist/git/blame.d.ts.map +1 -0
- package/dist/git/blame.js +91 -0
- package/dist/git/blame.js.map +1 -0
- package/dist/git/repos.d.ts +5 -0
- package/dist/git/repos.d.ts.map +1 -1
- package/dist/git/repos.js +13 -0
- package/dist/git/repos.js.map +1 -1
- package/dist/git/staging.d.ts +10 -1
- package/dist/git/staging.d.ts.map +1 -1
- package/dist/git/staging.js +21 -0
- package/dist/git/staging.js.map +1 -1
- package/dist/git/types.d.ts +48 -0
- package/dist/git/types.d.ts.map +1 -1
- package/dist/git/types.js +25 -0
- package/dist/git/types.js.map +1 -1
- package/dist/host.d.ts +2 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +8 -1
- package/dist/host.js.map +1 -1
- package/dist/lib/glob.d.ts +6 -0
- package/dist/lib/glob.d.ts.map +1 -0
- package/dist/lib/glob.js +49 -0
- package/dist/lib/glob.js.map +1 -0
- package/dist/lib/paths.d.ts +3 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +9 -1
- package/dist/lib/paths.js.map +1 -1
- package/dist/look/tools.d.ts +7 -1
- package/dist/look/tools.d.ts.map +1 -1
- package/dist/look/tools.js +19 -4
- package/dist/look/tools.js.map +1 -1
- package/dist/lsp/code-intelligence.d.ts +87 -0
- package/dist/lsp/code-intelligence.d.ts.map +1 -0
- package/dist/lsp/code-intelligence.js +343 -0
- package/dist/lsp/code-intelligence.js.map +1 -0
- package/dist/lsp/edits.d.ts +4 -0
- package/dist/lsp/edits.d.ts.map +1 -0
- package/dist/lsp/edits.js +14 -0
- package/dist/lsp/edits.js.map +1 -0
- package/dist/lsp/project-check.d.ts +8 -0
- package/dist/lsp/project-check.d.ts.map +1 -0
- package/dist/lsp/project-check.js +71 -0
- package/dist/lsp/project-check.js.map +1 -0
- package/dist/lsp/results.d.ts +95 -0
- package/dist/lsp/results.d.ts.map +1 -0
- package/dist/lsp/results.js +116 -0
- package/dist/lsp/results.js.map +1 -0
- package/dist/lsp/server.d.ts +22 -0
- package/dist/lsp/server.d.ts.map +1 -0
- package/dist/lsp/server.js +123 -0
- package/dist/lsp/server.js.map +1 -0
- package/dist/lsp/servers.d.ts +21 -0
- package/dist/lsp/servers.d.ts.map +1 -0
- package/dist/lsp/servers.js +57 -0
- package/dist/lsp/servers.js.map +1 -0
- package/dist/lsp/transport.d.ts +9 -0
- package/dist/lsp/transport.d.ts.map +1 -0
- package/dist/lsp/transport.js +64 -0
- package/dist/lsp/transport.js.map +1 -0
- package/dist/lsp/types.d.ts +262 -0
- package/dist/lsp/types.d.ts.map +1 -0
- package/dist/lsp/types.js +64 -0
- package/dist/lsp/types.js.map +1 -0
- package/dist/map/prompt.d.ts.map +1 -1
- package/dist/map/prompt.js +2 -1
- package/dist/map/prompt.js.map +1 -1
- package/dist/map/review.d.ts +29 -9
- package/dist/map/review.d.ts.map +1 -1
- package/dist/map/review.js +105 -25
- package/dist/map/review.js.map +1 -1
- package/dist/mcp/login.d.ts +2 -0
- package/dist/mcp/login.d.ts.map +1 -1
- package/dist/mcp/login.js +5 -0
- package/dist/mcp/login.js.map +1 -1
- package/dist/preview/pages.d.ts +17 -0
- package/dist/preview/pages.d.ts.map +1 -0
- package/dist/preview/pages.js +92 -0
- package/dist/preview/pages.js.map +1 -0
- package/dist/preview/previews.d.ts +22 -0
- package/dist/preview/previews.d.ts.map +1 -0
- package/dist/preview/previews.js +28 -0
- package/dist/preview/previews.js.map +1 -0
- package/dist/preview/prompt.d.ts +3 -0
- package/dist/preview/prompt.d.ts.map +1 -0
- package/dist/preview/prompt.js +5 -0
- package/dist/preview/prompt.js.map +1 -0
- package/dist/preview/tools.d.ts +21 -0
- package/dist/preview/tools.d.ts.map +1 -0
- package/dist/preview/tools.js +34 -0
- package/dist/preview/tools.js.map +1 -0
- package/dist/preview/types.d.ts +7 -0
- package/dist/preview/types.d.ts.map +1 -1
- package/dist/preview/types.js +2 -0
- package/dist/preview/types.js.map +1 -1
- package/dist/prompt/files.d.ts +4 -1
- package/dist/prompt/files.d.ts.map +1 -1
- package/dist/prompt/files.js +23 -8
- package/dist/prompt/files.js.map +1 -1
- package/dist/skills/tools.d.ts +26 -0
- package/dist/skills/tools.d.ts.map +1 -0
- package/dist/skills/tools.js +34 -0
- package/dist/skills/tools.js.map +1 -0
- package/dist/state/session.d.ts +4 -0
- package/dist/state/session.d.ts.map +1 -1
- package/dist/state/session.js +1 -0
- package/dist/state/session.js.map +1 -1
- package/package.json +3 -1
- package/schema/api.json +3016 -45
- package/vendor/darwin-arm64/build.json +62 -0
- package/vendor/darwin-arm64/ffmpeg +0 -0
- package/vendor/darwin-arm64/ffprobe +0 -0
- package/vendor/darwin-arm64/licenses/README.md +13 -0
- package/vendor/darwin-arm64/licenses/ffmpeg-LGPL-2.1.txt +502 -0
- package/vendor/darwin-arm64/licenses/whisper.cpp-MIT.txt +21 -0
- package/vendor/darwin-arm64/voices.bin +0 -0
- package/vendor/darwin-arm64/whisper-cli +0 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { readFile, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { matchesGlob } from '../lib/glob.js';
|
|
4
|
+
import { listProjectFiles } from '../prompt/files.js';
|
|
5
|
+
// Large enough for any source file; a bigger one is data, a bundle or a log, and would slow every search down.
|
|
6
|
+
const MAX_BYTES = 1024 * 1024;
|
|
7
|
+
const MAX_MATCHES = 5000;
|
|
8
|
+
const MAX_LINE = 500;
|
|
9
|
+
// Files read at once: enough to keep the disk busy, few enough not to run out of handles in a large project.
|
|
10
|
+
const AT_ONCE = 32;
|
|
11
|
+
/** What `query` asks for as a regular expression; throws one that isn't valid. */
|
|
12
|
+
export function patternOf({ query, caseSensitive, wholeWord, regex }) {
|
|
13
|
+
const source = regex ? query : query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
14
|
+
return new RegExp(wholeWord ? `\\b(?:${source})\\b` : source, caseSensitive ? 'g' : 'gi');
|
|
15
|
+
}
|
|
16
|
+
/** Every line of the folder's files the query finds, file by file in the order git lists them, up to a limit. */
|
|
17
|
+
export async function searchFiles(folder, search) {
|
|
18
|
+
const pattern = patternOf(search);
|
|
19
|
+
const files = [];
|
|
20
|
+
let found = 0;
|
|
21
|
+
await eachText(folder, await candidates(folder, search), (path, text) => {
|
|
22
|
+
if (found >= MAX_MATCHES)
|
|
23
|
+
return false;
|
|
24
|
+
const matches = matchesIn(text, pattern, MAX_MATCHES - found);
|
|
25
|
+
if (matches.length > 0) {
|
|
26
|
+
files.push({ path, matches });
|
|
27
|
+
found += matches.reduce((sum, match) => sum + match.ranges.length, 0);
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
});
|
|
31
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
32
|
+
return { files, truncated: found >= MAX_MATCHES };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Replaces what the query finds with `replacement` in the folder's files, or in `paths` of them only, and writes those
|
|
36
|
+
* it changed. In a regular expression `$1` and the like stand for what it caught; otherwise the text goes in as it is.
|
|
37
|
+
*/
|
|
38
|
+
export async function replaceInFiles(folder, search, replacement, paths) {
|
|
39
|
+
// Line by line, as the search found them: `^` and `$` stand for a line's start and end.
|
|
40
|
+
const pattern = new RegExp(patternOf(search).source, `${patternOf(search).flags}m`);
|
|
41
|
+
const text = search.regex ? replacement : replacement.replaceAll('$', '$$$$');
|
|
42
|
+
const chosen = (await candidates(folder, search)).filter((path) => !paths || paths.includes(path));
|
|
43
|
+
const changed = [];
|
|
44
|
+
let replacements = 0;
|
|
45
|
+
await eachText(folder, chosen, (path, content) => {
|
|
46
|
+
const count = [...content.matchAll(pattern)].filter((found) => found[0] !== '').length;
|
|
47
|
+
if (count > 0) {
|
|
48
|
+
changed.push({ path, text: content.replace(pattern, text) });
|
|
49
|
+
replacements += count;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
});
|
|
53
|
+
await Promise.all(changed.map(({ path, text: next }) => writeFile(join(folder, path), next)));
|
|
54
|
+
return { files: changed.length, replacements };
|
|
55
|
+
}
|
|
56
|
+
/** The folder's files the search's globs let in, as git lists them, so ignored ones stay out. */
|
|
57
|
+
async function candidates(folder, { include, exclude }) {
|
|
58
|
+
const included = globsOf(include);
|
|
59
|
+
const excluded = globsOf(exclude);
|
|
60
|
+
return (await listProjectFiles(folder)).filter((path) => !path.endsWith('/') && (included.length === 0 || included.some((glob) => fits(glob, path))) && !excluded.some((glob) => fits(glob, path)));
|
|
61
|
+
}
|
|
62
|
+
/** Each file's text, a few at a time, till `each` says to stop; one too large or not text is passed. */
|
|
63
|
+
async function eachText(folder, paths, each) {
|
|
64
|
+
for (let start = 0; start < paths.length; start += AT_ONCE) {
|
|
65
|
+
const read = await Promise.all(paths.slice(start, start + AT_ONCE).map(async (path) => {
|
|
66
|
+
const file = join(folder, path);
|
|
67
|
+
const info = await stat(file).catch(() => undefined);
|
|
68
|
+
if (!info?.isFile() || info.size > MAX_BYTES)
|
|
69
|
+
return undefined;
|
|
70
|
+
const text = await readFile(file, 'utf8').catch(() => undefined);
|
|
71
|
+
return text === undefined || text.includes('\u0000') ? undefined : { path, text };
|
|
72
|
+
}));
|
|
73
|
+
for (const file of read)
|
|
74
|
+
if (file && !each(file.path, file.text))
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function matchesIn(text, pattern, room) {
|
|
79
|
+
const matches = [];
|
|
80
|
+
const lines = text.split(/\r?\n/);
|
|
81
|
+
let left = room;
|
|
82
|
+
for (let index = 0; index < lines.length && left > 0; index++) {
|
|
83
|
+
const line = lines[index];
|
|
84
|
+
const ranges = [];
|
|
85
|
+
pattern.lastIndex = 0;
|
|
86
|
+
for (let found = pattern.exec(line); found && left > 0; found = pattern.exec(line)) {
|
|
87
|
+
// One that finds nothing, as `^`, would find it again at the same place for ever.
|
|
88
|
+
if (found[0] === '') {
|
|
89
|
+
pattern.lastIndex++;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (found.index < MAX_LINE)
|
|
93
|
+
ranges.push([found.index, Math.min(found.index + found[0].length, MAX_LINE)]);
|
|
94
|
+
left--;
|
|
95
|
+
}
|
|
96
|
+
if (ranges.length > 0)
|
|
97
|
+
matches.push({ line: index + 1, text: line.slice(0, MAX_LINE), ranges });
|
|
98
|
+
}
|
|
99
|
+
return matches;
|
|
100
|
+
}
|
|
101
|
+
function globsOf(list) {
|
|
102
|
+
return (list ?? '')
|
|
103
|
+
.split(',')
|
|
104
|
+
.map((glob) => glob.trim())
|
|
105
|
+
.filter(Boolean);
|
|
106
|
+
}
|
|
107
|
+
/** A glob fits a file itself, or a folder it is in, as `src` lets in everything under it. */
|
|
108
|
+
function fits(glob, path) {
|
|
109
|
+
const parts = path.split('/');
|
|
110
|
+
return parts.some((_, index) => matchesGlob(glob, parts.slice(0, index + 1).join('/')));
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/files/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class TrashUnsupported extends Error {
|
|
2
|
+
}
|
|
3
|
+
/** Moves a file or folder to the Trash, as the Finder would, under a name free there; where it went. */
|
|
4
|
+
export declare function toTrash(path: string): Promise<string>;
|
|
5
|
+
/** Whether `fromTrash` can put it back: `toTrash` moved it there, and it is still there. */
|
|
6
|
+
export declare function restorable(trash: string): Promise<boolean>;
|
|
7
|
+
/** Puts what `toTrash` moved back at `path`, once `restorable` said it can. */
|
|
8
|
+
export declare function fromTrash(trash: string, path: string): Promise<void>;
|
|
9
|
+
/** A rename, or a copy and a removal where the two are on different disks, as a project on another volume is. */
|
|
10
|
+
export declare function moveAcross(from: string, to: string): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=trash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trash.d.ts","sourceRoot":"","sources":["../../src/files/trash.ts"],"names":[],"mappings":"AAQA,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAE9C,wGAAwG;AACxG,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,mBAiBzC;AAED,4FAA4F;AAC5F,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,oBAE7C;AAED,+EAA+E;AAC/E,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,iBAO1D;AAED,iHAAiH;AACjH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,iBASxD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { cp, lstat, mkdir, rename, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, dirname, join } from 'node:path';
|
|
4
|
+
import { freeName } from './names.js';
|
|
5
|
+
/** What this process put in the Trash, so only that can be taken back out through it. */
|
|
6
|
+
const trashed = new Set();
|
|
7
|
+
export class TrashUnsupported extends Error {
|
|
8
|
+
}
|
|
9
|
+
/** Moves a file or folder to the Trash, as the Finder would, under a name free there; where it went. */
|
|
10
|
+
export async function toTrash(path) {
|
|
11
|
+
const { files, info } = trashFolders();
|
|
12
|
+
await mkdir(files, { recursive: true });
|
|
13
|
+
const name = await freeName(files, basename(path), '');
|
|
14
|
+
const trash = join(files, name);
|
|
15
|
+
if (info) {
|
|
16
|
+
await mkdir(info, { recursive: true });
|
|
17
|
+
await writeFile(join(info, `${name}.trashinfo`), `[Trash Info]\nPath=${encodeURI(path)}\nDeletionDate=${localDate(new Date())}\n`);
|
|
18
|
+
}
|
|
19
|
+
await moveAcross(path, trash);
|
|
20
|
+
trashed.add(trash);
|
|
21
|
+
return trash;
|
|
22
|
+
}
|
|
23
|
+
/** Whether `fromTrash` can put it back: `toTrash` moved it there, and it is still there. */
|
|
24
|
+
export async function restorable(trash) {
|
|
25
|
+
return trashed.has(trash) && (await lstat(trash).then(() => true, () => false));
|
|
26
|
+
}
|
|
27
|
+
/** Puts what `toTrash` moved back at `path`, once `restorable` said it can. */
|
|
28
|
+
export async function fromTrash(trash, path) {
|
|
29
|
+
const { info } = trashFolders();
|
|
30
|
+
await mkdir(dirname(path), { recursive: true });
|
|
31
|
+
await moveAcross(trash, path);
|
|
32
|
+
trashed.delete(trash);
|
|
33
|
+
if (info)
|
|
34
|
+
await rm(join(info, `${basename(trash)}.trashinfo`), { force: true });
|
|
35
|
+
}
|
|
36
|
+
/** A rename, or a copy and a removal where the two are on different disks, as a project on another volume is. */
|
|
37
|
+
export async function moveAcross(from, to) {
|
|
38
|
+
try {
|
|
39
|
+
await rename(from, to);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.code !== 'EXDEV')
|
|
43
|
+
throw error;
|
|
44
|
+
await cp(from, to, { recursive: true, verbatimSymlinks: true, errorOnExist: true, force: false });
|
|
45
|
+
await rm(from, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// The Finder's Trash takes what is moved into it without the record its own Put Back reads, which only the Finder
|
|
49
|
+
// writes; Jinion puts back what it trashed itself. Elsewhere, the trash freedesktop.org describes, record and all.
|
|
50
|
+
function trashFolders() {
|
|
51
|
+
if (process.env.JINION_TRASH)
|
|
52
|
+
return { files: process.env.JINION_TRASH };
|
|
53
|
+
if (process.platform === 'darwin')
|
|
54
|
+
return { files: join(homedir(), '.Trash') };
|
|
55
|
+
if (process.platform === 'win32')
|
|
56
|
+
throw new TrashUnsupported("Moving to the Recycle Bin isn't supported on Windows yet.");
|
|
57
|
+
const trash = join(process.env.XDG_DATA_HOME ?? join(homedir(), '.local', 'share'), 'Trash');
|
|
58
|
+
return { files: join(trash, 'files'), info: join(trash, 'info') };
|
|
59
|
+
}
|
|
60
|
+
function localDate(date) {
|
|
61
|
+
const two = (value) => String(value).padStart(2, '0');
|
|
62
|
+
return `${date.getFullYear()}-${two(date.getMonth() + 1)}-${two(date.getDate())}T${two(date.getHours())}:${two(date.getMinutes())}:${two(date.getSeconds())}`;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=trash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trash.js","sourceRoot":"","sources":["../../src/files/trash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** What to find in the folder's files, and in which of them. */
|
|
3
|
+
export declare const SearchQuery: z.ZodObject<{
|
|
4
|
+
query: z.ZodString;
|
|
5
|
+
caseSensitive: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
wholeWord: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
+
regex: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
include: z.ZodOptional<z.ZodString>;
|
|
9
|
+
exclude: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export type SearchQuery = z.infer<typeof SearchQuery>;
|
|
12
|
+
/** A line with what was found in it, as `[start, end)` places in `text`, counted from 0. */
|
|
13
|
+
export declare const SearchMatch: z.ZodObject<{
|
|
14
|
+
line: z.ZodNumber;
|
|
15
|
+
text: z.ZodString;
|
|
16
|
+
ranges: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export type SearchMatch = z.infer<typeof SearchMatch>;
|
|
19
|
+
export declare const FileMatches: z.ZodObject<{
|
|
20
|
+
path: z.ZodString;
|
|
21
|
+
matches: z.ZodArray<z.ZodObject<{
|
|
22
|
+
line: z.ZodNumber;
|
|
23
|
+
text: z.ZodString;
|
|
24
|
+
ranges: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type FileMatches = z.infer<typeof FileMatches>;
|
|
28
|
+
/** `truncated` when there were more than are given. */
|
|
29
|
+
export declare const SearchResults: z.ZodObject<{
|
|
30
|
+
files: z.ZodArray<z.ZodObject<{
|
|
31
|
+
path: z.ZodString;
|
|
32
|
+
matches: z.ZodArray<z.ZodObject<{
|
|
33
|
+
line: z.ZodNumber;
|
|
34
|
+
text: z.ZodString;
|
|
35
|
+
ranges: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
36
|
+
}, z.core.$strip>>;
|
|
37
|
+
}, z.core.$strip>>;
|
|
38
|
+
truncated: z.ZodBoolean;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
export type SearchResults = z.infer<typeof SearchResults>;
|
|
41
|
+
export declare const Replaced: z.ZodObject<{
|
|
42
|
+
files: z.ZodNumber;
|
|
43
|
+
replacements: z.ZodNumber;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
export type Replaced = z.infer<typeof Replaced>;
|
|
46
|
+
/**
|
|
47
|
+
* A file a client watches changed on disk: its time now, none once it is gone. Moved or renamed through the API, with
|
|
48
|
+
* `movedTo`, its path now, which is watched from then on in its place.
|
|
49
|
+
*/
|
|
50
|
+
export declare const FileChanged: z.ZodObject<{
|
|
51
|
+
session: z.ZodString;
|
|
52
|
+
path: z.ZodString;
|
|
53
|
+
modified: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
movedTo: z.ZodOptional<z.ZodString>;
|
|
55
|
+
by: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
agent: "agent";
|
|
57
|
+
other: "other";
|
|
58
|
+
}>>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
export type FileChanged = z.infer<typeof FileChanged>;
|
|
61
|
+
/** A file or folder moved, renamed or copied, by its paths in the session's folder; a copy from outside it, by its whole path. */
|
|
62
|
+
export declare const Moved: z.ZodObject<{
|
|
63
|
+
from: z.ZodString;
|
|
64
|
+
to: z.ZodString;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
export type Moved = z.infer<typeof Moved>;
|
|
67
|
+
/** What went to the Trash: its path in the session's folder, and its whole path in the Trash, by which it is put back. */
|
|
68
|
+
export declare const Trashed: z.ZodObject<{
|
|
69
|
+
path: z.ZodString;
|
|
70
|
+
trash: z.ZodString;
|
|
71
|
+
}, z.core.$strip>;
|
|
72
|
+
export type Trashed = z.infer<typeof Trashed>;
|
|
73
|
+
/** What a call did, so a client can undo it; `replaced`, what was in the way and went to the Trash for it. */
|
|
74
|
+
export declare const FilesMoved: z.ZodObject<{
|
|
75
|
+
moved: z.ZodArray<z.ZodObject<{
|
|
76
|
+
from: z.ZodString;
|
|
77
|
+
to: z.ZodString;
|
|
78
|
+
}, z.core.$strip>>;
|
|
79
|
+
replaced: z.ZodArray<z.ZodObject<{
|
|
80
|
+
path: z.ZodString;
|
|
81
|
+
trash: z.ZodString;
|
|
82
|
+
}, z.core.$strip>>;
|
|
83
|
+
}, z.core.$strip>;
|
|
84
|
+
export type FilesMoved = z.infer<typeof FilesMoved>;
|
|
85
|
+
export declare const FilesCopied: z.ZodObject<{
|
|
86
|
+
copied: z.ZodArray<z.ZodObject<{
|
|
87
|
+
from: z.ZodString;
|
|
88
|
+
to: z.ZodString;
|
|
89
|
+
}, z.core.$strip>>;
|
|
90
|
+
replaced: z.ZodArray<z.ZodObject<{
|
|
91
|
+
path: z.ZodString;
|
|
92
|
+
trash: z.ZodString;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
}, z.core.$strip>;
|
|
95
|
+
export type FilesCopied = z.infer<typeof FilesCopied>;
|
|
96
|
+
export declare const FileCreated: z.ZodObject<{
|
|
97
|
+
path: z.ZodString;
|
|
98
|
+
replaced: z.ZodArray<z.ZodObject<{
|
|
99
|
+
path: z.ZodString;
|
|
100
|
+
trash: z.ZodString;
|
|
101
|
+
}, z.core.$strip>>;
|
|
102
|
+
}, z.core.$strip>;
|
|
103
|
+
export type FileCreated = z.infer<typeof FileCreated>;
|
|
104
|
+
export declare const FilesRestored: z.ZodObject<{
|
|
105
|
+
restored: z.ZodArray<z.ZodString>;
|
|
106
|
+
replaced: z.ZodArray<z.ZodObject<{
|
|
107
|
+
path: z.ZodString;
|
|
108
|
+
trash: z.ZodString;
|
|
109
|
+
}, z.core.$strip>>;
|
|
110
|
+
}, z.core.$strip>;
|
|
111
|
+
export type FilesRestored = z.infer<typeof FilesRestored>;
|
|
112
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gEAAgE;AAChE,eAAO,MAAM,WAAW;;;;;;;iBAWtB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,4FAA4F;AAC5F,eAAO,MAAM,WAAW;;;;iBAKtB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,eAAO,MAAM,WAAW;;;;;;;iBAAgE,CAAC;AAEzF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,uDAAuD;AACvD,eAAO,MAAM,aAAa;;;;;;;;;;iBAAoE,CAAC;AAE/F,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,eAAO,MAAM,QAAQ;;;iBAAwE,CAAC;AAE9F,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;iBAOtB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,kIAAkI;AAClI,eAAO,MAAM,KAAK;;;iBAAiD,CAAC;AAEpE,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;AAE1C,0HAA0H;AAC1H,eAAO,MAAM,OAAO;;;iBAAoD,CAAC;AAEzE,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAE9C,8GAA8G;AAC9G,eAAO,MAAM,UAAU;;;;;;;;;iBAAkE,CAAC;AAE1F,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD,eAAO,MAAM,WAAW;;;;;;;;;iBAAmE,CAAC;AAE5F,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,eAAO,MAAM,WAAW;;;;;;iBAA6D,CAAC;AAEtF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,eAAO,MAAM,aAAa;;;;;;iBAA0E,CAAC;AAErG,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** What to find in the folder's files, and in which of them. */
|
|
3
|
+
export const SearchQuery = z.object({
|
|
4
|
+
query: z.string().min(1),
|
|
5
|
+
caseSensitive: z.boolean().optional(),
|
|
6
|
+
/** Only where it stands as a word of its own. */
|
|
7
|
+
wholeWord: z.boolean().optional(),
|
|
8
|
+
/** `query` is a regular expression, as JavaScript reads one. */
|
|
9
|
+
regex: z.boolean().optional(),
|
|
10
|
+
/** Globs, by commas, as `src, *.ts`: only the files one fits, or a folder of them. */
|
|
11
|
+
include: z.string().optional(),
|
|
12
|
+
/** Globs the same way, for files left out. */
|
|
13
|
+
exclude: z.string().optional(),
|
|
14
|
+
});
|
|
15
|
+
/** A line with what was found in it, as `[start, end)` places in `text`, counted from 0. */
|
|
16
|
+
export const SearchMatch = z.object({
|
|
17
|
+
/** Counted from 1. */
|
|
18
|
+
line: z.number().int(),
|
|
19
|
+
text: z.string(),
|
|
20
|
+
ranges: z.array(z.tuple([z.number().int(), z.number().int()])),
|
|
21
|
+
});
|
|
22
|
+
export const FileMatches = z.object({ path: z.string(), matches: z.array(SearchMatch) });
|
|
23
|
+
/** `truncated` when there were more than are given. */
|
|
24
|
+
export const SearchResults = z.object({ files: z.array(FileMatches), truncated: z.boolean() });
|
|
25
|
+
export const Replaced = z.object({ files: z.number().int(), replacements: z.number().int() });
|
|
26
|
+
/**
|
|
27
|
+
* A file a client watches changed on disk: its time now, none once it is gone. Moved or renamed through the API, with
|
|
28
|
+
* `movedTo`, its path now, which is watched from then on in its place.
|
|
29
|
+
*/
|
|
30
|
+
export const FileChanged = z.object({
|
|
31
|
+
session: z.string(),
|
|
32
|
+
path: z.string(),
|
|
33
|
+
modified: z.number().optional(),
|
|
34
|
+
movedTo: z.string().optional(),
|
|
35
|
+
/** `agent` when the session's running turn edits it, `other` when no turn runs; neither when a turn runs but names it in no edit, as a command of the agent's may change it. */
|
|
36
|
+
by: z.enum(['agent', 'other']).optional(),
|
|
37
|
+
});
|
|
38
|
+
/** A file or folder moved, renamed or copied, by its paths in the session's folder; a copy from outside it, by its whole path. */
|
|
39
|
+
export const Moved = z.object({ from: z.string(), to: z.string() });
|
|
40
|
+
/** What went to the Trash: its path in the session's folder, and its whole path in the Trash, by which it is put back. */
|
|
41
|
+
export const Trashed = z.object({ path: z.string(), trash: z.string() });
|
|
42
|
+
/** What a call did, so a client can undo it; `replaced`, what was in the way and went to the Trash for it. */
|
|
43
|
+
export const FilesMoved = z.object({ moved: z.array(Moved), replaced: z.array(Trashed) });
|
|
44
|
+
export const FilesCopied = z.object({ copied: z.array(Moved), replaced: z.array(Trashed) });
|
|
45
|
+
export const FileCreated = z.object({ path: z.string(), replaced: z.array(Trashed) });
|
|
46
|
+
export const FilesRestored = z.object({ restored: z.array(z.string()), replaced: z.array(Trashed) });
|
|
47
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gEAAgE;AAChE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,iDAAiD;IACjD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,gEAAgE;IAChE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,sFAAsF;IACtF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,8CAA8C;IAC9C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAIH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,sBAAsB;IACtB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACtB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;CAC/D,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAIzF,uDAAuD;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAI/F,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAI9F;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,gLAAgL;IAChL,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAIH,kIAAkI;AAClI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAIpE,0HAA0H;AAC1H,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAIzE,8GAA8G;AAC9G,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAI1F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAI5F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAItF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FileChanged, Moved } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The files one client has open, watched on disk: each folder holding one is watched, as many editors write a file by
|
|
4
|
+
* putting a new one in its place, which a watch on the file itself would lose.
|
|
5
|
+
*/
|
|
6
|
+
export declare class FileWatcher {
|
|
7
|
+
private readonly changed;
|
|
8
|
+
private readonly wanted;
|
|
9
|
+
private readonly folders;
|
|
10
|
+
private files;
|
|
11
|
+
private readonly settling;
|
|
12
|
+
constructor(changed: (change: FileChanged) => void);
|
|
13
|
+
/**
|
|
14
|
+
* Files and folders of `folder` moved or renamed through the API, by their paths there: each open file in them is told
|
|
15
|
+
* of with its path now, and watched there from then on.
|
|
16
|
+
*/
|
|
17
|
+
static moved(folder: string, moves: Moved[]): void;
|
|
18
|
+
/** The files of the session's folder it now has open, by their paths there; the ones before are let go. */
|
|
19
|
+
set(session: string, folder: string, paths: string[]): void;
|
|
20
|
+
close(): void;
|
|
21
|
+
private follow;
|
|
22
|
+
private rebuild;
|
|
23
|
+
private touched;
|
|
24
|
+
private tell;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/files/watch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAQrD;;;GAGG;AACH,qBAAa,WAAW;IAMV,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0D;IACjF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,KAAK,CAA0D;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoD;IAE7E,YAA6B,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,EAElE;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAE1C;IAED,2GAA2G;IAC3G,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAGnD;IAED,KAAK,SAOJ;IAED,OAAO,CAAC,MAAM;IAwBd,OAAO,CAAC,OAAO;IAoCf,OAAO,CAAC,OAAO;IAkBf,OAAO,CAAC,IAAI;CAGb"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { watch } from 'node:fs';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { dirname, isAbsolute, join, normalize, sep } from 'node:path';
|
|
4
|
+
// An editor or a tool writes a file in several steps; the change is told once they are done.
|
|
5
|
+
const SETTLE = 100;
|
|
6
|
+
/** Every client's watcher, for what the API moves to reach all of them. */
|
|
7
|
+
const watchers = new Set();
|
|
8
|
+
/**
|
|
9
|
+
* The files one client has open, watched on disk: each folder holding one is watched, as many editors write a file by
|
|
10
|
+
* putting a new one in its place, which a watch on the file itself would lose.
|
|
11
|
+
*/
|
|
12
|
+
export class FileWatcher {
|
|
13
|
+
changed;
|
|
14
|
+
wanted = new Map();
|
|
15
|
+
folders = new Map();
|
|
16
|
+
files = new Map();
|
|
17
|
+
settling = new Map();
|
|
18
|
+
constructor(changed) {
|
|
19
|
+
this.changed = changed;
|
|
20
|
+
watchers.add(this);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Files and folders of `folder` moved or renamed through the API, by their paths there: each open file in them is told
|
|
24
|
+
* of with its path now, and watched there from then on.
|
|
25
|
+
*/
|
|
26
|
+
static moved(folder, moves) {
|
|
27
|
+
for (const watcher of watchers)
|
|
28
|
+
watcher.follow(folder, moves);
|
|
29
|
+
}
|
|
30
|
+
/** The files of the session's folder it now has open, by their paths there; the ones before are let go. */
|
|
31
|
+
set(session, folder, paths) {
|
|
32
|
+
this.wanted.set(session, { folder, paths: paths.map(normalize).filter((path) => !isAbsolute(path) && !path.startsWith('..')) });
|
|
33
|
+
this.rebuild();
|
|
34
|
+
}
|
|
35
|
+
close() {
|
|
36
|
+
for (const watcher of this.folders.values())
|
|
37
|
+
watcher.close();
|
|
38
|
+
for (const timer of this.settling.values())
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
this.folders.clear();
|
|
41
|
+
this.wanted.clear();
|
|
42
|
+
watchers.delete(this);
|
|
43
|
+
}
|
|
44
|
+
follow(folder, moves) {
|
|
45
|
+
const told = [];
|
|
46
|
+
for (const [session, wanted] of this.wanted) {
|
|
47
|
+
if (wanted.folder !== folder)
|
|
48
|
+
continue;
|
|
49
|
+
wanted.paths = wanted.paths.map((path) => {
|
|
50
|
+
const move = moves.find(({ from }) => path === from || path.startsWith(`${from}${sep}`));
|
|
51
|
+
if (!move)
|
|
52
|
+
return path;
|
|
53
|
+
const movedTo = move.to + path.slice(move.from.length);
|
|
54
|
+
told.push({ session, path, movedTo });
|
|
55
|
+
return movedTo;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (told.length === 0)
|
|
59
|
+
return;
|
|
60
|
+
this.rebuild();
|
|
61
|
+
for (const change of told)
|
|
62
|
+
this.changed(change);
|
|
63
|
+
}
|
|
64
|
+
rebuild() {
|
|
65
|
+
const files = new Map();
|
|
66
|
+
for (const [session, { folder, paths }] of this.wanted) {
|
|
67
|
+
for (const path of paths) {
|
|
68
|
+
const file = join(folder, path);
|
|
69
|
+
files.set(file, [...(files.get(file) ?? []), { session, path }]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const needed = new Set([...files.keys()].map(dirname));
|
|
73
|
+
for (const [folder, watcher] of this.folders) {
|
|
74
|
+
if (needed.has(folder))
|
|
75
|
+
continue;
|
|
76
|
+
watcher.close();
|
|
77
|
+
this.folders.delete(folder);
|
|
78
|
+
}
|
|
79
|
+
for (const folder of needed) {
|
|
80
|
+
if (this.folders.has(folder))
|
|
81
|
+
continue;
|
|
82
|
+
try {
|
|
83
|
+
const watcher = watch(folder, { persistent: false }, (_event, name) => name && this.touched(join(folder, name.toString())));
|
|
84
|
+
watcher.on('error', () => this.folders.delete(folder));
|
|
85
|
+
this.folders.set(folder, watcher);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// A folder that is gone has nothing to watch; it is tried again once the files change.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.files = files;
|
|
92
|
+
}
|
|
93
|
+
touched(file) {
|
|
94
|
+
if (!this.files.has(file))
|
|
95
|
+
return;
|
|
96
|
+
clearTimeout(this.settling.get(file));
|
|
97
|
+
this.settling.set(file, setTimeout(() => {
|
|
98
|
+
this.settling.delete(file);
|
|
99
|
+
void stat(file).then((info) => this.tell(file, info.mtimeMs), () => this.tell(file, undefined));
|
|
100
|
+
}, SETTLE));
|
|
101
|
+
}
|
|
102
|
+
tell(file, modified) {
|
|
103
|
+
for (const { session, path } of this.files.get(file) ?? [])
|
|
104
|
+
this.changed({ session, path, ...(modified !== undefined && { modified }) });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/files/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Blame, CommitDetail } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Who last changed each line of a file in `folder`, from the repository it is in, the deepest when several hold it.
|
|
4
|
+
* With `text`, the lines are those of the text rather than the file on disk, as an editor holds it with edits not saved
|
|
5
|
+
* yet, which show as not committed. `null` for a file git doesn't know, as one never committed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function blame(folder: string, path: string, text?: string): Promise<Blame | null>;
|
|
8
|
+
/** A commit of one of the folder's repositories, with each file it changed. */
|
|
9
|
+
export declare function showCommit(folder: string, root: string, sha: string): Promise<CommitDetail | undefined>;
|
|
10
|
+
//# sourceMappingURL=blame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blame.d.ts","sourceRoot":"","sources":["../../src/git/blame.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAc,YAAY,EAAoB,MAAM,YAAY,CAAC;AAKpF;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAS9F;AAED,+EAA+E;AAC/E,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAS7G"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { isAbsolute, join, relative } from 'node:path';
|
|
3
|
+
import { findRepos } from './repos.js';
|
|
4
|
+
/** The sha git gives lines that aren't committed yet. */
|
|
5
|
+
const UNCOMMITTED = '0'.repeat(40);
|
|
6
|
+
/**
|
|
7
|
+
* Who last changed each line of a file in `folder`, from the repository it is in, the deepest when several hold it.
|
|
8
|
+
* With `text`, the lines are those of the text rather than the file on disk, as an editor holds it with edits not saved
|
|
9
|
+
* yet, which show as not committed. `null` for a file git doesn't know, as one never committed.
|
|
10
|
+
*/
|
|
11
|
+
export async function blame(folder, path, text) {
|
|
12
|
+
const file = join(folder, path);
|
|
13
|
+
const repo = repoOf(folder, file);
|
|
14
|
+
if (!repo)
|
|
15
|
+
return null;
|
|
16
|
+
const args = ['blame', '--porcelain', ...(text === undefined ? [] : ['--contents', '-']), '--', relative(repo.root, file)];
|
|
17
|
+
const [output, you] = await Promise.all([run(repo.root, args, text).catch(() => undefined), run(repo.root, ['config', 'user.email']).catch(() => '')]);
|
|
18
|
+
return output === undefined ? null : { repo: repo.root, ...(you.trim() && { you: you.trim() }), ...parseBlame(output) };
|
|
19
|
+
}
|
|
20
|
+
/** A commit of one of the folder's repositories, with each file it changed. */
|
|
21
|
+
export async function showCommit(folder, root, sha) {
|
|
22
|
+
if (!/^[0-9a-f]{4,40}$/i.test(sha) || !findRepos(folder).some((repo) => repo.root === root))
|
|
23
|
+
return undefined;
|
|
24
|
+
const output = await run(root, ['show', '--no-color', '-M', '--patch', '--format=%H%x00%an%x00%ae%x00%at%x00%s%x00%b%x00', sha]).catch(() => undefined);
|
|
25
|
+
if (output === undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
const [full, author, email, time, summary, body, patch] = output.split('\0');
|
|
28
|
+
return { sha: full, author: author, email: email, time: Number(time) * 1000, summary: summary, body: body.trim(), files: filesOf(patch ?? '') };
|
|
29
|
+
}
|
|
30
|
+
/** `git blame --porcelain`: each line under a header naming its commit, the commit told of the first time it comes. */
|
|
31
|
+
function parseBlame(output) {
|
|
32
|
+
const commits = {};
|
|
33
|
+
const ranges = [];
|
|
34
|
+
let current;
|
|
35
|
+
let fields = {};
|
|
36
|
+
for (const line of output.split('\n')) {
|
|
37
|
+
const header = /^([0-9a-f]{40}) \d+ (\d+)/.exec(line);
|
|
38
|
+
if (header) {
|
|
39
|
+
current = { sha: header[1], line: Number(header[2]) };
|
|
40
|
+
fields = {};
|
|
41
|
+
}
|
|
42
|
+
else if (line.startsWith('\t') && current) {
|
|
43
|
+
const { sha } = current;
|
|
44
|
+
if (sha !== UNCOMMITTED && !commits[sha]) {
|
|
45
|
+
commits[sha] = { sha, author: fields.author ?? '', email: (fields['author-mail'] ?? '').replace(/^<|>$/g, ''), time: Number(fields['author-time'] ?? 0) * 1000, summary: fields.summary ?? '' };
|
|
46
|
+
}
|
|
47
|
+
const last = ranges.at(-1);
|
|
48
|
+
const commit = sha === UNCOMMITTED ? undefined : sha;
|
|
49
|
+
if (last && last.commit === commit && last.start + last.lines === current.line)
|
|
50
|
+
last.lines += 1;
|
|
51
|
+
else
|
|
52
|
+
ranges.push({ start: current.line, lines: 1, ...(commit && { commit }) });
|
|
53
|
+
current = undefined;
|
|
54
|
+
}
|
|
55
|
+
else if (current) {
|
|
56
|
+
const space = line.indexOf(' ');
|
|
57
|
+
if (space > 0)
|
|
58
|
+
fields[line.slice(0, space)] = line.slice(space + 1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { ranges, commits };
|
|
62
|
+
}
|
|
63
|
+
function filesOf(patch) {
|
|
64
|
+
return patch
|
|
65
|
+
.split(/^(?=diff --git )/m)
|
|
66
|
+
.filter((part) => part.startsWith('diff --git '))
|
|
67
|
+
.map((part) => {
|
|
68
|
+
const added = /^\+\+\+ b\/(.+)$/m.exec(part)?.[1];
|
|
69
|
+
const removed = /^--- a\/(.+)$/m.exec(part)?.[1];
|
|
70
|
+
const named = /^diff --git a\/.+ b\/(.+)$/m.exec(part)?.[1];
|
|
71
|
+
return { path: added ?? removed ?? named ?? '', patch: part, binary: /^Binary files /m.test(part) };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function repoOf(folder, file) {
|
|
75
|
+
const inside = (root) => {
|
|
76
|
+
const path = relative(root, file);
|
|
77
|
+
return !path.startsWith('..') && !isAbsolute(path);
|
|
78
|
+
};
|
|
79
|
+
return findRepos(folder)
|
|
80
|
+
.filter((repo) => inside(repo.root))
|
|
81
|
+
.sort((a, b) => b.root.length - a.root.length)[0];
|
|
82
|
+
}
|
|
83
|
+
function run(cwd, args, input) {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const child = execFile('git', args, { cwd, maxBuffer: 64 * 1024 * 1024, timeout: 30_000 }, (error, stdout) => (error ? reject(error) : resolve(stdout)));
|
|
86
|
+
// Git can end before it reads its input, as when it refuses what it was asked; writing to it then isn't a failure.
|
|
87
|
+
child.stdin?.on('error', () => { });
|
|
88
|
+
child.stdin?.end(input ?? '');
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=blame.js.map
|