@plurnk/plurnk-service 1.0.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/.env.defaults +208 -0
- package/INSTALL.md +69 -0
- package/LICENSE +21 -0
- package/README.md +46 -0
- package/SPEC.md +1511 -0
- package/dist/Paths.d.ts +13 -0
- package/dist/Paths.d.ts.map +1 -0
- package/dist/Paths.js +60 -0
- package/dist/Paths.js.map +1 -0
- package/dist/content/edited-span.d.ts +2 -0
- package/dist/content/edited-span.d.ts.map +1 -0
- package/dist/content/edited-span.js +33 -0
- package/dist/content/edited-span.js.map +1 -0
- package/dist/content/index.d.ts +10 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +11 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/line-marker.d.ts +15 -0
- package/dist/content/line-marker.d.ts.map +1 -0
- package/dist/content/line-marker.js +21 -0
- package/dist/content/line-marker.js.map +1 -0
- package/dist/content/matcher.d.ts +44 -0
- package/dist/content/matcher.d.ts.map +1 -0
- package/dist/content/matcher.js +126 -0
- package/dist/content/matcher.js.map +1 -0
- package/dist/content/mimetype-binary.d.ts +8 -0
- package/dist/content/mimetype-binary.d.ts.map +1 -0
- package/dist/content/mimetype-binary.js +17 -0
- package/dist/content/mimetype-binary.js.map +1 -0
- package/dist/content/path-mimetype.d.ts +5 -0
- package/dist/content/path-mimetype.d.ts.map +1 -0
- package/dist/content/path-mimetype.js +15 -0
- package/dist/content/path-mimetype.js.map +1 -0
- package/dist/content/read-resolve.d.ts +20 -0
- package/dist/content/read-resolve.d.ts.map +1 -0
- package/dist/content/read-resolve.js +68 -0
- package/dist/content/read-resolve.js.map +1 -0
- package/dist/core/ChannelWrite.d.ts +100 -0
- package/dist/core/ChannelWrite.d.ts.map +1 -0
- package/dist/core/ChannelWrite.js +112 -0
- package/dist/core/ChannelWrite.js.map +1 -0
- package/dist/core/ChannelWrite.sql +84 -0
- package/dist/core/Db.d.ts +14 -0
- package/dist/core/Db.d.ts.map +1 -0
- package/dist/core/Db.js +7 -0
- package/dist/core/Db.js.map +1 -0
- package/dist/core/Dispatcher.d.ts +67 -0
- package/dist/core/Dispatcher.d.ts.map +1 -0
- package/dist/core/Dispatcher.js +1021 -0
- package/dist/core/Dispatcher.js.map +1 -0
- package/dist/core/Engine.d.ts +113 -0
- package/dist/core/Engine.d.ts.map +1 -0
- package/dist/core/Engine.js +1410 -0
- package/dist/core/Engine.js.map +1 -0
- package/dist/core/Engine.sql +538 -0
- package/dist/core/EnvFlags.d.ts +13 -0
- package/dist/core/EnvFlags.d.ts.map +1 -0
- package/dist/core/EnvFlags.js +84 -0
- package/dist/core/EnvFlags.js.map +1 -0
- package/dist/core/ExecutorRegistry.d.ts +45 -0
- package/dist/core/ExecutorRegistry.d.ts.map +1 -0
- package/dist/core/ExecutorRegistry.js +128 -0
- package/dist/core/ExecutorRegistry.js.map +1 -0
- package/dist/core/PacketBuilder.d.ts +67 -0
- package/dist/core/PacketBuilder.d.ts.map +1 -0
- package/dist/core/PacketBuilder.js +524 -0
- package/dist/core/PacketBuilder.js.map +1 -0
- package/dist/core/PluginLoader.d.ts +17 -0
- package/dist/core/PluginLoader.d.ts.map +1 -0
- package/dist/core/PluginLoader.js +97 -0
- package/dist/core/PluginLoader.js.map +1 -0
- package/dist/core/ProposalLifecycle.d.ts +59 -0
- package/dist/core/ProposalLifecycle.d.ts.map +1 -0
- package/dist/core/ProposalLifecycle.js +215 -0
- package/dist/core/ProposalLifecycle.js.map +1 -0
- package/dist/core/ProviderInstantiate.d.ts +9 -0
- package/dist/core/ProviderInstantiate.d.ts.map +1 -0
- package/dist/core/ProviderInstantiate.js +156 -0
- package/dist/core/ProviderInstantiate.js.map +1 -0
- package/dist/core/SchemeRegistry.d.ts +26 -0
- package/dist/core/SchemeRegistry.d.ts.map +1 -0
- package/dist/core/SchemeRegistry.js +205 -0
- package/dist/core/SchemeRegistry.js.map +1 -0
- package/dist/core/StrikeRail.d.ts +28 -0
- package/dist/core/StrikeRail.d.ts.map +1 -0
- package/dist/core/StrikeRail.js +165 -0
- package/dist/core/StrikeRail.js.map +1 -0
- package/dist/core/TelemetryChannel.d.ts +37 -0
- package/dist/core/TelemetryChannel.d.ts.map +1 -0
- package/dist/core/TelemetryChannel.js +77 -0
- package/dist/core/TelemetryChannel.js.map +1 -0
- package/dist/core/TokenGauge.d.ts +16 -0
- package/dist/core/TokenGauge.d.ts.map +1 -0
- package/dist/core/TokenGauge.js +58 -0
- package/dist/core/TokenGauge.js.map +1 -0
- package/dist/core/caps/CapsResolve.d.ts +5 -0
- package/dist/core/caps/CapsResolve.d.ts.map +1 -0
- package/dist/core/caps/CapsResolve.js +13 -0
- package/dist/core/caps/CapsResolve.js.map +1 -0
- package/dist/core/caps/DbChannelCaps.d.ts +16 -0
- package/dist/core/caps/DbChannelCaps.d.ts.map +1 -0
- package/dist/core/caps/DbChannelCaps.js +41 -0
- package/dist/core/caps/DbChannelCaps.js.map +1 -0
- package/dist/core/caps/DbEntryCaps.d.ts +19 -0
- package/dist/core/caps/DbEntryCaps.d.ts.map +1 -0
- package/dist/core/caps/DbEntryCaps.js +28 -0
- package/dist/core/caps/DbEntryCaps.js.map +1 -0
- package/dist/core/caps/DbNotifyCaps.d.ts +8 -0
- package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -0
- package/dist/core/caps/DbNotifyCaps.js +35 -0
- package/dist/core/caps/DbNotifyCaps.js.map +1 -0
- package/dist/core/caps/DbSubscriptionCaps.d.ts +10 -0
- package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -0
- package/dist/core/caps/DbSubscriptionCaps.js +86 -0
- package/dist/core/caps/DbSubscriptionCaps.js.map +1 -0
- package/dist/core/caps/DbTagCaps.d.ts +17 -0
- package/dist/core/caps/DbTagCaps.d.ts.map +1 -0
- package/dist/core/caps/DbTagCaps.js +37 -0
- package/dist/core/caps/DbTagCaps.js.map +1 -0
- package/dist/core/caps/SchemeCtxImpl.d.ts +18 -0
- package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -0
- package/dist/core/caps/SchemeCtxImpl.js +42 -0
- package/dist/core/caps/SchemeCtxImpl.js.map +1 -0
- package/dist/core/env-defaults.d.ts +19 -0
- package/dist/core/env-defaults.d.ts.map +1 -0
- package/dist/core/env-defaults.js +89 -0
- package/dist/core/env-defaults.js.map +1 -0
- package/dist/core/fork.d.ts +6 -0
- package/dist/core/fork.d.ts.map +1 -0
- package/dist/core/fork.js +84 -0
- package/dist/core/fork.js.map +1 -0
- package/dist/core/fork.sql +85 -0
- package/dist/core/git-membership.d.ts +23 -0
- package/dist/core/git-membership.d.ts.map +1 -0
- package/dist/core/git-membership.js +366 -0
- package/dist/core/git-membership.js.map +1 -0
- package/dist/core/git-state.d.ts +15 -0
- package/dist/core/git-state.d.ts.map +1 -0
- package/dist/core/git-state.js +67 -0
- package/dist/core/git-state.js.map +1 -0
- package/dist/core/packet-inject.d.ts +5 -0
- package/dist/core/packet-inject.d.ts.map +1 -0
- package/dist/core/packet-inject.js +48 -0
- package/dist/core/packet-inject.js.map +1 -0
- package/dist/core/packet-wire.d.ts +46 -0
- package/dist/core/packet-wire.d.ts.map +1 -0
- package/dist/core/packet-wire.js +453 -0
- package/dist/core/packet-wire.js.map +1 -0
- package/dist/core/path-decode.d.ts +2 -0
- package/dist/core/path-decode.d.ts.map +1 -0
- package/dist/core/path-decode.js +8 -0
- package/dist/core/path-decode.js.map +1 -0
- package/dist/core/plugin-attribution.d.ts +5 -0
- package/dist/core/plugin-attribution.d.ts.map +1 -0
- package/dist/core/plugin-attribution.js +39 -0
- package/dist/core/plugin-attribution.js.map +1 -0
- package/dist/core/plurnk-uri.d.ts +7 -0
- package/dist/core/plurnk-uri.d.ts.map +1 -0
- package/dist/core/plurnk-uri.js +52 -0
- package/dist/core/plurnk-uri.js.map +1 -0
- package/dist/core/resolveForLoop.d.ts +5 -0
- package/dist/core/resolveForLoop.d.ts.map +1 -0
- package/dist/core/resolveForLoop.js +12 -0
- package/dist/core/resolveForLoop.js.map +1 -0
- package/dist/core/results.d.ts +12 -0
- package/dist/core/results.d.ts.map +1 -0
- package/dist/core/results.js +27 -0
- package/dist/core/results.js.map +1 -0
- package/dist/core/run-cap.d.ts +8 -0
- package/dist/core/run-cap.d.ts.map +1 -0
- package/dist/core/run-cap.js +20 -0
- package/dist/core/run-cap.js.map +1 -0
- package/dist/core/run-ops.sql +43 -0
- package/dist/core/scheme-types.d.ts +45 -0
- package/dist/core/scheme-types.d.ts.map +1 -0
- package/dist/core/scheme-types.js +6 -0
- package/dist/core/scheme-types.js.map +1 -0
- package/dist/core/session-settings.d.ts +23 -0
- package/dist/core/session-settings.d.ts.map +1 -0
- package/dist/core/session-settings.js +55 -0
- package/dist/core/session-settings.js.map +1 -0
- package/dist/core/teaching.d.ts +3 -0
- package/dist/core/teaching.d.ts.map +1 -0
- package/dist/core/teaching.js +13 -0
- package/dist/core/teaching.js.map +1 -0
- package/dist/core/types.d.ts +3 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/digest/Digest.d.ts +20 -0
- package/dist/digest/Digest.d.ts.map +1 -0
- package/dist/digest/Digest.js +451 -0
- package/dist/digest/Digest.js.map +1 -0
- package/dist/digest/Digest.sql +1 -0
- package/dist/digest/digest.sql +55 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/schemes/EffectPolicy.d.ts +6 -0
- package/dist/schemes/EffectPolicy.d.ts.map +1 -0
- package/dist/schemes/EffectPolicy.js +18 -0
- package/dist/schemes/EffectPolicy.js.map +1 -0
- package/dist/schemes/Exec.d.ts +39 -0
- package/dist/schemes/Exec.d.ts.map +1 -0
- package/dist/schemes/Exec.js +510 -0
- package/dist/schemes/Exec.js.map +1 -0
- package/dist/schemes/ExecOutputScheme.d.ts +20 -0
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -0
- package/dist/schemes/ExecOutputScheme.js +39 -0
- package/dist/schemes/ExecOutputScheme.js.map +1 -0
- package/dist/schemes/File.d.ts +42 -0
- package/dist/schemes/File.d.ts.map +1 -0
- package/dist/schemes/File.js +356 -0
- package/dist/schemes/File.js.map +1 -0
- package/dist/schemes/Known.d.ts +17 -0
- package/dist/schemes/Known.d.ts.map +1 -0
- package/dist/schemes/Known.js +40 -0
- package/dist/schemes/Known.js.map +1 -0
- package/dist/schemes/Log.d.ts +22 -0
- package/dist/schemes/Log.d.ts.map +1 -0
- package/dist/schemes/Log.js +269 -0
- package/dist/schemes/Log.js.map +1 -0
- package/dist/schemes/Log.sql +59 -0
- package/dist/schemes/Plurnk.d.ts +17 -0
- package/dist/schemes/Plurnk.d.ts.map +1 -0
- package/dist/schemes/Plurnk.js +46 -0
- package/dist/schemes/Plurnk.js.map +1 -0
- package/dist/schemes/Run.d.ts +25 -0
- package/dist/schemes/Run.d.ts.map +1 -0
- package/dist/schemes/Run.js +172 -0
- package/dist/schemes/Run.js.map +1 -0
- package/dist/schemes/Skill.d.ts +17 -0
- package/dist/schemes/Skill.d.ts.map +1 -0
- package/dist/schemes/Skill.js +40 -0
- package/dist/schemes/Skill.js.map +1 -0
- package/dist/schemes/Unknown.d.ts +17 -0
- package/dist/schemes/Unknown.d.ts.map +1 -0
- package/dist/schemes/Unknown.js +39 -0
- package/dist/schemes/Unknown.js.map +1 -0
- package/dist/schemes/_entry-chunk.d.ts +11 -0
- package/dist/schemes/_entry-chunk.d.ts.map +1 -0
- package/dist/schemes/_entry-chunk.js +100 -0
- package/dist/schemes/_entry-chunk.js.map +1 -0
- package/dist/schemes/_entry-crud.d.ts +31 -0
- package/dist/schemes/_entry-crud.d.ts.map +1 -0
- package/dist/schemes/_entry-crud.js +77 -0
- package/dist/schemes/_entry-crud.js.map +1 -0
- package/dist/schemes/_entry-crud.sql +101 -0
- package/dist/schemes/_entry-find.d.ts +32 -0
- package/dist/schemes/_entry-find.d.ts.map +1 -0
- package/dist/schemes/_entry-find.js +226 -0
- package/dist/schemes/_entry-find.js.map +1 -0
- package/dist/schemes/_entry-find.sql +54 -0
- package/dist/schemes/_entry-graph.d.ts +16 -0
- package/dist/schemes/_entry-graph.d.ts.map +1 -0
- package/dist/schemes/_entry-graph.js +94 -0
- package/dist/schemes/_entry-graph.js.map +1 -0
- package/dist/schemes/_entry-graph.sql +52 -0
- package/dist/schemes/_entry-manifest.d.ts +25 -0
- package/dist/schemes/_entry-manifest.d.ts.map +1 -0
- package/dist/schemes/_entry-manifest.js +266 -0
- package/dist/schemes/_entry-manifest.js.map +1 -0
- package/dist/schemes/_entry-ops.d.ts +32 -0
- package/dist/schemes/_entry-ops.d.ts.map +1 -0
- package/dist/schemes/_entry-ops.js +216 -0
- package/dist/schemes/_entry-ops.js.map +1 -0
- package/dist/schemes/_entry-ops.sql +31 -0
- package/dist/schemes/_entry-semantic.d.ts +38 -0
- package/dist/schemes/_entry-semantic.d.ts.map +1 -0
- package/dist/schemes/_entry-semantic.js +202 -0
- package/dist/schemes/_entry-semantic.js.map +1 -0
- package/dist/schemes/_entry-semantic.sql +95 -0
- package/dist/schemes/_entry-send.d.ts +11 -0
- package/dist/schemes/_entry-send.d.ts.map +1 -0
- package/dist/schemes/_entry-send.js +66 -0
- package/dist/schemes/_entry-send.js.map +1 -0
- package/dist/schemes/cosine.d.ts +4 -0
- package/dist/schemes/cosine.d.ts.map +1 -0
- package/dist/schemes/cosine.js +9 -0
- package/dist/schemes/cosine.js.map +1 -0
- package/dist/schemes/exec-abort.d.ts +15 -0
- package/dist/schemes/exec-abort.d.ts.map +1 -0
- package/dist/schemes/exec-abort.js +29 -0
- package/dist/schemes/exec-abort.js.map +1 -0
- package/dist/schemes/exec-env.d.ts +5 -0
- package/dist/schemes/exec-env.d.ts.map +1 -0
- package/dist/schemes/exec-env.js +34 -0
- package/dist/schemes/exec-env.js.map +1 -0
- package/dist/server/Daemon.d.ts +244 -0
- package/dist/server/Daemon.d.ts.map +1 -0
- package/dist/server/Daemon.js +1119 -0
- package/dist/server/Daemon.js.map +1 -0
- package/dist/server/client-input.d.ts +11 -0
- package/dist/server/client-input.d.ts.map +1 -0
- package/dist/server/client-input.js +145 -0
- package/dist/server/client-input.js.map +1 -0
- package/dist/server/clientTurn.d.ts +6 -0
- package/dist/server/clientTurn.d.ts.map +1 -0
- package/dist/server/clientTurn.js +23 -0
- package/dist/server/clientTurn.js.map +1 -0
- package/dist/server/clientTurn.sql +10 -0
- package/dist/server/dispatch-as-plurnk.d.ts +7 -0
- package/dist/server/dispatch-as-plurnk.d.ts.map +1 -0
- package/dist/server/dispatch-as-plurnk.js +23 -0
- package/dist/server/dispatch-as-plurnk.js.map +1 -0
- package/dist/server/drain.sql +124 -0
- package/dist/server/envelope.d.ts +53 -0
- package/dist/server/envelope.d.ts.map +1 -0
- package/dist/server/envelope.js +172 -0
- package/dist/server/envelope.js.map +1 -0
- package/dist/server/envelope.sql +76 -0
- package/dist/server/logEntry.d.ts +35 -0
- package/dist/server/logEntry.d.ts.map +1 -0
- package/dist/server/logEntry.js +49 -0
- package/dist/server/logEntry.js.map +1 -0
- package/dist/server/logEntry.sql +10 -0
- package/dist/server/loopDocs.d.ts +6 -0
- package/dist/server/loopDocs.d.ts.map +1 -0
- package/dist/server/loopDocs.js +22 -0
- package/dist/server/loopDocs.js.map +1 -0
- package/dist/server/noProposals.d.ts +6 -0
- package/dist/server/noProposals.d.ts.map +1 -0
- package/dist/server/noProposals.js +37 -0
- package/dist/server/noProposals.js.map +1 -0
- package/dist/server/seam-entry-read.sql +21 -0
- package/dist/server/seam-log-read.sql +21 -0
- package/dist/server/seam-loop.sql +9 -0
- package/dist/server/seam-proposal-list.sql +13 -0
- package/dist/server/version-info.d.ts +14 -0
- package/dist/server/version-info.d.ts.map +1 -0
- package/dist/server/version-info.js +69 -0
- package/dist/server/version-info.js.map +1 -0
- package/dist/server/yolo.d.ts +6 -0
- package/dist/server/yolo.d.ts.map +1 -0
- package/dist/server/yolo.js +64 -0
- package/dist/server/yolo.js.map +1 -0
- package/dist/service.d.ts +6 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +309 -0
- package/dist/service.js.map +1 -0
- package/migrations/0000-00-00.01_schema.sql +500 -0
- package/package.json +86 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Db } from "../core/Db.ts";
|
|
2
|
+
import type { Mimetypes } from "@plurnk/plurnk-mimetypes";
|
|
3
|
+
export default class EntrySemantic {
|
|
4
|
+
#private;
|
|
5
|
+
static indexFts(db: Db, entryId: number, content: string): Promise<void>;
|
|
6
|
+
static cosine(a: Uint8Array, b: Uint8Array): number;
|
|
7
|
+
static indexEmbedding(db: Db, entryId: number, chunks: {
|
|
8
|
+
lineStart: number;
|
|
9
|
+
lineEnd: number;
|
|
10
|
+
vector: Uint8Array;
|
|
11
|
+
}[], model: string | undefined): Promise<void>;
|
|
12
|
+
static deriveEmbeddings(mimetypes: Mimetypes, content: string, symbols: readonly {
|
|
13
|
+
line?: number;
|
|
14
|
+
endLine?: number;
|
|
15
|
+
}[], fallbackEmbedding: Uint8Array | undefined, fallbackModel: string | undefined, signal?: AbortSignal, maxChunks?: number): Promise<{
|
|
16
|
+
chunks: {
|
|
17
|
+
lineStart: number;
|
|
18
|
+
lineEnd: number;
|
|
19
|
+
vector: Uint8Array;
|
|
20
|
+
}[];
|
|
21
|
+
model: string | undefined;
|
|
22
|
+
capped: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
static deepConfigSignature(mimetypes: Mimetypes): Promise<string>;
|
|
25
|
+
static ftsQueryFor(text: string): string;
|
|
26
|
+
static rankSemantic(db: Db, sessionId: number, scheme: string | null, mimetypes: Mimetypes, queryText: string, marker: {
|
|
27
|
+
first: number;
|
|
28
|
+
last: number | null;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
status: number;
|
|
31
|
+
results: Array<{
|
|
32
|
+
pathname: string;
|
|
33
|
+
lineStart: number;
|
|
34
|
+
lineEnd: number;
|
|
35
|
+
}>;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=_entry-semantic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_entry-semantic.d.ts","sourceRoot":"","sources":["../../src/schemes/_entry-semantic.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAO1D,MAAM,CAAC,OAAO,OAAO,aAAa;;IAG9B,OAAa,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7E;IAMD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAOlD;IAKD,OAAa,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAWnK;IAOD,OAAa,gBAAgB,CACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,SAAS;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,EACvD,iBAAiB,EAAE,UAAU,GAAG,SAAS,EACzC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,MAAM,CAAC,EAAE,WAAW,EACpB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;QAAE,MAAM,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,UAAU,CAAA;SAAE,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CA6C/H;IAmCD,OAAa,mBAAmB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAItE;IAID,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvC;IAMD,OAAa,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAyC1Q;CACJ"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// ~semantic (plurnk-service#186) — the FTS half. Re-indexes an entry's body
|
|
2
|
+
// content into entry_fts (the keyword/narrowing half of the fusion). The cosine
|
|
3
|
+
// rank over embedding vectors — the precise half — lands when the embedding
|
|
4
|
+
// channel does (a daughter projection, per the §mimetype boundary). Called from the
|
|
5
|
+
// gated manifest-add hook, so only when body content actually changed.
|
|
6
|
+
import EntryChunk from "./_entry-chunk.js";
|
|
7
|
+
export default class EntrySemantic {
|
|
8
|
+
// Replace an entry's FTS row with its current body content (rowid = entryId).
|
|
9
|
+
// Empty content (binary member / cleared entry) → no FTS row (delete only).
|
|
10
|
+
static async indexFts(db, entryId, content) {
|
|
11
|
+
await db.fts_delete.run({ entry_id: entryId });
|
|
12
|
+
if (content.length > 0)
|
|
13
|
+
await db.fts_insert.run({ entry_id: entryId, content });
|
|
14
|
+
}
|
|
15
|
+
// Cosine similarity over two Float32 vectors stored as BLOBs — the SqlRite
|
|
16
|
+
// `cosine()` function delegates here (cosine.ts is the registration adapter).
|
|
17
|
+
// Alignment-proof: the BLOB Uint8Array may be an unaligned view, so copy the
|
|
18
|
+
// exact bytes to a fresh buffer before the Float32 view. A zero vector → 0.
|
|
19
|
+
static cosine(a, b) {
|
|
20
|
+
const x = new Float32Array(a.buffer.slice(a.byteOffset, a.byteOffset + a.byteLength));
|
|
21
|
+
const y = new Float32Array(b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength));
|
|
22
|
+
let dot = 0, nx = 0, ny = 0;
|
|
23
|
+
for (let i = 0; i < x.length; i++) {
|
|
24
|
+
dot += x[i] * y[i];
|
|
25
|
+
nx += x[i] * x[i];
|
|
26
|
+
ny += y[i] * y[i];
|
|
27
|
+
}
|
|
28
|
+
const denom = Math.sqrt(nx) * Math.sqrt(ny);
|
|
29
|
+
return denom === 0 ? 0 : dot / denom;
|
|
30
|
+
}
|
|
31
|
+
// Store an entry's embedding vector + the model that produced it, or clear the
|
|
32
|
+
// row (binary/empty entry, or a degraded `embeddingMissing` projection). Called
|
|
33
|
+
// from the gated manifest-add hook beside indexFts / the symbol index.
|
|
34
|
+
static async indexEmbedding(db, entryId, chunks, model) {
|
|
35
|
+
// Re-derivation = clear all of the entry's chunk rows, then insert each in seq
|
|
36
|
+
// order. No model (no embedder installed) or no chunks → just cleared.
|
|
37
|
+
await db.embedding_delete.run({ entry_id: entryId });
|
|
38
|
+
if (model === undefined)
|
|
39
|
+
return;
|
|
40
|
+
for (const [seq, c] of chunks.entries()) {
|
|
41
|
+
await db.embedding_set.run({
|
|
42
|
+
entry_id: entryId, chunk_seq: seq, line_start: c.lineStart, line_end: c.lineEnd,
|
|
43
|
+
vector: c.vector, embedding_model: model,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Project Semantics — derive an entry's chunk embeddings. Probes the embedder
|
|
48
|
+
// capability (the daughter's window + tokenizer, surfaced via the Mimetypes
|
|
49
|
+
// handle): ABSENT → one whole-entry chunk from the fallback vector (today's
|
|
50
|
+
// behavior, no extra embed call); PRESENT → lossless tile, embed each chunk.
|
|
51
|
+
// Returns the chunk list + model for indexEmbedding; never touches the DB.
|
|
52
|
+
static async deriveEmbeddings(mimetypes, content, symbols, fallbackEmbedding, fallbackModel, signal, maxChunks) {
|
|
53
|
+
const info = await EntrySemantic.#embedderInfo(mimetypes);
|
|
54
|
+
if (info === null) {
|
|
55
|
+
const totalLines = content.length === 0 ? 0 : content.split("\n").length;
|
|
56
|
+
if (fallbackEmbedding === undefined || fallbackEmbedding.byteLength === 0 || totalLines === 0)
|
|
57
|
+
return { chunks: [], model: undefined, capped: false };
|
|
58
|
+
return { chunks: [{ lineStart: 1, lineEnd: totalLines, vector: fallbackEmbedding }], model: fallbackModel, capped: false };
|
|
59
|
+
}
|
|
60
|
+
// §semantic-entry-chunk-cap — a LATENCY stage, never a coverage bound: the INLINE
|
|
61
|
+
// (dispatch-time) path caps chunks so a cold ~query answers in bounded seconds, and a
|
|
62
|
+
// capped pass does NOT stamp the deep hash — the background pump completes the entry to
|
|
63
|
+
// FULL depth (a 300-page book is entirely searchable at steady state; rank can't be
|
|
64
|
+
// dominated regardless — semantic_rank takes one best chunk per entry). The old flat cap
|
|
65
|
+
// silently foreclosed legitimate large texts: head-only vectors under a whole-file FTS
|
|
66
|
+
// narrow returned head-biased spans forever, and the stamped hash made it permanent.
|
|
67
|
+
const CHUNK_CAP = maxChunks ?? Number.POSITIVE_INFINITY;
|
|
68
|
+
// Symbol edges (a @graph endLine, or the line before a symbol starts) are the
|
|
69
|
+
// tiler's preferred cut points; it still tiles every line if there are none.
|
|
70
|
+
const boundaries = new Set();
|
|
71
|
+
for (const s of symbols) {
|
|
72
|
+
if (typeof s.endLine === "number")
|
|
73
|
+
boundaries.add(s.endLine);
|
|
74
|
+
if (typeof s.line === "number" && s.line > 1)
|
|
75
|
+
boundaries.add(s.line - 1);
|
|
76
|
+
}
|
|
77
|
+
// mimetypes#50 — a REMOTE embedder is present with an incomplete self-report: the window
|
|
78
|
+
// is the operator's to declare (their knob), and the counter resolves through the seam's
|
|
79
|
+
// tokenizers by the embedder's model name — the chars/2 upper bound when inexact is the
|
|
80
|
+
// surfaced conservative fallback (smaller chunks are correct chunks).
|
|
81
|
+
if (info.maxTokens === null)
|
|
82
|
+
throw new Error("remote embedder reports no token window — set PLURNK_MIMETYPES_EMBED_MAX_TOKENS to the endpoint's limit");
|
|
83
|
+
const counter = info.countTokens ?? (await mimetypes.tokenizer(info.model ?? "")).countTokens;
|
|
84
|
+
const budget = EntrySemantic.#chunkBudget(info.maxTokens);
|
|
85
|
+
let specs = await EntryChunk.tile(content, boundaries, budget, EntrySemantic.#chunkOverlap(), counter);
|
|
86
|
+
if (specs.length === 0)
|
|
87
|
+
return { chunks: [], model: undefined, capped: false };
|
|
88
|
+
const capped = specs.length > CHUNK_CAP;
|
|
89
|
+
if (capped)
|
|
90
|
+
specs = specs.slice(0, CHUNK_CAP); // §semantic-entry-chunk-cap — inline latency stage; the pump completes
|
|
91
|
+
// One data-parallel batch over the tiled chunk texts (#272 — embedBatch via the
|
|
92
|
+
// framework seam, ~6× the per-chunk loop on a multi-core box; vectors bit-identical,
|
|
93
|
+
// so no re-embed). Each tile embeds as PLAIN TEXT: a chunk is a fragment, not a
|
|
94
|
+
// standalone document, so embedding under the entry's mimetype (e.g. application/json)
|
|
95
|
+
// re-validates the partial and throws — embedBatch embeds raw text directly.
|
|
96
|
+
const vectors = await mimetypes.embedBatch(specs.map((s) => s.text), { signal });
|
|
97
|
+
const chunks = [];
|
|
98
|
+
for (const [i, spec] of specs.entries()) {
|
|
99
|
+
const vector = vectors[i];
|
|
100
|
+
if (vector !== undefined && vector.byteLength > 0)
|
|
101
|
+
chunks.push({ lineStart: spec.lineStart, lineEnd: spec.lineEnd, vector });
|
|
102
|
+
}
|
|
103
|
+
return { chunks, model: chunks.length > 0 ? info.model : undefined, capped };
|
|
104
|
+
}
|
|
105
|
+
// Chunk budget in tokens — `.env.defaults` is the law, no code fallback. EMPTY =
|
|
106
|
+
// the embedder's reported window (scalable — NO model-specific number baked in);
|
|
107
|
+
// a positive value caps BELOW the window (e.g. to sweep granularity).
|
|
108
|
+
static #chunkBudget(maxTokens) {
|
|
109
|
+
const raw = process.env.PLURNK_SERVICE_SEMANTIC_CHUNK_TOKENS;
|
|
110
|
+
if (raw === undefined || raw.trim() === "")
|
|
111
|
+
return maxTokens;
|
|
112
|
+
const v = Number(raw);
|
|
113
|
+
if (!Number.isInteger(v) || v < 1)
|
|
114
|
+
throw new Error(`PLURNK_SERVICE_SEMANTIC_CHUNK_TOKENS must be empty (= the embedder's window) or a positive integer, got ${JSON.stringify(raw)}`);
|
|
115
|
+
return Math.min(v, maxTokens);
|
|
116
|
+
}
|
|
117
|
+
static #chunkOverlap() {
|
|
118
|
+
const v = Number(process.env.PLURNK_SERVICE_SEMANTIC_CHUNK_OVERLAP);
|
|
119
|
+
if (!(v >= 0 && v < 1))
|
|
120
|
+
throw new Error(`PLURNK_SERVICE_SEMANTIC_CHUNK_OVERLAP must be in [0,1), got ${JSON.stringify(process.env.PLURNK_SERVICE_SEMANTIC_CHUNK_OVERLAP)}`);
|
|
121
|
+
return v;
|
|
122
|
+
}
|
|
123
|
+
// The embedder capability surface (daughter window + tokenizer + model id), probed
|
|
124
|
+
// through the Mimetypes handle. null until an embedder is installed.
|
|
125
|
+
static async #embedderInfo(mimetypes) {
|
|
126
|
+
// PLURNK_SERVICE_EMBED_DISABLE=1 forces the no-embedder path even when the optional embeddings package
|
|
127
|
+
// IS installed — the whole semantic stack (deriveEmbeddings, the ~query FTS→cosine fusion, the
|
|
128
|
+
// deep_hash config) funnels through here, so one gate makes everything FTS-only. The fast lane
|
|
129
|
+
// (mock-provider tests) sets it so the suite doesn't spin up the MiniLM worker pool for nothing.
|
|
130
|
+
if (process.env.PLURNK_SERVICE_EMBED_DISABLE === "1")
|
|
131
|
+
return null;
|
|
132
|
+
return await mimetypes.embedderInfo();
|
|
133
|
+
}
|
|
134
|
+
// Folded into the entry's deep_hash so a derivation re-runs when the EMBEDDING
|
|
135
|
+
// inputs change, not just content: installing/swapping the embedder (the window
|
|
136
|
+
// flips none→N, activating tiling), the embedder's model id changing at the SAME
|
|
137
|
+
// window (#31 — else stale vectors from the old model's space survive the swap and
|
|
138
|
+
// get cosine-compared against the new model's), or sweeping the chunk knobs.
|
|
139
|
+
static async deepConfigSignature(mimetypes) {
|
|
140
|
+
const info = await EntrySemantic.#embedderInfo(mimetypes);
|
|
141
|
+
if (info === null)
|
|
142
|
+
return "embed:none";
|
|
143
|
+
return `embed:${info.model ?? "?"}:${info.maxTokens}:${info.maxTokens === null ? "?" : EntrySemantic.#chunkBudget(info.maxTokens)}:${EntrySemantic.#chunkOverlap()}`;
|
|
144
|
+
}
|
|
145
|
+
// Build the FTS5 narrow from a ~query: OR the alphanumeric terms (a broad cut —
|
|
146
|
+
// cosine does the precision). FTS5-syntax-safe (bare lowercased terms).
|
|
147
|
+
static ftsQueryFor(text) {
|
|
148
|
+
const terms = text.toLowerCase().match(/[a-z0-9]+/g);
|
|
149
|
+
if (terms === null)
|
|
150
|
+
return "";
|
|
151
|
+
return [...new Set(terms)].join(" OR ");
|
|
152
|
+
}
|
|
153
|
+
// The ~query dispatch: embed the query text through the SAME channel, FTS-narrow by
|
|
154
|
+
// its terms, cosine-rank the narrowed set, top-K. Each result carries its best-matching
|
|
155
|
+
// chunk's line span (the Finding extent). No embedder → the top-K <K> form degrades to an
|
|
156
|
+
// FTS-only keyword rank (whole-entry findings); the <0.x> threshold form stays 501.
|
|
157
|
+
static async rankSemantic(db, sessionId, scheme, mimetypes, queryText, marker) {
|
|
158
|
+
const ftsQuery = EntrySemantic.ftsQueryFor(queryText);
|
|
159
|
+
if (ftsQuery.length === 0)
|
|
160
|
+
return { status: 200, results: [] };
|
|
161
|
+
// #209 — the result marker form-dispatches: integer <K> → top-K rank;
|
|
162
|
+
// decimal <0.x> → a similarity threshold (minimum cosine in (0,1)), with
|
|
163
|
+
// <0.x,N> capping the threshold set at N (else unbounded). A fractional
|
|
164
|
+
// value outside (0,1) is a nonsense result-marker → 416, never coerced.
|
|
165
|
+
const { first, last } = marker;
|
|
166
|
+
const toResult = (x) => ({ pathname: x.pathname, lineStart: x.line_start, lineEnd: x.line_end });
|
|
167
|
+
// The query embedding honors the SAME gate as the corpus (#embedderInfo /
|
|
168
|
+
// PLURNK_SERVICE_EMBED_DISABLE): with the embeddings package installed but disabled,
|
|
169
|
+
// calling process() directly would compute a query vector and rank it against
|
|
170
|
+
// an empty entry_embeddings — every ~query silently []. Disabled → the honest
|
|
171
|
+
// FTS keyword fallback, same as no embedder at all.
|
|
172
|
+
const info = await EntrySemantic.#embedderInfo(mimetypes);
|
|
173
|
+
const r = info === null
|
|
174
|
+
? { embedding: undefined, embeddingModel: undefined }
|
|
175
|
+
: await mimetypes.process({ content: queryText, hint: "text/markdown" }, { channels: ["embedding"] });
|
|
176
|
+
if (r.embedding === undefined || r.embedding.byteLength === 0 || r.embeddingModel === undefined) {
|
|
177
|
+
// FTS fallback: no embedder, so there is no query vector to cosine with. Top-K ranks
|
|
178
|
+
// by BM25 keyword relevance alone; the <0.x> threshold form is intrinsically cosine-
|
|
179
|
+
// based (no bounded BM25 analogue) → it stays 501.
|
|
180
|
+
if (!Number.isInteger(first))
|
|
181
|
+
return { status: 501, results: [] };
|
|
182
|
+
const rows = await db.semantic_rank_fts.all({
|
|
183
|
+
fts_query: ftsQuery, session_id: sessionId, scheme, k: first,
|
|
184
|
+
});
|
|
185
|
+
return { status: 200, results: rows.map(toResult) };
|
|
186
|
+
}
|
|
187
|
+
if (Number.isInteger(first)) {
|
|
188
|
+
const rows = await db.semantic_rank.all({
|
|
189
|
+
fts_query: ftsQuery, session_id: sessionId, scheme, query_vector: r.embedding, embedding_model: r.embeddingModel, k: first,
|
|
190
|
+
});
|
|
191
|
+
return { status: 200, results: rows.map(toResult) };
|
|
192
|
+
}
|
|
193
|
+
if (first <= 0 || first >= 1)
|
|
194
|
+
return { status: 416, results: [] };
|
|
195
|
+
const cap = (last !== null && Number.isInteger(last) && last > 0) ? last : -1;
|
|
196
|
+
const rows = await db.semantic_rank_threshold.all({
|
|
197
|
+
fts_query: ftsQuery, session_id: sessionId, scheme, query_vector: r.embedding, embedding_model: r.embeddingModel, threshold: first, cap,
|
|
198
|
+
});
|
|
199
|
+
return { status: 200, results: rows.map(toResult) };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=_entry-semantic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_entry-semantic.js","sourceRoot":"","sources":["../../src/schemes/_entry-semantic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
-- ~semantic (plurnk-service#186) — the FTS half of the dialect (FTS narrow →
|
|
2
|
+
-- cosine rank). Populated at the gated manifest-add hook; the FTS5 rowid IS the
|
|
3
|
+
-- entry id, so a re-index is delete-by-rowid then insert.
|
|
4
|
+
|
|
5
|
+
-- PREP: fts_delete
|
|
6
|
+
DELETE FROM entry_fts WHERE rowid = $entry_id;
|
|
7
|
+
|
|
8
|
+
-- PREP: fts_insert
|
|
9
|
+
INSERT INTO entry_fts (rowid, content) VALUES ($entry_id, $content);
|
|
10
|
+
|
|
11
|
+
-- PREP: embedding_set
|
|
12
|
+
-- Insert ONE chunk's vector + its <L> extent + the model. The caller clears the
|
|
13
|
+
-- entry's rows (embedding_delete) first and inserts each chunk in seq order, so no
|
|
14
|
+
-- upsert is needed — a re-derivation is delete-all then insert-each.
|
|
15
|
+
INSERT INTO entry_embeddings (entry_id, chunk_seq, line_start, line_end, vector, embedding_model)
|
|
16
|
+
VALUES ($entry_id, $chunk_seq, $line_start, $line_end, $vector, $embedding_model);
|
|
17
|
+
|
|
18
|
+
-- PREP: embedding_delete
|
|
19
|
+
-- Clears ALL of an entry's chunk rows (the re-derivation reset).
|
|
20
|
+
DELETE FROM entry_embeddings WHERE entry_id = $entry_id;
|
|
21
|
+
|
|
22
|
+
-- PREP: semantic_rank
|
|
23
|
+
-- The ~semantic fusion: FTS narrows by keyword ($fts_query), then cosine ranks the
|
|
24
|
+
-- narrowed candidates over the query embedding ($query_vector), top-K. Scheme-scoped
|
|
25
|
+
-- like every dialect. FTS does the scale-cut; cosine the precise rank — so a high-
|
|
26
|
+
-- cosine entry that doesn't match the keyword is correctly excluded by the narrow.
|
|
27
|
+
-- Many chunk rows per entry → rank by the entry's BEST chunk (per-entry top cosine via
|
|
28
|
+
-- ROW_NUMBER), and surface that winning chunk's line span as the finding extent
|
|
29
|
+
-- (Project Findings). embedding_model filter keeps cosine within one model's dimensions.
|
|
30
|
+
WITH ranked AS (
|
|
31
|
+
SELECT e.pathname, em.line_start, em.line_end,
|
|
32
|
+
cosine(em.vector, $query_vector) AS score,
|
|
33
|
+
ROW_NUMBER() OVER (PARTITION BY e.id ORDER BY cosine(em.vector, $query_vector) DESC) AS rn
|
|
34
|
+
FROM entry_fts f
|
|
35
|
+
JOIN entries e ON e.id = f.rowid
|
|
36
|
+
JOIN entry_embeddings em ON em.entry_id = e.id AND em.embedding_model = $embedding_model
|
|
37
|
+
WHERE f.content MATCH $fts_query
|
|
38
|
+
AND e.session_id = $session_id
|
|
39
|
+
AND e.scheme IS $scheme
|
|
40
|
+
)
|
|
41
|
+
SELECT pathname, line_start, line_end FROM ranked
|
|
42
|
+
WHERE rn = 1
|
|
43
|
+
ORDER BY score DESC
|
|
44
|
+
LIMIT $k;
|
|
45
|
+
|
|
46
|
+
-- PREP: semantic_rank_threshold
|
|
47
|
+
-- #209 — the <0.x> similarity-threshold form: same FTS+cosine fusion, but a cosine
|
|
48
|
+
-- floor ($threshold, in (0,1)) replaces top-K, and $cap (-1 = unbounded) is the
|
|
49
|
+
-- optional <0.x,N> result cap.
|
|
50
|
+
WITH ranked AS (
|
|
51
|
+
SELECT e.pathname, em.line_start, em.line_end,
|
|
52
|
+
cosine(em.vector, $query_vector) AS score,
|
|
53
|
+
ROW_NUMBER() OVER (PARTITION BY e.id ORDER BY cosine(em.vector, $query_vector) DESC) AS rn
|
|
54
|
+
FROM entry_fts f
|
|
55
|
+
JOIN entries e ON e.id = f.rowid
|
|
56
|
+
JOIN entry_embeddings em ON em.entry_id = e.id AND em.embedding_model = $embedding_model
|
|
57
|
+
WHERE f.content MATCH $fts_query
|
|
58
|
+
AND e.session_id = $session_id
|
|
59
|
+
AND e.scheme IS $scheme
|
|
60
|
+
)
|
|
61
|
+
SELECT pathname, line_start, line_end FROM ranked
|
|
62
|
+
WHERE rn = 1 AND score >= $threshold
|
|
63
|
+
ORDER BY score DESC
|
|
64
|
+
LIMIT $cap;
|
|
65
|
+
|
|
66
|
+
-- PREP: semantic_rank_fts
|
|
67
|
+
-- FTS-only fallback when no embedder is installed: rank entry_fts by BM25 keyword
|
|
68
|
+
-- relevance alone (no entry_embeddings join, no cosine), scheme-scoped, top-K. Without
|
|
69
|
+
-- chunk vectors there is no winning span, so the finding is the whole entry — line
|
|
70
|
+
-- 1..its line count, derived from the indexed FTS content.
|
|
71
|
+
SELECT e.pathname,
|
|
72
|
+
1 AS line_start,
|
|
73
|
+
length(f.content) - length(replace(f.content, char(10), '')) + 1 AS line_end
|
|
74
|
+
FROM entry_fts f
|
|
75
|
+
JOIN entries e ON e.id = f.rowid
|
|
76
|
+
WHERE f.content MATCH $fts_query
|
|
77
|
+
AND e.session_id = $session_id
|
|
78
|
+
AND e.scheme IS $scheme
|
|
79
|
+
ORDER BY rank
|
|
80
|
+
LIMIT $k;
|
|
81
|
+
|
|
82
|
+
-- PREP: semantic_fts_candidates
|
|
83
|
+
-- §semantic-cold-query-full-fidelity — the FTS-narrowed candidate slice, BM25-ordered,
|
|
84
|
+
-- with the derivation inputs (content/mimetype/deep_hash) so the caller can derive any
|
|
85
|
+
-- stale candidate INLINE before ranking. Ranking only ever scores this narrowed set, so
|
|
86
|
+
-- embedding exactly this slice on demand gives bit-identical results to a warm corpus.
|
|
87
|
+
SELECT e.id AS entry_id, e.pathname, ec.content, ec.mimetype, e.deep_hash, 'body' AS channel
|
|
88
|
+
FROM entry_fts f
|
|
89
|
+
JOIN entries e ON e.id = f.rowid
|
|
90
|
+
JOIN entry_channels ec ON ec.entry_id = e.id AND ec.name = 'body'
|
|
91
|
+
WHERE f.content MATCH $fts_query
|
|
92
|
+
AND e.session_id = $session_id
|
|
93
|
+
AND e.scheme IS $scheme
|
|
94
|
+
ORDER BY bm25(entry_fts)
|
|
95
|
+
LIMIT $cap;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SendStatement } from "@plurnk/plurnk-grammar";
|
|
2
|
+
import type { PlurnkSchemeContext } from "../core/scheme-types.ts";
|
|
3
|
+
export interface SendResult {
|
|
4
|
+
status: number;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
export default class EntrySend {
|
|
8
|
+
#private;
|
|
9
|
+
static sendToSessionEntry(statement: SendStatement, ctx: PlurnkSchemeContext, scheme: string): Promise<SendResult>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=_entry-send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_entry-send.d.ts","sourceRoot":"","sources":["../../src/schemes/_entry-send.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAInE,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,CAAC,OAAO,OAAO,SAAS;;IAc1B,OAAa,kBAAkB,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuCvH;CACJ"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Shared SEND dispatcher for entry-bearing schemes. Schemes interpret
|
|
2
|
+
// status codes per SPEC §send-dispatch. v0 handles 410 (Gone, delete the resource)
|
|
3
|
+
// and 499 (Client Closed Request, cancel active subscription).
|
|
4
|
+
import { decodePathParens } from "../core/path-decode.js";
|
|
5
|
+
import EntryCrud from "./_entry-crud.js";
|
|
6
|
+
import ChannelWrite from "../core/ChannelWrite.js";
|
|
7
|
+
export default class EntrySend {
|
|
8
|
+
static #pathnameOf(statement) {
|
|
9
|
+
const path = statement.target;
|
|
10
|
+
if (path === null)
|
|
11
|
+
return null;
|
|
12
|
+
if (path.kind === "regex")
|
|
13
|
+
return path.raw; // regex source — parens are syntax, never encoded
|
|
14
|
+
return decodePathParens(path.kind === "url" ? path.pathname : path.raw); // #239 item 4
|
|
15
|
+
}
|
|
16
|
+
static #fragmentOf(statement) {
|
|
17
|
+
const path = statement.target;
|
|
18
|
+
if (path === null || path.kind !== "url")
|
|
19
|
+
return null;
|
|
20
|
+
return path.fragment;
|
|
21
|
+
}
|
|
22
|
+
static async sendToSessionEntry(statement, ctx, scheme) {
|
|
23
|
+
if (statement.target === null)
|
|
24
|
+
return { status: 400, error: "directed SEND requires a path" };
|
|
25
|
+
const status = statement.signal;
|
|
26
|
+
if (status === null)
|
|
27
|
+
return { status: 400, error: "SEND requires a numeric status code" };
|
|
28
|
+
// SEND[410] Gone — delete the targeted resource (SPEC §send-dispatch). With a
|
|
29
|
+
// #fragment, deletes just that channel; without, deletes the whole entry.
|
|
30
|
+
if (status === 410) {
|
|
31
|
+
const pathname = EntrySend.#pathnameOf(statement);
|
|
32
|
+
if (pathname === null)
|
|
33
|
+
return { status: 400 };
|
|
34
|
+
const fragment = EntrySend.#fragmentOf(statement);
|
|
35
|
+
if (fragment !== null) {
|
|
36
|
+
const { db, sessionId } = ctx;
|
|
37
|
+
const entry = await db.crud_find_session_entry.get({ session_id: sessionId, scheme, pathname });
|
|
38
|
+
if (entry === undefined)
|
|
39
|
+
return { status: 404 };
|
|
40
|
+
const deleted = await db.crud_delete_channel.get({ entry_id: entry.id, name: fragment });
|
|
41
|
+
return { status: deleted === undefined ? 404 : 200 };
|
|
42
|
+
}
|
|
43
|
+
const result = await EntryCrud.deleteEntry(pathname, ctx, scheme);
|
|
44
|
+
return { status: result.status };
|
|
45
|
+
}
|
|
46
|
+
// SEND[499] Client Closed Request — cancel active subscription (SPEC §send-dispatch, §stream-control).
|
|
47
|
+
// Entry-bearing schemes never have subscriptions in v0; always return 404.
|
|
48
|
+
// Streaming schemes (sse / exec / etc.) override this and look up via
|
|
49
|
+
// findActiveSubscription, then call their teardown using the stored handle.
|
|
50
|
+
if (status === 499) {
|
|
51
|
+
const pathname = EntrySend.#pathnameOf(statement);
|
|
52
|
+
if (pathname === null)
|
|
53
|
+
return { status: 400 };
|
|
54
|
+
const { db, sessionId, runId } = ctx;
|
|
55
|
+
const entry = await db.crud_find_session_entry.get({ session_id: sessionId, scheme, pathname });
|
|
56
|
+
if (entry === undefined)
|
|
57
|
+
return { status: 404, error: "no entry at path" };
|
|
58
|
+
const subscription = await ChannelWrite.findActiveSubscription(db, { runId, entryId: entry.id });
|
|
59
|
+
if (subscription === null)
|
|
60
|
+
return { status: 404, error: "no active subscription to cancel" };
|
|
61
|
+
return { status: 501, error: `entry scheme does not own subscription cancellation; subscription owned by scheme '${subscription.scheme}'` };
|
|
62
|
+
}
|
|
63
|
+
return { status: 501, error: `entry scheme does not interpret SEND status ${status}` }; // §send-dispatch-entry-schemes-501-on-non-410
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=_entry-send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_entry-send.js","sourceRoot":"","sources":["../../src/schemes/_entry-send.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosine.d.ts","sourceRoot":"","sources":["../../src/schemes/cosine.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,OAAO,CAAC;;0BAClB,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// SqlRite function module (#186, ~semantic). The sqlrite contract requires a
|
|
2
|
+
// default-export handler and turns the filename into the SQL function name — so
|
|
3
|
+
// this is a thin registration adapter; the logic lives in EntrySemantic.cosine
|
|
4
|
+
// (OO). `deterministic` marks it a pure function so SQLite may optimize it. One
|
|
5
|
+
// of the few intentionally non-class modules (sqlrite's function convention).
|
|
6
|
+
import EntrySemantic from "./_entry-semantic.js";
|
|
7
|
+
export const deterministic = true;
|
|
8
|
+
export default (a, b) => EntrySemantic.cosine(a, b);
|
|
9
|
+
//# sourceMappingURL=cosine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosine.js","sourceRoot":"","sources":["../../src/schemes/cosine.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,OAAO,aAAa,MAAM,sBAAsB,CAAC;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,eAAe,CAAC,CAAa,EAAE,CAAa,EAAU,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default class ExecAbort {
|
|
2
|
+
static get graceMs(): number;
|
|
3
|
+
static teardownReason(): {
|
|
4
|
+
housekeeping: true;
|
|
5
|
+
graceMs: number;
|
|
6
|
+
};
|
|
7
|
+
static killReason(signal: number | null): {
|
|
8
|
+
signal: number | null;
|
|
9
|
+
};
|
|
10
|
+
static timeoutReason(): {
|
|
11
|
+
housekeeping: true;
|
|
12
|
+
graceMs: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=exec-abort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-abort.d.ts","sourceRoot":"","sources":["../../src/schemes/exec-abort.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,SAAS;IAI1B,MAAM,KAAK,OAAO,IAAI,MAAM,CAE3B;IAGD,MAAM,CAAC,cAAc,IAAI;QAAE,YAAY,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAE/D;IAID,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAElE;IAKD,MAAM,CAAC,aAAa,IAAI;QAAE,YAAY,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAE9D;CACJ"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// The abort-reason protocol @plurnk/plurnk-execs' SubprocessExecutor reads off `signal.reason`:
|
|
2
|
+
// { signal } → deliver exactly that Unix signal, once, no escalation.
|
|
3
|
+
// { housekeeping: true, graceMs } → loop/run teardown: the polite signal, then SIGKILL after graceMs.
|
|
4
|
+
// A { signal: null } reason (a bare KILL) carries no override, so the executor applies its own
|
|
5
|
+
// polite default, SIGHUP — the gentlest rung; the model escalates with explicit codes.
|
|
6
|
+
export default class ExecAbort {
|
|
7
|
+
// The grace a teardown straggler gets before the hard SIGKILL. The executor refuses to bake a
|
|
8
|
+
// number (it'd be a magic literal there); the consumer owns it — env-tunable, 2s default. A
|
|
9
|
+
// getter, not a static field, so a test can set the env at runtime. §run-lifecycle-total-reap
|
|
10
|
+
static get graceMs() {
|
|
11
|
+
return Number(process.env.PLURNK_SERVICE_EXEC_KILL_GRACE_MS ?? "2000");
|
|
12
|
+
}
|
|
13
|
+
// Loop/run teardown — a BOUNDED reap, so Exec.idle() can't wedge on a signal-ignoring spawn.
|
|
14
|
+
static teardownReason() {
|
|
15
|
+
return { housekeeping: true, graceMs: ExecAbort.graceMs };
|
|
16
|
+
}
|
|
17
|
+
// The model's KILL[code] → exactly that signal, once (the model owns escalation: KILL[15] SIGTERM,
|
|
18
|
+
// KILL[9] SIGKILL). A bare KILL (null) carries no override — the executor's SIGHUP polite default.
|
|
19
|
+
static killReason(signal) {
|
|
20
|
+
return { signal };
|
|
21
|
+
}
|
|
22
|
+
// grammar 0.74.20 EXEC `<T>` timeout — the spawn outlived its T-second budget. A BOUNDED reap
|
|
23
|
+
// (polite signal then SIGKILL after graceMs), same protocol as teardown so a signal-ignoring
|
|
24
|
+
// spawn still dies; the caller stamps the distinct 504 close status (a timeout, not a plain kill).
|
|
25
|
+
static timeoutReason() {
|
|
26
|
+
return { housekeeping: true, graceMs: ExecAbort.graceMs };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=exec-abort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-abort.js","sourceRoot":"","sources":["../../src/schemes/exec-abort.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8FAA8F;AAC9F,yGAAyG;AACzG,+FAA+F;AAC/F,uFAAuF;AACvF,MAAM,CAAC,OAAO,OAAO,SAAS;IAC1B,8FAA8F;IAC9F,4FAA4F;IAC5F,8FAA8F;IAC9F,MAAM,KAAK,OAAO;QACd,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,MAAM,CAAC,CAAC;IAC3E,CAAC;IAED,6FAA6F;IAC7F,MAAM,CAAC,cAAc;QACjB,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;IAC9D,CAAC;IAED,mGAAmG;IACnG,mGAAmG;IACnG,MAAM,CAAC,UAAU,CAAC,MAAqB;QACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IACtB,CAAC;IAED,8FAA8F;IAC9F,6FAA6F;IAC7F,mGAAmG;IACnG,MAAM,CAAC,aAAa;QAChB,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;IAC9D,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-env.d.ts","sourceRoot":"","sources":["../../src/schemes/exec-env.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,OAAO,OAAO,OAAO;;IAYxB,MAAM,CAAC,MAAM,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,UAAU,CAOrE;CACJ"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// SPEC §exec {§exec-env-scoped} — the environment an EXEC subprocess receives.
|
|
2
|
+
//
|
|
3
|
+
// It gets the *project's* environment (its `.env`, the standard shell vars like PATH
|
|
4
|
+
// and HOME) so the model's commands run as the project expects — but never plurnk's
|
|
5
|
+
// own secrets: the `PLURNK_*` config (all of plurnk's knobs are prefixed; see
|
|
6
|
+
// .env.defaults) and the provider API keys plurnk-providers reads. The provider key-vars
|
|
7
|
+
// are sourced from STANDARD_PROVIDERS so the denylist tracks the provider set rather
|
|
8
|
+
// than a hand-maintained list that drifts as providers are added.
|
|
9
|
+
//
|
|
10
|
+
// A denylist, not an allowlist: a subprocess needs the long tail of inherited vars
|
|
11
|
+
// (PATH, HOME, LANG, the project's own keys); only plurnk's two owned families are
|
|
12
|
+
// stripped. The service owns this policy; the executor (plurnk-execs SubprocessExecutor,
|
|
13
|
+
// plurnk-execs#8) spawns with the env it is handed.
|
|
14
|
+
import { STANDARD_PROVIDERS } from "@plurnk/plurnk-providers";
|
|
15
|
+
export default class ExecEnv {
|
|
16
|
+
// apiKeyVar is optional (providers 0.9.0): an anonymous provider like `plurnk`
|
|
17
|
+
// has none. It loses no secret here — plurnk's PLURNK_API_KEY cred is
|
|
18
|
+
// already stripped by the PLURNK_ prefix rule below — so drop the empties.
|
|
19
|
+
static #providerKeys = new Set(Object.values(STANDARD_PROVIDERS)
|
|
20
|
+
.map((spec) => spec.apiKeyVar)
|
|
21
|
+
.filter((v) => v !== undefined));
|
|
22
|
+
// Read at call time (not memoized) so a secret set into process.env after boot is
|
|
23
|
+
// still scoped out of the next spawn.
|
|
24
|
+
static scoped(env = process.env) {
|
|
25
|
+
const out = {};
|
|
26
|
+
for (const [key, value] of Object.entries(env)) {
|
|
27
|
+
if (key.startsWith("PLURNK_") || ExecEnv.#providerKeys.has(key))
|
|
28
|
+
continue; // plurnk's own — never to a subprocess
|
|
29
|
+
out[key] = value;
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=exec-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-env.js","sourceRoot":"","sources":["../../src/schemes/exec-env.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,qFAAqF;AACrF,oFAAoF;AACpF,8EAA8E;AAC9E,yFAAyF;AACzF,qFAAqF;AACrF,kEAAkE;AAClE,EAAE;AACF,mFAAmF;AACnF,mFAAmF;AACnF,yFAAyF;AACzF,oDAAoD;AAEpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,CAAC,OAAO,OAAO,OAAO;IACxB,+EAA+E;IAC/E,sEAAsE;IACtE,2EAA2E;IAC3E,MAAM,CAAC,aAAa,GAAwB,IAAI,GAAG,CAC/C,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC;SAC5B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;SAC7B,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CACnD,CAAC;IAEF,kFAAkF;IAClF,sCAAsC;IACtC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;QAC9C,MAAM,GAAG,GAAsB,EAAE,CAAC;QAClC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7C,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS,CAAE,uCAAuC;YACnH,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACrB,CAAC;QACD,OAAO,GAAG,CAAC;IACf,CAAC;CACJ"}
|