@bevel-software/platform-core-backend 0.29.0 → 0.31.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/agent-guide/access-control.md +49 -4
- package/agent-guide/html-views.md +76 -2
- package/dist/__tests__/test-repositories.d.ts +3 -0
- package/dist/__tests__/test-repositories.d.ts.map +1 -0
- package/dist/__tests__/test-repositories.js +18 -0
- package/dist/__tests__/test-repositories.js.map +1 -0
- package/dist/core/catalog-revision.js +3 -3
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +3 -2
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +3 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +35 -5
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +8 -0
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +4 -0
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +20 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +32 -1
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +135 -17
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +20 -6
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +1 -1
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +66 -6
- package/dist/modules/audit/agent-audit.service.js.map +1 -1
- package/dist/modules/audit/audit.contract.d.ts +52 -8
- package/dist/modules/audit/audit.contract.d.ts.map +1 -1
- package/dist/modules/audit/audit.contract.js +37 -1
- package/dist/modules/audit/audit.contract.js.map +1 -1
- package/dist/modules/audit/audit.routes.d.ts +1 -1
- package/dist/modules/audit/audit.routes.d.ts.map +1 -1
- package/dist/modules/audit/audit.routes.js +15 -13
- package/dist/modules/audit/audit.routes.js.map +1 -1
- package/dist/modules/audit/request-audit.d.ts +21 -10
- package/dist/modules/audit/request-audit.d.ts.map +1 -1
- package/dist/modules/audit/request-audit.js +26 -10
- package/dist/modules/audit/request-audit.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +22 -3
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +15 -6
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/diff/diff.service.d.ts.map +1 -1
- package/dist/modules/diff/diff.service.js +7 -1
- package/dist/modules/diff/diff.service.js.map +1 -1
- package/dist/modules/kb-fs/git-dir.d.ts +21 -0
- package/dist/modules/kb-fs/git-dir.d.ts.map +1 -0
- package/dist/modules/kb-fs/git-dir.js +58 -0
- package/dist/modules/kb-fs/git-dir.js.map +1 -0
- package/dist/modules/kb-fs/index.d.ts +3 -0
- package/dist/modules/kb-fs/index.d.ts.map +1 -1
- package/dist/modules/kb-fs/index.js +3 -1
- package/dist/modules/kb-fs/index.js.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +3 -12
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/kb-fs/mutex.d.ts +11 -0
- package/dist/modules/kb-fs/mutex.d.ts.map +1 -1
- package/dist/modules/kb-fs/mutex.js +14 -0
- package/dist/modules/kb-fs/mutex.js.map +1 -1
- package/dist/modules/kb-fs/ref-files.d.ts +63 -0
- package/dist/modules/kb-fs/ref-files.d.ts.map +1 -0
- package/dist/modules/kb-fs/ref-files.js +249 -0
- package/dist/modules/kb-fs/ref-files.js.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts +14 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +4 -0
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/mcp.routes.d.ts +5 -0
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.routes.js +67 -0
- package/dist/modules/mcp/mcp.routes.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +107 -27
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +257 -50
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/request-context.d.ts +25 -0
- package/dist/modules/mcp/request-context.d.ts.map +1 -0
- package/dist/modules/mcp/request-context.js +11 -0
- package/dist/modules/mcp/request-context.js.map +1 -0
- package/dist/modules/mcp/shared-definitions.d.ts +56 -0
- package/dist/modules/mcp/shared-definitions.d.ts.map +1 -0
- package/dist/modules/mcp/shared-definitions.js +117 -0
- package/dist/modules/mcp/shared-definitions.js.map +1 -0
- package/dist/modules/mcp/surface-cache.d.ts +70 -0
- package/dist/modules/mcp/surface-cache.d.ts.map +1 -0
- package/dist/modules/mcp/surface-cache.js +104 -0
- package/dist/modules/mcp/surface-cache.js.map +1 -0
- package/dist/modules/plugins/teams.routes.d.ts +4 -0
- package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
- package/dist/modules/plugins/teams.routes.js +9 -1
- package/dist/modules/plugins/teams.routes.js.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +1 -2
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +1 -2
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +33 -12
- package/dist/modules/tool-helpers/tool-context.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +2 -2
- package/dist/modules/tool-helpers/tool.contract.d.ts +10 -2
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js +3 -14
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +18 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +453 -2
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +142 -4
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +645 -128
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/read-on-branch.d.ts +35 -0
- package/dist/modules/workflow/read-on-branch.d.ts.map +1 -0
- package/dist/modules/workflow/read-on-branch.js +58 -0
- package/dist/modules/workflow/read-on-branch.js.map +1 -0
- package/dist/modules/workflow/workflow-hooks.d.ts +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +22 -41
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +48 -8
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +163 -16
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts +2 -2
- package/dist/modules/workspace/agent-access.gate.js +2 -2
- package/dist/modules/workspace/bounded-matcher.d.ts +79 -0
- package/dist/modules/workspace/bounded-matcher.d.ts.map +1 -0
- package/dist/modules/workspace/bounded-matcher.js +261 -0
- package/dist/modules/workspace/bounded-matcher.js.map +1 -0
- package/dist/modules/workspace/fetch-instant.d.ts +9 -0
- package/dist/modules/workspace/fetch-instant.d.ts.map +1 -0
- package/dist/modules/workspace/fetch-instant.js +13 -0
- package/dist/modules/workspace/fetch-instant.js.map +1 -0
- package/dist/modules/workspace/index.d.ts +9 -0
- package/dist/modules/workspace/index.d.ts.map +1 -1
- package/dist/modules/workspace/index.js +10 -0
- package/dist/modules/workspace/index.js.map +1 -1
- package/dist/modules/workspace/kb-repository.contract.d.ts +124 -0
- package/dist/modules/workspace/kb-repository.contract.d.ts.map +1 -0
- package/dist/modules/workspace/kb-repository.contract.js +19 -0
- package/dist/modules/workspace/kb-repository.contract.js.map +1 -0
- package/dist/modules/workspace/kb-repository.d.ts +236 -0
- package/dist/modules/workspace/kb-repository.d.ts.map +1 -0
- package/dist/modules/workspace/kb-repository.js +811 -0
- package/dist/modules/workspace/kb-repository.js.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts +50 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.js +27 -0
- package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -0
- package/dist/modules/workspace/routine-write-policy.d.ts +0 -7
- package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
- package/dist/modules/workspace/routine-write-policy.js +0 -5
- package/dist/modules/workspace/routine-write-policy.js.map +1 -1
- package/dist/modules/workspace/set-aside-clone.d.ts +40 -0
- package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -1
- package/dist/modules/workspace/set-aside-clone.js +139 -0
- package/dist/modules/workspace/set-aside-clone.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +99 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +407 -29
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +68 -32
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +240 -161
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +13 -4
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +162 -336
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/git.contract.d.ts +7 -0
- package/dist/shared/git.contract.d.ts.map +1 -1
- package/dist/shared/git.contract.js +9 -0
- package/dist/shared/git.contract.js.map +1 -1
- package/dist/shared/no-link-below.d.ts +10 -0
- package/dist/shared/no-link-below.d.ts.map +1 -0
- package/dist/shared/no-link-below.js +30 -0
- package/dist/shared/no-link-below.js.map +1 -0
- package/dist/test-setup.js +4 -0
- package/dist/test-setup.js.map +1 -1
- package/migrations/0018_agent_events_page.sql +11 -0
- package/migrations/meta/0018_snapshot.json +2429 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +3 -3
- package/src/__tests__/test-repositories.ts +22 -0
- package/src/__tests__/workspace-service.ts +69 -0
- package/src/core/__tests__/lifecycle.test.ts +16 -0
- package/src/core/catalog-revision.ts +3 -3
- package/src/core/create-core-server.ts +3 -2
- package/src/core/create-core-services.ts +39 -4
- package/src/core/lifecycle.ts +10 -0
- package/src/modules/access/__tests__/access-control.atref-cache.test.ts +144 -4
- package/src/modules/access/__tests__/access-control.group-read.test.ts +73 -0
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +66 -0
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
- package/src/modules/access/access-control.interface.ts +22 -0
- package/src/modules/access/access-control.service.ts +138 -15
- package/src/modules/access/access.routes.ts +22 -6
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +22 -1
- package/src/modules/agent-instructions/shared-file-rules.ts +1 -1
- package/src/modules/audit/__tests__/agent-audit.service.test.ts +78 -1
- package/src/modules/audit/__tests__/audit.routes.test.ts +43 -5
- package/src/modules/audit/agent-audit.service.ts +66 -6
- package/src/modules/audit/audit.contract.ts +62 -10
- package/src/modules/audit/audit.routes.ts +14 -12
- package/src/modules/audit/request-audit.ts +28 -13
- package/src/modules/database/core-schema.ts +15 -6
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.worktree.test.ts +76 -0
- package/src/modules/diff/diff.service.ts +6 -4
- package/src/modules/kb-fs/__tests__/git-dir.test.ts +77 -0
- package/src/modules/kb-fs/__tests__/mutex.canonical.test.ts +57 -0
- package/src/modules/kb-fs/__tests__/ref-files.test.ts +338 -0
- package/src/modules/kb-fs/git-dir.ts +53 -0
- package/src/modules/kb-fs/index.ts +3 -0
- package/src/modules/kb-fs/locking-filesystem.ts +3 -12
- package/src/modules/kb-fs/mutex.ts +16 -0
- package/src/modules/kb-fs/ref-files.ts +279 -0
- package/src/modules/mcp/__tests__/mcp-routes-harness.ts +7 -1
- package/src/modules/mcp/__tests__/mcp.routes.page.test.ts +115 -0
- package/src/modules/mcp/__tests__/mcp.surface-cache.test.ts +521 -0
- package/src/modules/mcp/__tests__/shared-definitions.test.ts +28 -0
- package/src/modules/mcp/__tests__/surface-cache.test.ts +127 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +21 -0
- package/src/modules/mcp/mcp.routes.ts +68 -0
- package/src/modules/mcp/mcp.service.ts +315 -51
- package/src/modules/mcp/request-context.ts +34 -0
- package/src/modules/mcp/shared-definitions.ts +121 -0
- package/src/modules/mcp/surface-cache.ts +154 -0
- package/src/modules/plugins/__tests__/teams.routes.test.ts +55 -0
- package/src/modules/plugins/teams.routes.ts +14 -1
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +2 -2
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +2 -2
- package/src/modules/tool-auth/internal-token.service.ts +1 -1
- package/src/modules/tool-auth/tool-auth.middleware.ts +1 -2
- package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +2 -2
- package/src/modules/tool-helpers/tool-context.ts +37 -18
- package/src/modules/tool-helpers/tool-handler.ts +2 -2
- package/src/modules/tool-helpers/tool.contract.ts +10 -2
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +1 -1
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +7 -2
- package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +23 -12
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +250 -4
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +464 -4
- package/src/modules/workflow/agent-tools/change-request-read.tools.ts +4 -22
- package/src/modules/workflow/agent-tools/workflow.tools.ts +462 -1
- package/src/modules/workflow/git/__tests__/git.service.changedPathsMemo.test.ts +175 -0
- package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +76 -11
- package/src/modules/workflow/git/__tests__/git.service.mergeIntoBranch.test.ts +721 -0
- package/src/modules/workflow/git/__tests__/git.service.worktrees.test.ts +284 -0
- package/src/modules/workflow/git/git.service.ts +719 -126
- package/src/modules/workflow/read-on-branch.ts +79 -0
- package/src/modules/workflow/workflow-hooks.ts +1 -1
- package/src/modules/workflow/workflow.routes.ts +21 -39
- package/src/modules/workflow/workflow.service.ts +203 -16
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +2 -2
- package/src/modules/workspace/__tests__/bounded-matcher.test.ts +213 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +22 -7
- package/src/modules/workspace/__tests__/kb-repository.test.ts +481 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +14 -0
- package/src/modules/workspace/__tests__/routine-write-policy.test.ts +0 -11
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +4 -3
- package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +12 -5
- package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.test.ts +24 -23
- package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.worktrees.test.ts +620 -0
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +15 -1
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +71 -5
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +153 -298
- package/src/modules/workspace/agent-access.gate.ts +2 -2
- package/src/modules/workspace/bounded-matcher.ts +328 -0
- package/src/modules/workspace/fetch-instant.ts +13 -0
- package/src/modules/workspace/index.ts +23 -0
- package/src/modules/workspace/kb-repository.contract.ts +124 -0
- package/src/modules/workspace/kb-repository.ts +844 -0
- package/src/modules/workspace/pattern-matcher.contract.ts +69 -0
- package/src/modules/workspace/routine-write-policy.ts +0 -15
- package/src/modules/workspace/set-aside-clone.ts +140 -0
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +3 -2
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +12 -10
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.worktrees.test.ts +613 -0
- package/src/modules/workspace/startup/kb-startup-runner.ts +422 -29
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +4 -3
- package/src/modules/workspace/workspace.service.ts +247 -169
- package/src/modules/workspace/workspace.tools.ts +179 -365
- package/src/shared/__tests__/no-link-below.test.ts +45 -0
- package/src/shared/git.contract.ts +10 -0
- package/src/shared/no-link-below.ts +29 -0
- package/src/test-setup.ts +5 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type IPatternMatcher, type IPatternSearch } from './pattern-matcher.contract.js';
|
|
2
|
+
/**
|
|
3
|
+
* The one place a CALLER'S regular expression is run (see
|
|
4
|
+
* {@link IPatternMatcher}).
|
|
5
|
+
*
|
|
6
|
+
* The pattern never runs on the request thread: the lines go to a worker, the
|
|
7
|
+
* worker answers which of them match, and a search whose matching outlives its
|
|
8
|
+
* budget has its worker terminated (which interrupts even a regex
|
|
9
|
+
* mid-backtrack) and is answered with {@link PatternTooExpensiveError}.
|
|
10
|
+
* Nothing partial is returned: a search that blew its budget answers the 400
|
|
11
|
+
* alone.
|
|
12
|
+
*
|
|
13
|
+
* The semantics are the engine's own — the worker compiles the same source with
|
|
14
|
+
* the same flags and calls `test` on each line — so a pattern within budget
|
|
15
|
+
* matches exactly the lines it always did.
|
|
16
|
+
*
|
|
17
|
+
* The pool is this instance's own: the composition root builds one per graph
|
|
18
|
+
* and closes it when the graph stops, so no worker outlives what it served.
|
|
19
|
+
*/
|
|
20
|
+
export interface WorkerPatternMatcherOptions {
|
|
21
|
+
/** Matching time one search may spend, summed over every file it searches. Default 5 s. */
|
|
22
|
+
budgetMs?: number;
|
|
23
|
+
/** Workers kept for searches at once; a search past this waits for one to free up. Default 4. */
|
|
24
|
+
poolMax?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Searches that may wait for a worker at once. A waiting search holds the
|
|
27
|
+
* lines it was handed, so the queue is capped: past it a search is refused
|
|
28
|
+
* with a 503 rather than piling file contents up in memory. Default 16.
|
|
29
|
+
*/
|
|
30
|
+
maxWaiting?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Longest pattern accepted. The pattern is compiled on the request thread
|
|
33
|
+
* (that is how a syntax error earns its 400 there), so its length is what
|
|
34
|
+
* bounds that. Default 1000.
|
|
35
|
+
*/
|
|
36
|
+
maxPatternLength?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Characters handed to the worker in one message. Posting a message copies
|
|
39
|
+
* it on the request thread, so a large file goes over in pieces of about
|
|
40
|
+
* this size rather than in one copy that would stall every other request.
|
|
41
|
+
* A single line longer than this is not posted at all: it is written into
|
|
42
|
+
* shared memory this many characters at a time, yielding between pieces,
|
|
43
|
+
* and the worker reads it from there. Default 1 MB.
|
|
44
|
+
*/
|
|
45
|
+
batchChars?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Lines handed to the worker in one message. Each line is an entry the
|
|
48
|
+
* copy has to walk whatever its length, so a file of empty lines is bounded
|
|
49
|
+
* by this, not by `batchChars`. Default 10,000.
|
|
50
|
+
*/
|
|
51
|
+
batchLines?: number;
|
|
52
|
+
}
|
|
53
|
+
export declare class WorkerPatternMatcher implements IPatternMatcher {
|
|
54
|
+
private readonly budgetMs;
|
|
55
|
+
private readonly poolMax;
|
|
56
|
+
private readonly maxWaiting;
|
|
57
|
+
private readonly maxPatternLength;
|
|
58
|
+
private readonly batchChars;
|
|
59
|
+
private readonly batchLines;
|
|
60
|
+
private readonly idle;
|
|
61
|
+
private readonly all;
|
|
62
|
+
private readonly waiting;
|
|
63
|
+
private closed;
|
|
64
|
+
private readonly lease;
|
|
65
|
+
constructor(opts?: WorkerPatternMatcherOptions);
|
|
66
|
+
search(source: string, flags: string): IPatternSearch;
|
|
67
|
+
close(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Where the batch starting at `from` ends: about `batchChars` characters on,
|
|
70
|
+
* at most `batchLines` lines on, and never empty. A batch of one line past
|
|
71
|
+
* `batchChars` is handed over through shared memory instead (see
|
|
72
|
+
* {@link BoundedSearch.matchBatch}).
|
|
73
|
+
*/
|
|
74
|
+
private batchEnd;
|
|
75
|
+
private acquire;
|
|
76
|
+
private release;
|
|
77
|
+
private spawn;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=bounded-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-matcher.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/bounded-matcher.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EAGpB,MAAM,+BAA+B,CAAC;AAEvC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,2BAA2B;IAC1C,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA4CD,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAElB,IAAI,GAAE,2BAAgC;IAiBlD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc;IAgB/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;YAQF,OAAO;IAcrB,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,KAAK;CAcd"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { Worker } from 'node:worker_threads';
|
|
2
|
+
import { ToolError } from '../tool-helpers/tool.contract.js';
|
|
3
|
+
import { PatternTooExpensiveError, SearchBusyError, } from './pattern-matcher.contract.js';
|
|
4
|
+
/**
|
|
5
|
+
* Slack on top of the remaining budget before a batch is given up on: the
|
|
6
|
+
* budget counts only the worker's own matching time, so handing the lines over
|
|
7
|
+
* and the answer back must not be what trips it.
|
|
8
|
+
*/
|
|
9
|
+
const TRANSFER_GRACE_MS = 250;
|
|
10
|
+
/** The worker: compiles the pattern it is handed and answers the indices of the lines it matches. */
|
|
11
|
+
const WORKER_SOURCE = `
|
|
12
|
+
const { parentPort } = require('node:worker_threads');
|
|
13
|
+
const { performance } = require('node:perf_hooks');
|
|
14
|
+
let cached = { key: null, re: null };
|
|
15
|
+
parentPort.on('message', ({ source, flags, lines, shared, limit }) => {
|
|
16
|
+
try {
|
|
17
|
+
// One line too long to post, written into shared memory as raw UTF-16 code units.
|
|
18
|
+
if (shared) lines = [Buffer.from(shared).toString('utf16le')];
|
|
19
|
+
const key = flags + '/' + source;
|
|
20
|
+
if (cached.key !== key) cached = { key, re: new RegExp(source, flags) };
|
|
21
|
+
const re = cached.re;
|
|
22
|
+
const started = performance.now();
|
|
23
|
+
const hits = [];
|
|
24
|
+
for (let i = 0; i < lines.length && hits.length < limit; i++) {
|
|
25
|
+
re.lastIndex = 0;
|
|
26
|
+
if (re.test(lines[i])) hits.push(i);
|
|
27
|
+
}
|
|
28
|
+
parentPort.postMessage({ hits, elapsed: performance.now() - started });
|
|
29
|
+
} catch (err) {
|
|
30
|
+
parentPort.postMessage({ error: String(err && err.message ? err.message : err) });
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
`;
|
|
34
|
+
export class WorkerPatternMatcher {
|
|
35
|
+
budgetMs;
|
|
36
|
+
poolMax;
|
|
37
|
+
maxWaiting;
|
|
38
|
+
maxPatternLength;
|
|
39
|
+
batchChars;
|
|
40
|
+
batchLines;
|
|
41
|
+
idle = [];
|
|
42
|
+
all = new Set();
|
|
43
|
+
waiting = [];
|
|
44
|
+
closed = false;
|
|
45
|
+
lease;
|
|
46
|
+
constructor(opts = {}) {
|
|
47
|
+
this.budgetMs = option('budgetMs', opts.budgetMs ?? 5_000, 1, MAX_TIMER_MS - TRANSFER_GRACE_MS);
|
|
48
|
+
// A pool of none would leave every search waiting for a worker that never comes.
|
|
49
|
+
this.poolMax = option('poolMax', opts.poolMax ?? 4, 1);
|
|
50
|
+
// No queue at all is allowed: every search past the pool is refused busy.
|
|
51
|
+
this.maxWaiting = option('maxWaiting', opts.maxWaiting ?? 16, 0);
|
|
52
|
+
this.maxPatternLength = option('maxPatternLength', opts.maxPatternLength ?? 1_000, 1);
|
|
53
|
+
this.batchChars = option('batchChars', opts.batchChars ?? 1_000_000, 1);
|
|
54
|
+
this.batchLines = option('batchLines', opts.batchLines ?? 10_000, 1);
|
|
55
|
+
this.lease = {
|
|
56
|
+
acquire: () => this.acquire(),
|
|
57
|
+
release: (w) => this.release(w),
|
|
58
|
+
batchEnd: (lines, from) => this.batchEnd(lines, from),
|
|
59
|
+
batchChars: this.batchChars,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
search(source, flags) {
|
|
63
|
+
if (source.length > this.maxPatternLength) {
|
|
64
|
+
throw new ToolError(`Pattern too long: ${source.length} characters, and a search pattern may have at most ${this.maxPatternLength}.`, 400, { code: 'pattern_too_long' });
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
new RegExp(source, flags);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
throw new ToolError(`Invalid regex: ${err.message}`, 400);
|
|
71
|
+
}
|
|
72
|
+
return new BoundedSearch(this.lease, source, flags, this.budgetMs);
|
|
73
|
+
}
|
|
74
|
+
async close() {
|
|
75
|
+
this.closed = true;
|
|
76
|
+
for (const waiter of this.waiting.splice(0))
|
|
77
|
+
waiter.reject(new SearchBusyError());
|
|
78
|
+
const workers = [...this.all];
|
|
79
|
+
this.idle.length = 0;
|
|
80
|
+
await Promise.all(workers.map((w) => w.terminate()));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Where the batch starting at `from` ends: about `batchChars` characters on,
|
|
84
|
+
* at most `batchLines` lines on, and never empty. A batch of one line past
|
|
85
|
+
* `batchChars` is handed over through shared memory instead (see
|
|
86
|
+
* {@link BoundedSearch.matchBatch}).
|
|
87
|
+
*/
|
|
88
|
+
batchEnd(lines, from) {
|
|
89
|
+
let to = from;
|
|
90
|
+
let chars = 0;
|
|
91
|
+
const last = Math.min(lines.length, from + this.batchLines);
|
|
92
|
+
while (to < last && (to === from || chars + lines[to].length <= this.batchChars))
|
|
93
|
+
chars += lines[to++].length;
|
|
94
|
+
return to;
|
|
95
|
+
}
|
|
96
|
+
async acquire() {
|
|
97
|
+
if (this.closed)
|
|
98
|
+
throw new SearchBusyError();
|
|
99
|
+
if (this.idle.length === 0 && this.all.size >= this.poolMax && this.waiting.length >= this.maxWaiting) {
|
|
100
|
+
throw new SearchBusyError();
|
|
101
|
+
}
|
|
102
|
+
const w = this.idle.pop() ??
|
|
103
|
+
(this.all.size < this.poolMax
|
|
104
|
+
? this.spawn()
|
|
105
|
+
: await new Promise((resolve, reject) => this.waiting.push({ resolve, reject })));
|
|
106
|
+
w.ref();
|
|
107
|
+
return w;
|
|
108
|
+
}
|
|
109
|
+
release(w) {
|
|
110
|
+
const next = this.waiting.shift();
|
|
111
|
+
if (next)
|
|
112
|
+
return next.resolve(w);
|
|
113
|
+
// An idle worker must not hold a process's exit open.
|
|
114
|
+
w.unref();
|
|
115
|
+
this.idle.push(w);
|
|
116
|
+
}
|
|
117
|
+
spawn() {
|
|
118
|
+
const w = new Worker(WORKER_SOURCE, { eval: true });
|
|
119
|
+
this.all.add(w);
|
|
120
|
+
// A worker that dies — terminated over budget, or out of memory — leaves the pool.
|
|
121
|
+
w.once('exit', () => {
|
|
122
|
+
this.all.delete(w);
|
|
123
|
+
const at = this.idle.indexOf(w);
|
|
124
|
+
if (at >= 0)
|
|
125
|
+
this.idle.splice(at, 1);
|
|
126
|
+
if (this.closed)
|
|
127
|
+
return;
|
|
128
|
+
const next = this.waiting.shift();
|
|
129
|
+
if (next)
|
|
130
|
+
next.resolve(this.spawn());
|
|
131
|
+
});
|
|
132
|
+
return w;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** One search: a caller's pattern, matched off the event loop under one budget. */
|
|
136
|
+
class BoundedSearch {
|
|
137
|
+
pool;
|
|
138
|
+
source;
|
|
139
|
+
flags;
|
|
140
|
+
budgetMs;
|
|
141
|
+
spentMs = 0;
|
|
142
|
+
constructor(pool, source, flags, budgetMs) {
|
|
143
|
+
this.pool = pool;
|
|
144
|
+
this.source = source;
|
|
145
|
+
this.flags = flags;
|
|
146
|
+
this.budgetMs = budgetMs;
|
|
147
|
+
}
|
|
148
|
+
async matchingLines(lines, limit) {
|
|
149
|
+
if (limit <= 0 || lines.length === 0)
|
|
150
|
+
return [];
|
|
151
|
+
if (this.spentMs >= this.budgetMs)
|
|
152
|
+
throw new PatternTooExpensiveError(this.source, this.budgetMs);
|
|
153
|
+
const w = await this.pool.acquire();
|
|
154
|
+
const hits = [];
|
|
155
|
+
try {
|
|
156
|
+
for (let from = 0; from < lines.length && hits.length < limit;) {
|
|
157
|
+
const to = this.pool.batchEnd(lines, from);
|
|
158
|
+
for (const i of await this.matchBatch(w, lines.slice(from, to), limit - hits.length))
|
|
159
|
+
hits.push(from + i);
|
|
160
|
+
from = to;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
// Terminating is what stops a regex mid-backtrack; the pool replaces it.
|
|
165
|
+
void w.terminate();
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
this.pool.release(w);
|
|
169
|
+
return hits;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* One handoff to the worker, charged to this search's budget. No handoff
|
|
173
|
+
* copies more than `batchChars` characters on the request thread at once: a
|
|
174
|
+
* line longer than that goes over in shared memory, not in the message.
|
|
175
|
+
*/
|
|
176
|
+
async matchBatch(w, lines, limit) {
|
|
177
|
+
if (this.spentMs >= this.budgetMs)
|
|
178
|
+
throw new PatternTooExpensiveError(this.source, this.budgetMs);
|
|
179
|
+
const oversized = lines.length === 1 && lines[0].length > this.pool.batchChars;
|
|
180
|
+
const payload = oversized ? { shared: await shareLine(w, lines[0], this.pool.batchChars) } : { lines };
|
|
181
|
+
const remaining = this.budgetMs - this.spentMs;
|
|
182
|
+
const reply = await run(w, { source: this.source, flags: this.flags, ...payload, limit }, remaining + TRANSFER_GRACE_MS);
|
|
183
|
+
if (reply === 'timeout') {
|
|
184
|
+
this.spentMs = this.budgetMs;
|
|
185
|
+
throw new PatternTooExpensiveError(this.source, this.budgetMs);
|
|
186
|
+
}
|
|
187
|
+
if ('error' in reply)
|
|
188
|
+
throw new ToolError(`Invalid regex: ${reply.error}`, 400);
|
|
189
|
+
this.spentMs += reply.elapsed;
|
|
190
|
+
if (this.spentMs > this.budgetMs)
|
|
191
|
+
throw new PatternTooExpensiveError(this.source, this.budgetMs);
|
|
192
|
+
return reply.hits;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* A line as raw UTF-16 code units in shared memory, which a message hands the
|
|
197
|
+
* worker without copying. It is written `chunkChars` at a time with a turn of
|
|
198
|
+
* the event loop between, so a line of any length never holds the request
|
|
199
|
+
* thread for longer than one chunk. Raw code units keep the line exact, lone
|
|
200
|
+
* surrogates included.
|
|
201
|
+
*
|
|
202
|
+
* The worker it is meant for can be terminated by `close()` during those turns,
|
|
203
|
+
* before {@link run} listens for its exit; a message posted to it then would
|
|
204
|
+
* never be answered. So its exit is watched here too: writing stops and the
|
|
205
|
+
* search is answered busy, as one terminated under `run` is.
|
|
206
|
+
*/
|
|
207
|
+
async function shareLine(w, line, chunkChars) {
|
|
208
|
+
let exited = false;
|
|
209
|
+
const onExit = () => {
|
|
210
|
+
exited = true;
|
|
211
|
+
};
|
|
212
|
+
w.once('exit', onExit);
|
|
213
|
+
try {
|
|
214
|
+
const shared = new SharedArrayBuffer(line.length * 2);
|
|
215
|
+
const bytes = Buffer.from(shared);
|
|
216
|
+
for (let at = 0; at < line.length && !exited; at += chunkChars) {
|
|
217
|
+
if (at > 0)
|
|
218
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
219
|
+
bytes.write(line.slice(at, at + chunkChars), at * 2, 'utf16le');
|
|
220
|
+
}
|
|
221
|
+
if (exited)
|
|
222
|
+
throw new SearchBusyError();
|
|
223
|
+
return shared;
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
w.off('exit', onExit);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function run(w, message, timeoutMs) {
|
|
230
|
+
return new Promise((resolve, reject) => {
|
|
231
|
+
const settle = (fn) => {
|
|
232
|
+
clearTimeout(timer);
|
|
233
|
+
w.off('message', onMessage);
|
|
234
|
+
w.off('error', onError);
|
|
235
|
+
w.off('exit', onExit);
|
|
236
|
+
fn();
|
|
237
|
+
};
|
|
238
|
+
const onMessage = (reply) => settle(() => resolve(reply));
|
|
239
|
+
const onError = (err) => settle(() => reject(err));
|
|
240
|
+
// Terminated under the search by `close()`: answered as busy, not left hanging until the timer.
|
|
241
|
+
const onExit = () => settle(() => reject(new SearchBusyError()));
|
|
242
|
+
const timer = setTimeout(() => settle(() => resolve('timeout')), timeoutMs);
|
|
243
|
+
w.on('message', onMessage);
|
|
244
|
+
w.on('error', onError);
|
|
245
|
+
w.on('exit', onExit);
|
|
246
|
+
w.postMessage(message);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The longest delay `setTimeout` honours. A longer one fires after 1 ms, so a
|
|
251
|
+
* budget past this (less the grace added to it) would stop every search at once.
|
|
252
|
+
*/
|
|
253
|
+
const MAX_TIMER_MS = 2_147_483_647;
|
|
254
|
+
/** A sizing option as given, refused at construction unless it is an integer from `min` to `max`. */
|
|
255
|
+
function option(name, value, min, max = Number.MAX_SAFE_INTEGER) {
|
|
256
|
+
if (!Number.isInteger(value) || value < min || value > max) {
|
|
257
|
+
throw new RangeError(`WorkerPatternMatcher: ${name} must be an integer from ${min} to ${max}, got ${value}.`);
|
|
258
|
+
}
|
|
259
|
+
return value;
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=bounded-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-matcher.js","sourceRoot":"","sources":["../../../src/modules/workspace/bounded-matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An instant on the one clock that fetch starts and `fetchedSince` instants
|
|
3
|
+
* are read from. Milliseconds, like `Date.now()`, but strictly increasing in
|
|
4
|
+
* call order: two readings never compare equal, so a fetch started in the
|
|
5
|
+
* same millisecond as a listing is still ordered before or after it, and
|
|
6
|
+
* "started after the instant" is a strict comparison that cannot be a tie.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fetchInstant(): number;
|
|
9
|
+
//# sourceMappingURL=fetch-instant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-instant.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/fetch-instant.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
let last = 0;
|
|
2
|
+
/**
|
|
3
|
+
* An instant on the one clock that fetch starts and `fetchedSince` instants
|
|
4
|
+
* are read from. Milliseconds, like `Date.now()`, but strictly increasing in
|
|
5
|
+
* call order: two readings never compare equal, so a fetch started in the
|
|
6
|
+
* same millisecond as a listing is still ordered before or after it, and
|
|
7
|
+
* "started after the instant" is a strict comparison that cannot be a tie.
|
|
8
|
+
*/
|
|
9
|
+
export function fetchInstant() {
|
|
10
|
+
last = Math.max(Date.now(), last + 0.001);
|
|
11
|
+
return last;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=fetch-instant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-instant.js","sourceRoot":"","sources":["../../../src/modules/workspace/fetch-instant.ts"],"names":[],"mappings":"AAAA,IAAI,IAAI,GAAG,CAAC,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -7,4 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { FileReaderRegistry, type FileKind, type FileReader, type ReadResult, } from './file-readers/file-reader.js';
|
|
9
9
|
export { OCTET_STREAM, rawExtensionOf, rawMimeFor } from './file-readers/raw-mime.js';
|
|
10
|
+
/**
|
|
11
|
+
* The knowledge base's one repository, every branch workspace a worktree of
|
|
12
|
+
* it. (Where a checkout's git directory is — its `.git` folder, or the
|
|
13
|
+
* folder its `.git` FILE names — is `kb-fs/git-dir.ts`.)
|
|
14
|
+
*/
|
|
15
|
+
export { KbRepository, repositoryDirFor, workingCopyShape, type WorkingCopyShape, } from './kb-repository.js';
|
|
16
|
+
export type { AddWorktreeOptions, FetchOptions, IKbRepository } from './kb-repository.contract.js';
|
|
17
|
+
export { assertAgentWriteAllowed, notifyAgentRead, SESSION_ID_DESCRIPTION, SESSION_ID_INPUT, ToolDescriptionNotes, type AgentAccessGate, } from './agent-access.gate.js';
|
|
18
|
+
export { SpillStore } from './spill-store.js';
|
|
10
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACtF;;;;GAIG;AACH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGnG,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -7,4 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { FileReaderRegistry, } from './file-readers/file-reader.js';
|
|
9
9
|
export { OCTET_STREAM, rawExtensionOf, rawMimeFor } from './file-readers/raw-mime.js';
|
|
10
|
+
/**
|
|
11
|
+
* The knowledge base's one repository, every branch workspace a worktree of
|
|
12
|
+
* it. (Where a checkout's git directory is — its `.git` folder, or the
|
|
13
|
+
* folder its `.git` FILE names — is `kb-fs/git-dir.ts`.)
|
|
14
|
+
*/
|
|
15
|
+
export { KbRepository, repositoryDirFor, workingCopyShape, } from './kb-repository.js';
|
|
16
|
+
// The agent-access gate: what a module's agent tools take to tell the
|
|
17
|
+
// deployment's hooks of a read or a write, and the session input they declare.
|
|
18
|
+
export { assertAgentWriteAllowed, notifyAgentRead, SESSION_ID_DESCRIPTION, SESSION_ID_INPUT, ToolDescriptionNotes, } from './agent-access.gate.js';
|
|
19
|
+
export { SpillStore } from './spill-store.js';
|
|
10
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,kBAAkB,GAInB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,kBAAkB,GAInB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACtF;;;;GAIG;AACH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAE5B,sEAAsE;AACtE,+EAA+E;AAC/E,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The knowledge base's one repository, every branch workspace a worktree of
|
|
3
|
+
* it — the contract its consumers (the workspace service, the KB startup
|
|
4
|
+
* phase, the set-aside of a moved repository, the git layer) depend on.
|
|
5
|
+
* `KbRepository` (`kb-repository.ts`) is the implementation, a bare
|
|
6
|
+
* repository driven by the git CLI; the composition root makes ONE and
|
|
7
|
+
* injects it everywhere, so that one fetch serves every workspace and the
|
|
8
|
+
* repository's administration — its creation, the writes to its one config
|
|
9
|
+
* file, its worktree list, a set-aside — is serialized in one place.
|
|
10
|
+
*
|
|
11
|
+
* Nothing else is serialized by the application: git was built for many
|
|
12
|
+
* worktrees of one repository, and protects the refs, `packed-refs` and the
|
|
13
|
+
* object store with its own locks. The worktree list (`worktrees/`) it does
|
|
14
|
+
* not lock, which is why adding, removing and pruning worktrees are
|
|
15
|
+
* administration here. Two worktrees run side by side, as two developers'
|
|
16
|
+
* worktrees of one repository do.
|
|
17
|
+
*/
|
|
18
|
+
export interface FetchOptions {
|
|
19
|
+
/** A fetch that SUCCEEDED this recently is fresh enough; nothing runs. */
|
|
20
|
+
maxAgeMs: number;
|
|
21
|
+
/**
|
|
22
|
+
* An instant (`fetchInstant()`): a success counts as fresh only when
|
|
23
|
+
* its fetch started after it, however young it is (a fetch from before a listing may lack
|
|
24
|
+
* what the listing saw). A fetch in flight that started before it is
|
|
25
|
+
* waited for, not joined, and a fresh one runs.
|
|
26
|
+
*/
|
|
27
|
+
fetchedSince?: number;
|
|
28
|
+
/** Skip the freshness window (the in-flight join still applies). */
|
|
29
|
+
force?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* A fetch that FAILED this recently is not retried: the answer is the
|
|
32
|
+
* failure. For pollers, so a host that is down is not asked again on every
|
|
33
|
+
* request. Absent, a failure is retried on the next call.
|
|
34
|
+
*/
|
|
35
|
+
failureBackoffMs?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface AddWorktreeOptions {
|
|
38
|
+
/** A converted clone whose branch was never pushed: its local ref is enough. */
|
|
39
|
+
allowLocalOnly?: boolean;
|
|
40
|
+
/** A conversion: a local ref behind the remote stays where it is. */
|
|
41
|
+
keepLocalTip?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Reuse the repository's own fetch when it started after this instant
|
|
44
|
+
* (`fetchInstant()`)
|
|
45
|
+
* and knows the branch. An instant, not an age: it is compared inside the
|
|
46
|
+
* reservation, so time spent waiting for it cannot age a fetch out.
|
|
47
|
+
*/
|
|
48
|
+
fetchedSince?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface IKbRepository {
|
|
51
|
+
/** The bare repository's folder. */
|
|
52
|
+
readonly dir: string;
|
|
53
|
+
/**
|
|
54
|
+
* Run `fn` as the repository's one administrator for its duration: no
|
|
55
|
+
* creation of the repository, no write to its one config file (git refuses
|
|
56
|
+
* a second writer of it rather than waiting), no change to its worktree
|
|
57
|
+
* list (which git does not lock: a prune beside a `worktree add` can take
|
|
58
|
+
* the entry being made), and no set-aside runs beside it. Git operations
|
|
59
|
+
* in the worktrees are not held back — git's own locks cover them — so a
|
|
60
|
+
* caller that moves the repository's folders holds those off itself (the
|
|
61
|
+
* startup phase runs before anything is served; the workspace service
|
|
62
|
+
* wraps a set-aside in what surrounds one). Never nested: `fn` must not
|
|
63
|
+
* call `exclusive` again, nor a method that does (`ensure`,
|
|
64
|
+
* `refreshCredentials`, `writeConfig`, `addWorktree`, `removeWorktree`,
|
|
65
|
+
* `forgetWorktrees`, `prune`, `setOriginUrl`).
|
|
66
|
+
*/
|
|
67
|
+
exclusive<T>(fn: () => Promise<T>): Promise<T>;
|
|
68
|
+
/** Whether the repository is on disk and finished (its first fetch landed). */
|
|
69
|
+
exists(): Promise<boolean>;
|
|
70
|
+
/** Create the repository and fetch it once when it is not there. Throws with git's words, redacted. */
|
|
71
|
+
ensure(): Promise<void>;
|
|
72
|
+
/** Re-stamp the credential helper when the deployment's credential changed. */
|
|
73
|
+
refreshCredentials(): Promise<void>;
|
|
74
|
+
/** Run `git config` writes against the shared configuration, one writer at a time. */
|
|
75
|
+
writeConfig(cwd: string, argLists: readonly string[][]): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Garbage-collect the repository when git finds it worth it (`gc --auto`
|
|
78
|
+
* with git's default thresholds). Automatic collection is off on the
|
|
79
|
+
* repository — a commit in one worktree would otherwise collect beside
|
|
80
|
+
* every other worktree's work — so the startup phase runs this once, when
|
|
81
|
+
* nothing else does. Never throws.
|
|
82
|
+
*/
|
|
83
|
+
maintain(): Promise<void>;
|
|
84
|
+
/** The last time the repository reached the remote and whether it worked; null before any attempt. */
|
|
85
|
+
lastContact(): {
|
|
86
|
+
at: number;
|
|
87
|
+
ok: boolean;
|
|
88
|
+
} | null;
|
|
89
|
+
/** Why the last fetch failed, redacted; null when it did not. */
|
|
90
|
+
lastFetchFailure(): string | null;
|
|
91
|
+
/**
|
|
92
|
+
* `git fetch --prune origin`, once for every workspace: throttled, and
|
|
93
|
+
* joined while in flight. Answers whether the remote-tracking refs are
|
|
94
|
+
* provably fresh. Never throws.
|
|
95
|
+
*/
|
|
96
|
+
fetch(opts: FetchOptions): Promise<boolean>;
|
|
97
|
+
/** Forget what this process knows of the repository (it was set aside). */
|
|
98
|
+
forget(): void;
|
|
99
|
+
/** Add the worktree of `branch` at `checkoutDir`, copying no history. */
|
|
100
|
+
addWorktree(branch: string, checkoutDir: string, opts?: AddWorktreeOptions): Promise<void>;
|
|
101
|
+
/** Remove and prune the worktree at `checkoutDir`, with its branch's local ref; nothing else. */
|
|
102
|
+
removeWorktree(checkoutDir: string, branch: string): Promise<void>;
|
|
103
|
+
/** Prune worktrees whose folders were deleted by hand, and drop their branches' local refs. */
|
|
104
|
+
forgetWorktrees(branches: readonly string[]): Promise<void>;
|
|
105
|
+
/** `git worktree prune`. */
|
|
106
|
+
prune(): Promise<void>;
|
|
107
|
+
/** The folders of the repository's worktrees, as git lists them. */
|
|
108
|
+
listWorktrees(): Promise<string[]>;
|
|
109
|
+
/** Import the tip of `branch` from the full clone at `cloneDir` (unpushed commits included); answers the tip. */
|
|
110
|
+
importBranch(cloneDir: string, branch: string): Promise<string>;
|
|
111
|
+
/**
|
|
112
|
+
* Import the full clone's stash entries and its other local refs (not its own
|
|
113
|
+
* branch, not remote-tracking ones) under `refs/kb-converted/<workspaceId>/`,
|
|
114
|
+
* leaving the clone as it was; answers the refs written.
|
|
115
|
+
*/
|
|
116
|
+
importLocalRefs(cloneDir: string, branch: string, workspaceId: string): Promise<string[]>;
|
|
117
|
+
/** The address the repository fetches from, or null when it cannot be read. */
|
|
118
|
+
originUrl(): Promise<string | null>;
|
|
119
|
+
/** Re-link a repository and its worktrees that were moved together; answers the worktrees that could not be. */
|
|
120
|
+
relinkMovedCopy(movedRepository: string, movedWorktrees: readonly string[]): Promise<string[]>;
|
|
121
|
+
/** Point the repository at `url`, forgetting the old address's fetch freshness. */
|
|
122
|
+
setOriginUrl(url: string): Promise<void>;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=kb-repository.contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-repository.contract.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/kb-repository.contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The knowledge base's one repository, every branch workspace a worktree of
|
|
3
|
+
* it — the contract its consumers (the workspace service, the KB startup
|
|
4
|
+
* phase, the set-aside of a moved repository, the git layer) depend on.
|
|
5
|
+
* `KbRepository` (`kb-repository.ts`) is the implementation, a bare
|
|
6
|
+
* repository driven by the git CLI; the composition root makes ONE and
|
|
7
|
+
* injects it everywhere, so that one fetch serves every workspace and the
|
|
8
|
+
* repository's administration — its creation, the writes to its one config
|
|
9
|
+
* file, its worktree list, a set-aside — is serialized in one place.
|
|
10
|
+
*
|
|
11
|
+
* Nothing else is serialized by the application: git was built for many
|
|
12
|
+
* worktrees of one repository, and protects the refs, `packed-refs` and the
|
|
13
|
+
* object store with its own locks. The worktree list (`worktrees/`) it does
|
|
14
|
+
* not lock, which is why adding, removing and pruning worktrees are
|
|
15
|
+
* administration here. Two worktrees run side by side, as two developers'
|
|
16
|
+
* worktrees of one repository do.
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=kb-repository.contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-repository.contract.js","sourceRoot":"","sources":["../../../src/modules/workspace/kb-repository.contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
|