@ponraaj/dimple-sdk 0.0.0-alpha.11 → 0.0.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dimple.d.ts +10 -0
- package/dist/errors.js +245 -75
- package/dist/index.js +390 -138
- package/dist/internal/config/index.d.ts +2 -2
- package/dist/internal/config/schema.d.ts +116 -21
- package/dist/internal/embedder/index.d.ts +1 -1
- package/dist/internal/embedder/transformers.d.ts +65 -17
- package/dist/internal/store/topics/index.d.ts +2 -2
- package/dist/internal/store/topics/lifecycle.d.ts +25 -0
- package/dist/internal/workflow/index.d.ts +1 -1
- package/dist/internal/workflow/queue.d.ts +21 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ import { Effect as Effect39, Layer as Layer15, Schedule as Schedule2, Schema as
|
|
|
33
33
|
|
|
34
34
|
// ../store/src/store.ts
|
|
35
35
|
import { Config as Config4, Effect as Effect25, Layer as Layer10, Schema as Schema23 } from "effect";
|
|
36
|
-
import { eq as eq8, and as and8, desc as desc2, asc as asc5, inArray as inArray4, ne as ne4, or, isNull as isNull2, like, sql as
|
|
36
|
+
import { eq as eq8, and as and8, desc as desc2, asc as asc5, inArray as inArray4, ne as ne4, or, isNull as isNull2, like, sql as sql8 } from "drizzle-orm";
|
|
37
37
|
|
|
38
38
|
// ../store/src/db-backend.ts
|
|
39
39
|
import { Context as Context2 } from "effect";
|
|
@@ -840,6 +840,43 @@ var IndexConfig = Schema8.Struct({
|
|
|
840
840
|
maxNeighbors: Schema8.optional(Schema8.Number),
|
|
841
841
|
searchL: Schema8.optional(Schema8.Number)
|
|
842
842
|
});
|
|
843
|
+
var ThreadCount = Schema8.Number.pipe(Schema8.refine((n) => Number.isInteger(n) && n >= 0 && n <= 1024, {
|
|
844
|
+
identifier: "ThreadCount"
|
|
845
|
+
}));
|
|
846
|
+
var SessionOptions = Schema8.Struct({
|
|
847
|
+
intraOpNumThreads: Schema8.optional(ThreadCount),
|
|
848
|
+
interOpNumThreads: Schema8.optional(ThreadCount),
|
|
849
|
+
executionMode: Schema8.optional(Schema8.Literals(["sequential", "parallel"])),
|
|
850
|
+
graphOptimizationLevel: Schema8.optional(Schema8.Literals(["disabled", "basic", "extended", "all", "layout"])),
|
|
851
|
+
enableCpuMemArena: Schema8.optional(Schema8.Boolean),
|
|
852
|
+
enableMemPattern: Schema8.optional(Schema8.Boolean),
|
|
853
|
+
gpuMemLimit: Schema8.optional(Schema8.Number),
|
|
854
|
+
arenaExtendStrategy: Schema8.optional(Schema8.Literals([0, 1]))
|
|
855
|
+
});
|
|
856
|
+
var mergeSessionOptions = (global, model) => {
|
|
857
|
+
const pick = (key) => model?.[key] ?? global?.[key];
|
|
858
|
+
const intraOpNumThreads = pick("intraOpNumThreads");
|
|
859
|
+
const interOpNumThreads = pick("interOpNumThreads");
|
|
860
|
+
const executionMode = pick("executionMode");
|
|
861
|
+
const graphOptimizationLevel = pick("graphOptimizationLevel");
|
|
862
|
+
const enableCpuMemArena = pick("enableCpuMemArena");
|
|
863
|
+
const enableMemPattern = pick("enableMemPattern");
|
|
864
|
+
const gpuMemLimit = pick("gpuMemLimit");
|
|
865
|
+
const arenaExtendStrategy = pick("arenaExtendStrategy");
|
|
866
|
+
const empty = intraOpNumThreads === undefined && interOpNumThreads === undefined && executionMode === undefined && graphOptimizationLevel === undefined && enableCpuMemArena === undefined && enableMemPattern === undefined && gpuMemLimit === undefined && arenaExtendStrategy === undefined;
|
|
867
|
+
if (empty)
|
|
868
|
+
return;
|
|
869
|
+
return {
|
|
870
|
+
...intraOpNumThreads !== undefined ? { intraOpNumThreads } : undefined,
|
|
871
|
+
...interOpNumThreads !== undefined ? { interOpNumThreads } : undefined,
|
|
872
|
+
...executionMode !== undefined ? { executionMode } : undefined,
|
|
873
|
+
...graphOptimizationLevel !== undefined ? { graphOptimizationLevel } : undefined,
|
|
874
|
+
...enableCpuMemArena !== undefined ? { enableCpuMemArena } : undefined,
|
|
875
|
+
...enableMemPattern !== undefined ? { enableMemPattern } : undefined,
|
|
876
|
+
...gpuMemLimit !== undefined ? { gpuMemLimit } : undefined,
|
|
877
|
+
...arenaExtendStrategy !== undefined ? { arenaExtendStrategy } : undefined
|
|
878
|
+
};
|
|
879
|
+
};
|
|
843
880
|
var EmbeddingModelConfig = Schema8.Struct({
|
|
844
881
|
id: Schema8.String,
|
|
845
882
|
provider: Schema8.String,
|
|
@@ -877,14 +914,13 @@ var EmbeddingModelConfig = Schema8.Struct({
|
|
|
877
914
|
pooling: Schema8.optional(Schema8.Literals(["mean", "cls", "none"])),
|
|
878
915
|
normalize: Schema8.optional(Schema8.Boolean),
|
|
879
916
|
cacheDir: Schema8.optional(Schema8.String),
|
|
880
|
-
sessionOptions: Schema8.optional(
|
|
881
|
-
|
|
882
|
-
arenaExtendStrategy: Schema8.optional(Schema8.Literals([0, 1]))
|
|
883
|
-
})),
|
|
917
|
+
sessionOptions: Schema8.optional(SessionOptions),
|
|
918
|
+
wasm: Schema8.optional(Schema8.Struct({ numThreads: Schema8.optional(ThreadCount) })),
|
|
884
919
|
autoInstall: Schema8.optional(Schema8.Boolean)
|
|
885
920
|
});
|
|
886
921
|
var EmbeddingConfig = Schema8.Struct({
|
|
887
922
|
defaultModel: Schema8.String,
|
|
923
|
+
sessionOptions: Schema8.optional(SessionOptions),
|
|
888
924
|
models: Schema8.Array(EmbeddingModelConfig)
|
|
889
925
|
});
|
|
890
926
|
var MaxAttempts = Schema8.Number.pipe(Schema8.refine((n) => Number.isInteger(n) && n > 0 && n <= 100, {
|
|
@@ -2736,8 +2772,8 @@ var resolveTopics = Effect11.fn("topics.resolveTopics")(function* (queryVector,
|
|
|
2736
2772
|
});
|
|
2737
2773
|
|
|
2738
2774
|
// ../store/src/topics/lifecycle.ts
|
|
2739
|
-
import { Clock as Clock3, Effect as Effect20 } from "effect";
|
|
2740
|
-
import { and as and3, eq as eq3, inArray, ne } from "drizzle-orm";
|
|
2775
|
+
import { Clock as Clock3, Cause as Cause3, Effect as Effect20, Exit as Exit6 } from "effect";
|
|
2776
|
+
import { and as and3, eq as eq3, inArray, ne, sql as sql3 } from "drizzle-orm";
|
|
2741
2777
|
|
|
2742
2778
|
// ../workflow/src/queue.ts
|
|
2743
2779
|
import { Effect as Effect12, Schema as Schema13 } from "effect";
|
|
@@ -2820,6 +2856,16 @@ var MemoryEmbed = JobDefinition.make("memory.embed", {
|
|
|
2820
2856
|
error: Schema13.String,
|
|
2821
2857
|
idempotencyKey: (p) => `embed:${p.memoryId}:${p.modelKey}`
|
|
2822
2858
|
});
|
|
2859
|
+
var MemoryEmbedBatch = JobDefinition.make("memory.embed.batch", {
|
|
2860
|
+
payload: {
|
|
2861
|
+
memoryIds: Schema13.Array(Schema13.String),
|
|
2862
|
+
modelKey: Schema13.String,
|
|
2863
|
+
nonce: Schema13.String
|
|
2864
|
+
},
|
|
2865
|
+
success: Schema13.Void,
|
|
2866
|
+
error: Schema13.String,
|
|
2867
|
+
idempotencyKey: (p) => `embed-batch:${p.modelKey}:${p.nonce}`
|
|
2868
|
+
});
|
|
2823
2869
|
var TopicMerge = JobDefinition.make("topic.merge", {
|
|
2824
2870
|
payload: { topicId: Schema13.String, modelKey: Schema13.String },
|
|
2825
2871
|
success: Schema13.Void,
|
|
@@ -2877,6 +2923,7 @@ var AuditWrite = JobDefinition.make("audit.write", {
|
|
|
2877
2923
|
var queues = [
|
|
2878
2924
|
TopicSplit,
|
|
2879
2925
|
MemoryEmbed,
|
|
2926
|
+
MemoryEmbedBatch,
|
|
2880
2927
|
TopicMerge,
|
|
2881
2928
|
TopicRebalance,
|
|
2882
2929
|
ConceptCluster,
|
|
@@ -3703,46 +3750,136 @@ var setActiveModel = Effect20.fn("topics.setActiveModel")(function* (model, conf
|
|
|
3703
3750
|
}).pipe(routingFailure3("topics.setActiveModel.deactivate"));
|
|
3704
3751
|
return { routed, alreadyInTree, deactivated };
|
|
3705
3752
|
});
|
|
3753
|
+
var embedOneMemory = (deps, payload, ctx) => Effect20.gen(function* () {
|
|
3754
|
+
const envelope = payload;
|
|
3755
|
+
const model = deps.getModelConfig(envelope.modelKey);
|
|
3756
|
+
if (!model) {
|
|
3757
|
+
return yield* Effect20.fail(new JobFailure({
|
|
3758
|
+
jobId: ctx.jobId,
|
|
3759
|
+
message: `memory.embed: unknown model "${envelope.modelKey}"`
|
|
3760
|
+
}));
|
|
3761
|
+
}
|
|
3762
|
+
const content = yield* deps.getMemoryContent(envelope.memoryId).pipe(Effect20.catchTag("Store.NotFound", () => Effect20.succeed(undefined)), Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: load content: ${e}` })));
|
|
3763
|
+
if (content === undefined) {
|
|
3764
|
+
yield* Effect20.logDebug("embed.stale-reoffer").pipe(Effect20.annotateLogs({
|
|
3765
|
+
scope: "@dimple/store",
|
|
3766
|
+
event: "embed.stale-reoffer",
|
|
3767
|
+
memoryId: envelope.memoryId,
|
|
3768
|
+
modelKey: envelope.modelKey
|
|
3769
|
+
}));
|
|
3770
|
+
return;
|
|
3771
|
+
}
|
|
3772
|
+
const vector = yield* deps.embedOne(content, model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: embed: ${e}` })));
|
|
3773
|
+
const backend = yield* Service2;
|
|
3774
|
+
const db = backend.db;
|
|
3775
|
+
const existing = yield* Effect20.tryPromise({
|
|
3776
|
+
try: () => db.select({ memoryId: topicMemberships.memoryId }).from(topicMemberships).where(and3(eq3(topicMemberships.memoryId, envelope.memoryId), eq3(topicMemberships.modelKey, model.id))),
|
|
3777
|
+
catch: (cause) => new StoreError({ message: `memory.embed: membership check: ${cause}` })
|
|
3778
|
+
}).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: membership check: ${e}` })));
|
|
3779
|
+
yield* ensureTopicTree(model, deps.config).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: seed tree: ${e}` })));
|
|
3780
|
+
yield* backend.ensureVectorTable(model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: vector table: ${e}` })));
|
|
3781
|
+
yield* backend.insertVector(envelope.memoryId, [...vector], model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: insert vector: ${e}` })));
|
|
3782
|
+
yield* Effect20.tryPromise({
|
|
3783
|
+
try: () => db.update(memories).set({ embedding: [...vector], embeddingModel: model.id }).where(eq3(memories.id, envelope.memoryId)),
|
|
3784
|
+
catch: (cause) => new StoreError({ message: `memory.embed: stamp embedding: ${cause}` })
|
|
3785
|
+
}).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: stamp embedding: ${e}` })));
|
|
3786
|
+
if (existing.length === 0) {
|
|
3787
|
+
yield* routeInsert(envelope.memoryId, [...vector], model, deps.config).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: route: ${e}` })));
|
|
3788
|
+
}
|
|
3789
|
+
yield* Effect20.logInfo("embed.completed").pipe(Effect20.annotateLogs({
|
|
3790
|
+
scope: "@dimple/store",
|
|
3791
|
+
event: "embed.completed",
|
|
3792
|
+
memoryId: envelope.memoryId,
|
|
3793
|
+
modelKey: envelope.modelKey,
|
|
3794
|
+
reroute: existing.length === 0
|
|
3795
|
+
}));
|
|
3796
|
+
return;
|
|
3797
|
+
});
|
|
3706
3798
|
function memoryEmbedHandler(deps) {
|
|
3799
|
+
const run = (payload, ctx) => embedOneMemory(deps, payload, ctx);
|
|
3800
|
+
return deps.backend ? (payload, ctx) => run(payload, ctx).pipe(Effect20.provideService(Service2, deps.backend)) : run;
|
|
3801
|
+
}
|
|
3802
|
+
var logBatchCompleted = (modelKey, embedded, failed, ctx) => Effect20.logInfo("embed.batch.completed").pipe(Effect20.annotateLogs({
|
|
3803
|
+
scope: "@dimple/store",
|
|
3804
|
+
event: "embed.batch.completed",
|
|
3805
|
+
jobId: ctx.jobId,
|
|
3806
|
+
modelKey,
|
|
3807
|
+
embedded,
|
|
3808
|
+
failed
|
|
3809
|
+
}));
|
|
3810
|
+
var batchFailure = (ctx, failed, total, first) => Effect20.fail(new JobFailure({
|
|
3811
|
+
jobId: ctx.jobId,
|
|
3812
|
+
message: `memory.embed.batch: ${failed}/${total} failed — ${first}`
|
|
3813
|
+
}));
|
|
3814
|
+
function memoryEmbedBatchHandler(deps) {
|
|
3707
3815
|
const run = (payload, ctx) => Effect20.gen(function* () {
|
|
3708
|
-
const
|
|
3709
|
-
const model = deps.getModelConfig(envelope.modelKey);
|
|
3816
|
+
const model = deps.getModelConfig(payload.modelKey);
|
|
3710
3817
|
if (!model) {
|
|
3711
3818
|
return yield* Effect20.fail(new JobFailure({
|
|
3712
3819
|
jobId: ctx.jobId,
|
|
3713
|
-
message: `memory.embed: unknown model "${
|
|
3820
|
+
message: `memory.embed: unknown model "${payload.modelKey}"`
|
|
3714
3821
|
}));
|
|
3715
3822
|
}
|
|
3716
|
-
const
|
|
3717
|
-
|
|
3823
|
+
const backend = yield* Service2;
|
|
3824
|
+
const db = backend.db;
|
|
3825
|
+
let failed = 0;
|
|
3826
|
+
let first;
|
|
3827
|
+
const embedded = [];
|
|
3828
|
+
const stale = [];
|
|
3829
|
+
yield* Effect20.forEach(payload.memoryIds, (memoryId) => Effect20.gen(function* () {
|
|
3830
|
+
const content = yield* deps.getMemoryContent(memoryId).pipe(Effect20.catchTag("Store.NotFound", () => Effect20.succeed(undefined)), Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: load content: ${e}` })));
|
|
3831
|
+
if (content === undefined) {
|
|
3832
|
+
stale.push(memoryId);
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
const vector = yield* deps.embedOne(content, model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: embed: ${e}` })));
|
|
3836
|
+
embedded.push({ memoryId, vector });
|
|
3837
|
+
}).pipe(Effect20.exit, Effect20.tap((exit) => {
|
|
3838
|
+
if (Exit6.isSuccess(exit))
|
|
3839
|
+
return Effect20.void;
|
|
3840
|
+
failed += 1;
|
|
3841
|
+
first ??= Cause3.pretty(exit.cause);
|
|
3842
|
+
return Effect20.void;
|
|
3843
|
+
})), { concurrency: 1, discard: true });
|
|
3844
|
+
for (const memoryId of stale) {
|
|
3718
3845
|
yield* Effect20.logDebug("embed.stale-reoffer").pipe(Effect20.annotateLogs({
|
|
3719
3846
|
scope: "@dimple/store",
|
|
3720
3847
|
event: "embed.stale-reoffer",
|
|
3721
|
-
memoryId
|
|
3722
|
-
modelKey:
|
|
3848
|
+
memoryId,
|
|
3849
|
+
modelKey: payload.modelKey
|
|
3723
3850
|
}));
|
|
3851
|
+
}
|
|
3852
|
+
if (embedded.length === 0) {
|
|
3853
|
+
yield* logBatchCompleted(payload.modelKey, 0, failed, ctx);
|
|
3854
|
+
if (failed > 0) {
|
|
3855
|
+
return yield* batchFailure(ctx, failed, payload.memoryIds.length, first);
|
|
3856
|
+
}
|
|
3724
3857
|
return;
|
|
3725
3858
|
}
|
|
3726
|
-
const vector = yield* deps.embedOne(content, model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: embed: ${e}` })));
|
|
3727
|
-
const backend = yield* Service2;
|
|
3728
|
-
const db = backend.db;
|
|
3729
|
-
const existing = yield* Effect20.tryPromise({
|
|
3730
|
-
try: () => db.select({ memoryId: topicMemberships.memoryId }).from(topicMemberships).where(and3(eq3(topicMemberships.memoryId, envelope.memoryId), eq3(topicMemberships.modelKey, model.id))),
|
|
3731
|
-
catch: (cause) => new StoreError({ message: `memory.embed: membership check: ${cause}` })
|
|
3732
|
-
}).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: membership check: ${e}` })));
|
|
3733
3859
|
yield* ensureTopicTree(model, deps.config).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: seed tree: ${e}` })));
|
|
3734
3860
|
yield* backend.ensureVectorTable(model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: vector table: ${e}` })));
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3861
|
+
const ids = embedded.map((e) => e.memoryId);
|
|
3862
|
+
const members = yield* Effect20.tryPromise({
|
|
3863
|
+
try: () => db.select({ memoryId: topicMemberships.memoryId }).from(topicMemberships).where(and3(eq3(topicMemberships.modelKey, model.id), inArray(topicMemberships.memoryId, ids))),
|
|
3864
|
+
catch: (cause) => new StoreError({ message: `memory.embed: membership check: ${cause}` })
|
|
3865
|
+
}).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: membership check: ${e}` })));
|
|
3866
|
+
const memberSet = new Set(members.map((r) => r.memoryId));
|
|
3867
|
+
const entries = embedded.map((e) => ({ memoryId: e.memoryId, vector: [...e.vector] }));
|
|
3868
|
+
yield* backend.insertVectors(entries, model).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: insert vectors: ${e}` })));
|
|
3869
|
+
yield* Effect20.tryPromise({
|
|
3870
|
+
try: () => db.transaction(async (tx) => {
|
|
3871
|
+
await tx.run(sql3`UPDATE ${memories} SET embedding = CASE id ${sql3.join(entries.map((entry) => sql3`WHEN ${entry.memoryId} THEN ${new Float32Array(entry.vector).buffer}`), sql3` `)} END, embedding_model = ${model.id} WHERE id IN (${sql3.join(entries.map((entry) => sql3`${entry.memoryId}`), sql3`, `)})`);
|
|
3872
|
+
}),
|
|
3873
|
+
catch: (cause) => new StoreError({ message: `memory.embed: stamp embeddings: ${cause}` })
|
|
3874
|
+
}).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: stamp embeddings: ${e}` })));
|
|
3875
|
+
const fresh = entries.filter((entry) => !memberSet.has(entry.memoryId));
|
|
3876
|
+
if (fresh.length > 0) {
|
|
3877
|
+
yield* routeInsertMany(fresh, model, deps.config).pipe(Effect20.mapError((e) => new JobFailure({ jobId: ctx.jobId, message: `memory.embed: route: ${e}` })));
|
|
3878
|
+
}
|
|
3879
|
+
yield* logBatchCompleted(payload.modelKey, embedded.length, failed, ctx);
|
|
3880
|
+
if (failed > 0) {
|
|
3881
|
+
return yield* batchFailure(ctx, failed, payload.memoryIds.length, first);
|
|
3738
3882
|
}
|
|
3739
|
-
yield* Effect20.logInfo("embed.completed").pipe(Effect20.annotateLogs({
|
|
3740
|
-
scope: "@dimple/store",
|
|
3741
|
-
event: "embed.completed",
|
|
3742
|
-
memoryId: envelope.memoryId,
|
|
3743
|
-
modelKey: envelope.modelKey,
|
|
3744
|
-
reroute: existing.length === 0
|
|
3745
|
-
}));
|
|
3746
3883
|
return;
|
|
3747
3884
|
});
|
|
3748
3885
|
return deps.backend ? (payload, ctx) => run(payload, ctx).pipe(Effect20.provideService(Service2, deps.backend)) : run;
|
|
@@ -3750,19 +3887,19 @@ function memoryEmbedHandler(deps) {
|
|
|
3750
3887
|
|
|
3751
3888
|
// ../store/src/topics/jobs.ts
|
|
3752
3889
|
import { Clock as Clock4, Effect as Effect21 } from "effect";
|
|
3753
|
-
import { and as and4, asc as asc3, eq as eq4, inArray as inArray2, sql as
|
|
3890
|
+
import { and as and4, asc as asc3, eq as eq4, inArray as inArray2, sql as sql5 } from "drizzle-orm";
|
|
3754
3891
|
|
|
3755
3892
|
// ../store/src/topics/topic-vectors.ts
|
|
3756
|
-
import { sql as
|
|
3893
|
+
import { sql as sql4 } from "drizzle-orm";
|
|
3757
3894
|
var topicVectorTableName2 = (model) => `topic_vec_${model.dimensions}_${model.id.replace(/[^a-zA-Z0-9_]/g, "_")}`;
|
|
3758
3895
|
var deleteTopicVectorRow = async (runner, model, topicKey) => {
|
|
3759
3896
|
const table = topicVectorTableName2(model);
|
|
3760
|
-
await runner.run(
|
|
3897
|
+
await runner.run(sql4`DELETE FROM ${sql4.raw(table)} WHERE topic_key = ${topicKey}`);
|
|
3761
3898
|
};
|
|
3762
3899
|
var writeTopicVector = async (runner, model, topicKey, ls) => {
|
|
3763
3900
|
const table = topicVectorTableName2(model);
|
|
3764
|
-
await runner.run(
|
|
3765
|
-
INSERT OR REPLACE INTO ${
|
|
3901
|
+
await runner.run(sql4`
|
|
3902
|
+
INSERT OR REPLACE INTO ${sql4.raw(table)} (topic_key, sum_vector, model_key)
|
|
3766
3903
|
VALUES (${topicKey}, vector32(${JSON.stringify([...ls])}), ${model.id})
|
|
3767
3904
|
`);
|
|
3768
3905
|
};
|
|
@@ -3853,7 +3990,7 @@ var splitTopic = Effect21.fn("TopicSplit.splitTopic")(function* (topicKey, model
|
|
|
3853
3990
|
}).onConflictDoUpdate({
|
|
3854
3991
|
target: [topicGrowthState.topicKey, topicGrowthState.modelKey],
|
|
3855
3992
|
set: {
|
|
3856
|
-
splitRejectedCount:
|
|
3993
|
+
splitRejectedCount: sql5`${topicGrowthState.splitRejectedCount} + 1`,
|
|
3857
3994
|
splitDeferred: 1
|
|
3858
3995
|
}
|
|
3859
3996
|
});
|
|
@@ -4543,7 +4680,7 @@ var staleNoOp = (notFound, model) => Effect22.gen(function* () {
|
|
|
4543
4680
|
|
|
4544
4681
|
// ../store/src/topics/observability.ts
|
|
4545
4682
|
import { Effect as Effect23 } from "effect";
|
|
4546
|
-
import { and as and6, desc, eq as eq6, inArray as inArray3, ne as ne3, sql as
|
|
4683
|
+
import { and as and6, desc, eq as eq6, inArray as inArray3, ne as ne3, sql as sql6 } from "drizzle-orm";
|
|
4547
4684
|
var DEFAULT_MAX_LEAF_ITEMS3 = 128;
|
|
4548
4685
|
var DEFAULT_SPLIT_DEFERRED_HARD_LIMIT2 = 512;
|
|
4549
4686
|
var DEFAULT_CHANGE_LOG_LIMIT = 50;
|
|
@@ -4587,7 +4724,7 @@ var topicMetrics = Effect23.fn("topics.topicMetrics")(function* (modelKey, confi
|
|
|
4587
4724
|
}
|
|
4588
4725
|
leafMemberCounts.sort((a, b) => a - b);
|
|
4589
4726
|
const growth = yield* Effect23.tryPromise({
|
|
4590
|
-
try: () => db.select({ total:
|
|
4727
|
+
try: () => db.select({ total: sql6`coalesce(sum(${topicGrowthState.splitRejectedCount}), 0)` }).from(topicGrowthState).where(eq6(topicGrowthState.modelKey, modelKey)),
|
|
4591
4728
|
catch: (cause) => cause
|
|
4592
4729
|
}).pipe(routingFailure4("topics.topicMetrics.growth"));
|
|
4593
4730
|
const splitRejectedTotal = Number(growth[0]?.total ?? 0);
|
|
@@ -4643,7 +4780,7 @@ var topicHealth = Effect23.fn("topics.topicHealth")(function* (modelKey, config)
|
|
|
4643
4780
|
catch: (cause) => cause
|
|
4644
4781
|
}).pipe(routingFailure4("topics.topicHealth.topics"));
|
|
4645
4782
|
const countRows = yield* Effect23.tryPromise({
|
|
4646
|
-
try: () => db.select({ topicKey: topicMemberships.topicKey, count:
|
|
4783
|
+
try: () => db.select({ topicKey: topicMemberships.topicKey, count: sql6`count(*)` }).from(topicMemberships).where(eq6(topicMemberships.modelKey, modelKey)).groupBy(topicMemberships.topicKey),
|
|
4647
4784
|
catch: (cause) => cause
|
|
4648
4785
|
}).pipe(routingFailure4("topics.topicHealth.memberships"));
|
|
4649
4786
|
const membershipCount = new Map(countRows.map((r) => [r.topicKey, Number(r.count)]));
|
|
@@ -4668,7 +4805,7 @@ var topicHealth = Effect23.fn("topics.topicHealth")(function* (modelKey, config)
|
|
|
4668
4805
|
|
|
4669
4806
|
// ../store/src/graph/observability.ts
|
|
4670
4807
|
import { Effect as Effect24 } from "effect";
|
|
4671
|
-
import { and as and7, eq as eq7, isNull, sql as
|
|
4808
|
+
import { and as and7, eq as eq7, isNull, sql as sql7 } from "drizzle-orm";
|
|
4672
4809
|
var graphCoverage = Effect24.fn("GraphCoverage.run")(function* (modelKey) {
|
|
4673
4810
|
const backend = yield* Service2;
|
|
4674
4811
|
const db = backend.db;
|
|
@@ -4682,7 +4819,7 @@ var graphCoverage = Effect24.fn("GraphCoverage.run")(function* (modelKey) {
|
|
|
4682
4819
|
const coveredMemories = totalMemories - isolatedMemories;
|
|
4683
4820
|
const coveragePercent = totalMemories === 0 ? 0 : Math.round(coveredMemories / totalMemories * 1000) / 10;
|
|
4684
4821
|
const pendingRows = yield* Effect24.tryPromise({
|
|
4685
|
-
try: () => db.select({ count:
|
|
4822
|
+
try: () => db.select({ count: sql7`count(*)` }).from(artifactEdges).where(and7(eq7(artifactEdges.status, "pending"), isNull(artifactEdges.expiredAt))),
|
|
4686
4823
|
catch: (cause) => new StoreError({ message: `graphCoverage: pending: ${cause}` })
|
|
4687
4824
|
});
|
|
4688
4825
|
const pendingCandidates = totalMemories === 0 ? 0 : Number(pendingRows[0]?.count ?? 0);
|
|
@@ -5303,7 +5440,7 @@ var makeStore = (backend, modelConfig, topicsOptions, graphConfig, auditOptions,
|
|
|
5303
5440
|
const relRows = await tx.select({ parentKey: topicRelations.parentKey }).from(topicRelations).where(and8(eq8(topicRelations.childKey, membership.topicKey), eq8(topicRelations.modelKey, membership.modelKey), eq8(topicRelations.relationKind, "parent_child")));
|
|
5304
5441
|
let ancestorKey = relRows[0]?.parentKey;
|
|
5305
5442
|
while (ancestorKey) {
|
|
5306
|
-
await tx.update(topics).set({ memberCount:
|
|
5443
|
+
await tx.update(topics).set({ memberCount: sql8`max(0, ${topics.memberCount} - 1)`, updatedAt: Date.now() }).where(and8(eq8(topics.topicKey, ancestorKey), eq8(topics.modelKey, membership.modelKey)));
|
|
5307
5444
|
const up = await tx.select({ parentKey: topicRelations.parentKey }).from(topicRelations).where(and8(eq8(topicRelations.childKey, ancestorKey), eq8(topicRelations.modelKey, membership.modelKey), eq8(topicRelations.relationKind, "parent_child")));
|
|
5308
5445
|
ancestorKey = up[0]?.parentKey;
|
|
5309
5446
|
}
|
|
@@ -5597,7 +5734,7 @@ var makeStore = (backend, modelConfig, topicsOptions, graphConfig, auditOptions,
|
|
|
5597
5734
|
const now = Date.now();
|
|
5598
5735
|
yield* Effect25.tryPromise({
|
|
5599
5736
|
try: () => db.transaction(async (tx) => {
|
|
5600
|
-
await tx.run(
|
|
5737
|
+
await tx.run(sql8`UPDATE ${memories2} SET embedding = CASE id ${sql8.join(entries.map((entry) => sql8`WHEN ${entry.id} THEN ${new Float32Array(entry.embedding).buffer}`), sql8` `)} END, embedding_model = ${modelName} WHERE id IN (${sql8.join(entries.map((entry) => entry.id), sql8`, `)})`);
|
|
5601
5738
|
await tx.insert(memoryEvents2).values(entries.map((entry) => ({
|
|
5602
5739
|
memoryId: entry.id,
|
|
5603
5740
|
eventType: "embedding_updated",
|
|
@@ -5646,7 +5783,7 @@ var makeStore = (backend, modelConfig, topicsOptions, graphConfig, auditOptions,
|
|
|
5646
5783
|
});
|
|
5647
5784
|
const findStale = Effect25.fn("Store.findStale")(function* (model) {
|
|
5648
5785
|
const rows = yield* Effect25.tryPromise({
|
|
5649
|
-
try: () => db.select({ id: memories2.id }).from(memories2).where(and8(eq8(memories2.state, "active"),
|
|
5786
|
+
try: () => db.select({ id: memories2.id }).from(memories2).where(and8(eq8(memories2.state, "active"), sql8`(embedding IS NULL OR embedding_model IS NULL OR embedding_model != ${model})`)),
|
|
5650
5787
|
catch: storeError("Store.findStale")
|
|
5651
5788
|
});
|
|
5652
5789
|
return rows.map((row) => row.id);
|
|
@@ -6284,6 +6421,7 @@ __export(exports_topics, {
|
|
|
6284
6421
|
radiusOf: () => radiusOf,
|
|
6285
6422
|
mergeOrBorrow: () => mergeOrBorrow,
|
|
6286
6423
|
memoryEmbedHandler: () => memoryEmbedHandler,
|
|
6424
|
+
memoryEmbedBatchHandler: () => memoryEmbedBatchHandler,
|
|
6287
6425
|
lloydRefine: () => lloydRefine,
|
|
6288
6426
|
isActive: () => isActive,
|
|
6289
6427
|
farthestPair: () => farthestPair,
|
|
@@ -6358,7 +6496,7 @@ __export(exports_graph, {
|
|
|
6358
6496
|
|
|
6359
6497
|
// ../store/src/graph/concepts.ts
|
|
6360
6498
|
import { Clock as Clock6, Effect as Effect27 } from "effect";
|
|
6361
|
-
import { and as and9, asc as asc6, eq as eq9, isNotNull, sql as
|
|
6499
|
+
import { and as and9, asc as asc6, eq as eq9, isNotNull, sql as sql9 } from "drizzle-orm";
|
|
6362
6500
|
var DEFAULT_CLUSTER_K = 8;
|
|
6363
6501
|
var DEFAULT_CLUSTER_MIN_SIZE = 3;
|
|
6364
6502
|
var DEFAULT_CLUSTER_PASSES = 2;
|
|
@@ -6551,7 +6689,7 @@ var persistClusters = (db, members, config, now) => Effect27.tryPromise({
|
|
|
6551
6689
|
}).onConflictDoUpdate({
|
|
6552
6690
|
target: concepts.id,
|
|
6553
6691
|
set: {
|
|
6554
|
-
occurrenceCount:
|
|
6692
|
+
occurrenceCount: sql9`${concepts.occurrenceCount} + 1`,
|
|
6555
6693
|
lastSeen: now
|
|
6556
6694
|
}
|
|
6557
6695
|
});
|
|
@@ -6565,7 +6703,7 @@ var persistClusters = (db, members, config, now) => Effect27.tryPromise({
|
|
|
6565
6703
|
};
|
|
6566
6704
|
})).onConflictDoUpdate({
|
|
6567
6705
|
target: [memoryConcepts.conceptId, memoryConcepts.memoryId],
|
|
6568
|
-
set: { confidence:
|
|
6706
|
+
set: { confidence: sql9`excluded.confidence`, assignedAt: now }
|
|
6569
6707
|
});
|
|
6570
6708
|
conceptCount++;
|
|
6571
6709
|
annotated += memberIndices.length;
|
|
@@ -6601,7 +6739,7 @@ function conceptClusterHandler(deps) {
|
|
|
6601
6739
|
}
|
|
6602
6740
|
// ../store/src/graph/dream.ts
|
|
6603
6741
|
import { Clock as Clock7, Effect as Effect28 } from "effect";
|
|
6604
|
-
import { and as and10, asc as asc7, eq as eq10, gt, inArray as inArray5, isNull as isNull3, sql as
|
|
6742
|
+
import { and as and10, asc as asc7, eq as eq10, gt, inArray as inArray5, isNull as isNull3, sql as sql10 } from "drizzle-orm";
|
|
6605
6743
|
var dreamStateDefaults = {
|
|
6606
6744
|
minHours: 24,
|
|
6607
6745
|
minNewMemories: 20,
|
|
@@ -6732,7 +6870,7 @@ var runDream = Effect28.fn("MemoryDream.run")(function* (model, classify) {
|
|
|
6732
6870
|
};
|
|
6733
6871
|
}
|
|
6734
6872
|
const sinceCountRows = yield* Effect28.tryPromise({
|
|
6735
|
-
try: () => db.select({ count:
|
|
6873
|
+
try: () => db.select({ count: sql10`count(*)` }).from(memories).where(gt(memories.createdAt, lastDreamAt)),
|
|
6736
6874
|
catch: (cause) => new StoreError({ message: `memory.dream: count new: ${cause}` })
|
|
6737
6875
|
});
|
|
6738
6876
|
const memoriesSinceWatermark = Number(sinceCountRows[0]?.count ?? 0);
|
|
@@ -6911,7 +7049,7 @@ var runDream = Effect28.fn("MemoryDream.run")(function* (model, classify) {
|
|
|
6911
7049
|
if (outcome.inserted)
|
|
6912
7050
|
created++;
|
|
6913
7051
|
}
|
|
6914
|
-
const countRows = await tx.select({ count:
|
|
7052
|
+
const countRows = await tx.select({ count: sql10`count(*)` }).from(memories);
|
|
6915
7053
|
const totalMemories = Number(countRows[0]?.count ?? 0);
|
|
6916
7054
|
await tx.insert(dreamState).values({
|
|
6917
7055
|
modelKey: model.id,
|
|
@@ -6950,7 +7088,7 @@ function graphDreamHandler(deps) {
|
|
|
6950
7088
|
}
|
|
6951
7089
|
// ../store/src/graph/repair.ts
|
|
6952
7090
|
import { Clock as Clock8, Effect as Effect29 } from "effect";
|
|
6953
|
-
import { and as and11, eq as eq11, isNotNull as isNotNull2, lt, or as or2, sql as
|
|
7091
|
+
import { and as and11, eq as eq11, isNotNull as isNotNull2, lt, or as or2, sql as sql11 } from "drizzle-orm";
|
|
6954
7092
|
var DEFAULT_EXPIRED_GRACE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
6955
7093
|
var runRepair = (db, includePurgeExpired, expiredGraceMs, now) => Effect29.tryPromise({
|
|
6956
7094
|
try: () => db.transaction(async (tx) => {
|
|
@@ -6962,15 +7100,15 @@ var runRepair = (db, includePurgeExpired, expiredGraceMs, now) => Effect29.tryPr
|
|
|
6962
7100
|
edgeKind: artifactEdges.edgeKind,
|
|
6963
7101
|
fromMemoryId: artifactEdges.fromMemoryId,
|
|
6964
7102
|
toMemoryId: artifactEdges.toMemoryId,
|
|
6965
|
-
fromMissing:
|
|
7103
|
+
fromMissing: sql11`NOT EXISTS (
|
|
6966
7104
|
SELECT 1 FROM memories WHERE memories.id = ${artifactEdges.fromMemoryId}
|
|
6967
7105
|
)`,
|
|
6968
|
-
toMissing:
|
|
7106
|
+
toMissing: sql11`NOT EXISTS (
|
|
6969
7107
|
SELECT 1 FROM memories WHERE memories.id = ${artifactEdges.toMemoryId}
|
|
6970
7108
|
)`
|
|
6971
|
-
}).from(artifactEdges).where(or2(
|
|
7109
|
+
}).from(artifactEdges).where(or2(sql11`NOT EXISTS (
|
|
6972
7110
|
SELECT 1 FROM memories WHERE memories.id = ${artifactEdges.fromMemoryId}
|
|
6973
|
-
)`,
|
|
7111
|
+
)`, sql11`NOT EXISTS (
|
|
6974
7112
|
SELECT 1 FROM memories WHERE memories.id = ${artifactEdges.toMemoryId}
|
|
6975
7113
|
)`));
|
|
6976
7114
|
for (const row of orphanRows) {
|
|
@@ -6993,12 +7131,12 @@ var runRepair = (db, includePurgeExpired, expiredGraceMs, now) => Effect29.tryPr
|
|
|
6993
7131
|
const staleRows = await tx.select({
|
|
6994
7132
|
conceptId: memoryConcepts.conceptId,
|
|
6995
7133
|
memoryId: memoryConcepts.memoryId,
|
|
6996
|
-
memoryMissing:
|
|
7134
|
+
memoryMissing: sql11`NOT EXISTS (
|
|
6997
7135
|
SELECT 1 FROM memories WHERE memories.id = ${memoryConcepts.memoryId}
|
|
6998
7136
|
)`
|
|
6999
|
-
}).from(memoryConcepts).where(or2(
|
|
7137
|
+
}).from(memoryConcepts).where(or2(sql11`NOT EXISTS (
|
|
7000
7138
|
SELECT 1 FROM concepts WHERE concepts.id = ${memoryConcepts.conceptId}
|
|
7001
|
-
)`,
|
|
7139
|
+
)`, sql11`NOT EXISTS (
|
|
7002
7140
|
SELECT 1 FROM memories WHERE memories.id = ${memoryConcepts.memoryId}
|
|
7003
7141
|
)`));
|
|
7004
7142
|
for (const row of staleRows) {
|
|
@@ -7321,16 +7459,32 @@ var importFromDisk = () => new Promise((resolve, reject) => {
|
|
|
7321
7459
|
reject(cause);
|
|
7322
7460
|
}
|
|
7323
7461
|
});
|
|
7324
|
-
var buildSessionOptions = (opts) =>
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
}
|
|
7332
|
-
|
|
7333
|
-
|
|
7462
|
+
var buildSessionOptions = (opts) => {
|
|
7463
|
+
const cuda = opts.gpuMemLimit !== undefined || opts.arenaExtendStrategy !== undefined;
|
|
7464
|
+
return {
|
|
7465
|
+
enableCpuMemArena: opts.enableCpuMemArena ?? false,
|
|
7466
|
+
...opts.intraOpNumThreads !== undefined ? { intraOpNumThreads: opts.intraOpNumThreads } : undefined,
|
|
7467
|
+
...opts.interOpNumThreads !== undefined ? { interOpNumThreads: opts.interOpNumThreads } : undefined,
|
|
7468
|
+
...opts.executionMode !== undefined ? { executionMode: opts.executionMode } : undefined,
|
|
7469
|
+
...opts.graphOptimizationLevel !== undefined ? { graphOptimizationLevel: opts.graphOptimizationLevel } : undefined,
|
|
7470
|
+
...opts.enableMemPattern !== undefined ? { enableMemPattern: opts.enableMemPattern } : undefined,
|
|
7471
|
+
...cuda ? {
|
|
7472
|
+
executionProviders: [
|
|
7473
|
+
{
|
|
7474
|
+
name: "cuda",
|
|
7475
|
+
device_id: 0,
|
|
7476
|
+
...opts.gpuMemLimit !== undefined ? { gpu_mem_limit: opts.gpuMemLimit } : undefined,
|
|
7477
|
+
...opts.arenaExtendStrategy !== undefined ? { arena_extend_strategy: opts.arenaExtendStrategy } : undefined
|
|
7478
|
+
}
|
|
7479
|
+
]
|
|
7480
|
+
} : undefined
|
|
7481
|
+
};
|
|
7482
|
+
};
|
|
7483
|
+
var applyWasmOptions = (env, wasm) => {
|
|
7484
|
+
if (wasm?.numThreads === undefined)
|
|
7485
|
+
return;
|
|
7486
|
+
env.backends.onnx.wasm.numThreads = wasm.numThreads;
|
|
7487
|
+
};
|
|
7334
7488
|
var defaults2 = {
|
|
7335
7489
|
modelId: "Xenova/all-MiniLM-L6-v2",
|
|
7336
7490
|
device: "cpu",
|
|
@@ -7372,10 +7526,11 @@ var make6 = (options) => {
|
|
|
7372
7526
|
}));
|
|
7373
7527
|
if (options.cacheDir)
|
|
7374
7528
|
transformers.env.cacheDir = options.cacheDir;
|
|
7529
|
+
applyWasmOptions(transformers.env, options.wasm);
|
|
7375
7530
|
pipe = yield* Effect32.tryPromise(() => transformers.pipeline("feature-extraction", options.modelId ?? defaults2.modelId, {
|
|
7376
7531
|
device: options.device ?? defaults2.device,
|
|
7377
7532
|
dtype: options.dtype ?? defaults2.dtype,
|
|
7378
|
-
|
|
7533
|
+
session_options: buildSessionOptions(options.sessionOptions ?? {})
|
|
7379
7534
|
})).pipe(Effect32.mapError((cause) => new EmbeddingError({ message: `load model: ${cause}` })));
|
|
7380
7535
|
return pipe;
|
|
7381
7536
|
});
|
|
@@ -7676,7 +7831,7 @@ var configured8 = (options, deps) => make({
|
|
|
7676
7831
|
deps
|
|
7677
7832
|
});
|
|
7678
7833
|
// ../llm/src/llm.ts
|
|
7679
|
-
import { Cause as
|
|
7834
|
+
import { Cause as Cause4, Effect as Effect36, Option as Option12, Schema as Schema28 } from "effect";
|
|
7680
7835
|
import {
|
|
7681
7836
|
generateText as generateTextCall,
|
|
7682
7837
|
NoSuchToolError,
|
|
@@ -7733,7 +7888,7 @@ var makeLLM = (model, defaults3 = {}) => {
|
|
|
7733
7888
|
...input.system !== undefined ? { system: input.system } : undefined,
|
|
7734
7889
|
...callOptions(input)
|
|
7735
7890
|
}).then((result) => result.text),
|
|
7736
|
-
catch: (cause) => new LLMError({ message: "LLM text generation failed", cause:
|
|
7891
|
+
catch: (cause) => new LLMError({ message: "LLM text generation failed", cause: Cause4.die(cause) })
|
|
7737
7892
|
});
|
|
7738
7893
|
yield* Effect36.logDebug("llm.generate-text").pipe(Effect36.annotateLogs({
|
|
7739
7894
|
scope: "@dimple/llm",
|
|
@@ -7785,7 +7940,7 @@ ${schemaJson}`,
|
|
|
7785
7940
|
return Promise.reject(extracted.error);
|
|
7786
7941
|
return input.schema.parse(extracted.value);
|
|
7787
7942
|
},
|
|
7788
|
-
catch: (cause) => new LLMError({ message: "LLM structured generation failed", cause:
|
|
7943
|
+
catch: (cause) => new LLMError({ message: "LLM structured generation failed", cause: Cause4.die(cause) })
|
|
7789
7944
|
});
|
|
7790
7945
|
yield* Effect36.logDebug("llm.generate-object").pipe(Effect36.annotateLogs({
|
|
7791
7946
|
scope: "@dimple/llm",
|
|
@@ -7897,7 +8052,8 @@ var embedderFromConfig = (model) => model.provider === "transformers" ? Effect39
|
|
|
7897
8052
|
...model.normalize !== undefined ? { normalize: model.normalize } : undefined,
|
|
7898
8053
|
...model.cacheDir !== undefined ? { cacheDir: model.cacheDir } : undefined,
|
|
7899
8054
|
...model.autoInstall !== undefined ? { autoInstall: model.autoInstall } : undefined,
|
|
7900
|
-
...model.sessionOptions !== undefined ? { sessionOptions: model.sessionOptions } : undefined
|
|
8055
|
+
...model.sessionOptions !== undefined ? { sessionOptions: model.sessionOptions } : undefined,
|
|
8056
|
+
...model.wasm !== undefined ? { wasm: model.wasm } : undefined
|
|
7901
8057
|
})) : model.provider === "openai" ? model.apiKey === undefined ? Effect39.fail(new EmbeddingError({ message: `OpenAI model ${model.id} requires an apiKey` })) : Effect39.succeed(makeHostedEmbeddingModel({
|
|
7902
8058
|
modelId: model.id,
|
|
7903
8059
|
model: model.model,
|
|
@@ -7987,6 +8143,13 @@ var layer13 = (options) => {
|
|
|
7987
8143
|
config: topicConfig,
|
|
7988
8144
|
backend
|
|
7989
8145
|
}));
|
|
8146
|
+
yield* register("memory.embed.batch", exports_topics.memoryEmbedBatchHandler({
|
|
8147
|
+
getModelConfig,
|
|
8148
|
+
embedOne: (text4, model) => options.embedderFor(model).pipe(Effect39.flatMap((m) => m.embedSingle(text4))),
|
|
8149
|
+
getMemoryContent: (memoryId) => store2.get(memoryId).pipe(Effect39.map((m) => m.content)),
|
|
8150
|
+
config: topicConfig,
|
|
8151
|
+
backend
|
|
8152
|
+
}));
|
|
7990
8153
|
yield* register("concept.cluster", exports_graph.conceptClusterHandler({ getModelConfig, config: graphConfig, backend }));
|
|
7991
8154
|
if (options.llm !== undefined) {
|
|
7992
8155
|
yield* register("memory.dream", exports_graph.graphDreamHandler({
|
|
@@ -8062,6 +8225,13 @@ var layerConfig7 = (options) => Layer15.unwrap(Effect39.gen(function* () {
|
|
|
8062
8225
|
});
|
|
8063
8226
|
}
|
|
8064
8227
|
const llm = cfg.config.llm;
|
|
8228
|
+
const models2 = embedding.models.map((model) => {
|
|
8229
|
+
const sessionOptions = mergeSessionOptions(embedding.sessionOptions, model.sessionOptions);
|
|
8230
|
+
return {
|
|
8231
|
+
...model,
|
|
8232
|
+
...sessionOptions !== undefined ? { sessionOptions } : undefined
|
|
8233
|
+
};
|
|
8234
|
+
});
|
|
8065
8235
|
return layer13({
|
|
8066
8236
|
storeUrl: cfg.config.storeUrl,
|
|
8067
8237
|
...cfg.config.defaultK !== undefined ? { defaultK: cfg.config.defaultK } : undefined,
|
|
@@ -8069,7 +8239,7 @@ var layerConfig7 = (options) => Layer15.unwrap(Effect39.gen(function* () {
|
|
|
8069
8239
|
...cfg.config.defaultTtlSecs !== undefined ? { defaultTtlSecs: cfg.config.defaultTtlSecs } : undefined,
|
|
8070
8240
|
jobsUrl,
|
|
8071
8241
|
...options?.migrationFolder !== undefined ? { migrationFolder: options.migrationFolder } : undefined,
|
|
8072
|
-
models:
|
|
8242
|
+
models: models2,
|
|
8073
8243
|
defaultModelId: embedding.defaultModel,
|
|
8074
8244
|
embedderFor: embedderFromConfig,
|
|
8075
8245
|
...cfg.config.topics !== undefined ? { topics: { config: cfg.config.topics } } : undefined,
|
|
@@ -8204,7 +8374,7 @@ var remapError = (cause) => {
|
|
|
8204
8374
|
};
|
|
8205
8375
|
|
|
8206
8376
|
// src/make.ts
|
|
8207
|
-
import { Effect as Effect50, Exit as
|
|
8377
|
+
import { Effect as Effect50, Exit as Exit8, Layer as Layer26, ManagedRuntime, Scope as Scope5 } from "effect";
|
|
8208
8378
|
|
|
8209
8379
|
// ../extractor/src/code-extractor.ts
|
|
8210
8380
|
import { Context as Context13, Effect as Effect40, Layer as Layer16 } from "effect";
|
|
@@ -9098,7 +9268,7 @@ var resolveConfigInput = Effect48.fn("Sdk.resolveConfigInput")(function* (input)
|
|
|
9098
9268
|
var configLayerFromInput = (input) => Layer25.effect(Service4, resolveConfigInput(input).pipe(Effect48.map((config) => Service4.of({ config }))));
|
|
9099
9269
|
|
|
9100
9270
|
// src/dimple.ts
|
|
9101
|
-
import { Cause as
|
|
9271
|
+
import { Cause as Cause5, Effect as Effect49, Exit as Exit7, Option as Option15, Schema as Schema40 } from "effect";
|
|
9102
9272
|
|
|
9103
9273
|
// src/indexer.ts
|
|
9104
9274
|
import { execFileSync } from "node:child_process";
|
|
@@ -9585,6 +9755,8 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9585
9755
|
const keyPrefix = options.keyPrefix ?? "code-";
|
|
9586
9756
|
const namespace = options.namespace;
|
|
9587
9757
|
const embed = options.embed !== false;
|
|
9758
|
+
const deferEmbed = embed && options.deferEmbed === true;
|
|
9759
|
+
const embedUnits = embed && !deferEmbed;
|
|
9588
9760
|
const maxFileBytes = options.maxFileBytes ?? 64 * 1024;
|
|
9589
9761
|
const maxChunkBytes = options.maxChunkBytes ?? 8 * 1024;
|
|
9590
9762
|
const extensions = [...options.extensions ?? INDEXABLE_EXTENSIONS];
|
|
@@ -9602,6 +9774,7 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9602
9774
|
let skipped = 0;
|
|
9603
9775
|
const unitIds = new Map;
|
|
9604
9776
|
const freshIds = [];
|
|
9777
|
+
const pendingEmbedIds = [];
|
|
9605
9778
|
const pendingEdges = [];
|
|
9606
9779
|
const pendingCallEdges = [];
|
|
9607
9780
|
const stableChunkId = (chunkId) => chunkId.replace(/:\d+$/, "");
|
|
@@ -9612,6 +9785,8 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9612
9785
|
return;
|
|
9613
9786
|
return parentAndMethod.split(".")[0];
|
|
9614
9787
|
};
|
|
9788
|
+
if (embedUnits)
|
|
9789
|
+
yield* core().store.ensureTopicTree(core().defaultModel.id);
|
|
9615
9790
|
for (const filePath of walk.files) {
|
|
9616
9791
|
const relative = keyForPath(walk.root, filePath);
|
|
9617
9792
|
const language = languageForPath(filePath);
|
|
@@ -9629,77 +9804,143 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9629
9804
|
let upd = 0;
|
|
9630
9805
|
let dups = 0;
|
|
9631
9806
|
const fileKey = `${keyPrefix}${relative}`;
|
|
9632
|
-
const fileOutcome = yield* upsertUnit({
|
|
9633
|
-
logicalKey: fileKey,
|
|
9634
|
-
content: source,
|
|
9635
|
-
...namespace !== undefined ? { namespace } : undefined,
|
|
9636
|
-
ttlSecs: null,
|
|
9637
|
-
metadata: JSON.stringify({
|
|
9638
|
-
filePath,
|
|
9639
|
-
language,
|
|
9640
|
-
kind: "file",
|
|
9641
|
-
imports: extracted.imports ?? [],
|
|
9642
|
-
...commit !== null ? { codeVersion: commit } : undefined
|
|
9643
|
-
}),
|
|
9644
|
-
contentType: `text/x-${language}`
|
|
9645
|
-
}, embed);
|
|
9646
|
-
if (fileOutcome.kind === "skipped") {
|
|
9647
|
-
dups += 1;
|
|
9648
|
-
unitIds.set(fileKey, fileOutcome.id);
|
|
9649
|
-
} else {
|
|
9650
|
-
if (fileOutcome.kind === "updated")
|
|
9651
|
-
upd += 1;
|
|
9652
|
-
else
|
|
9653
|
-
units += 1;
|
|
9654
|
-
unitIds.set(fileKey, fileOutcome.id);
|
|
9655
|
-
freshIds.push(fileOutcome.id);
|
|
9656
|
-
}
|
|
9657
9807
|
const classKeys = new Map;
|
|
9658
9808
|
for (const chunk of extracted.chunks) {
|
|
9659
9809
|
if (chunk.kind === "class" || chunk.kind.endsWith("class")) {
|
|
9660
9810
|
classKeys.set(chunk.name, chunkKeyOf(chunk.id));
|
|
9661
9811
|
}
|
|
9662
9812
|
}
|
|
9813
|
+
const specs = [
|
|
9814
|
+
{
|
|
9815
|
+
key: fileKey,
|
|
9816
|
+
input: {
|
|
9817
|
+
logicalKey: fileKey,
|
|
9818
|
+
content: source,
|
|
9819
|
+
...namespace !== undefined ? { namespace } : undefined,
|
|
9820
|
+
ttlSecs: null,
|
|
9821
|
+
metadata: JSON.stringify({
|
|
9822
|
+
filePath,
|
|
9823
|
+
language,
|
|
9824
|
+
kind: "file",
|
|
9825
|
+
imports: extracted.imports ?? [],
|
|
9826
|
+
...commit !== null ? { codeVersion: commit } : undefined
|
|
9827
|
+
}),
|
|
9828
|
+
contentType: `text/x-${language}`
|
|
9829
|
+
}
|
|
9830
|
+
}
|
|
9831
|
+
];
|
|
9663
9832
|
for (const chunk of extracted.chunks) {
|
|
9664
9833
|
const chunkKey = chunkKeyOf(chunk.id);
|
|
9665
9834
|
const content = [chunk.docstring, chunk.sourceText].filter((c) => c !== undefined && c.length > 0).join(`
|
|
9666
9835
|
|
|
9667
9836
|
`).slice(0, maxChunkBytes);
|
|
9668
|
-
const
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9837
|
+
const parent = chunk.kind === "method" ? parentClassOf(chunk.id) : undefined;
|
|
9838
|
+
const classKey = parent === undefined ? undefined : classKeys.get(parent);
|
|
9839
|
+
specs.push({
|
|
9840
|
+
key: chunkKey,
|
|
9841
|
+
input: {
|
|
9842
|
+
logicalKey: chunkKey,
|
|
9843
|
+
content,
|
|
9844
|
+
...namespace !== undefined ? { namespace } : undefined,
|
|
9845
|
+
ttlSecs: null,
|
|
9846
|
+
metadata: JSON.stringify({
|
|
9847
|
+
filePath,
|
|
9848
|
+
language,
|
|
9849
|
+
kind: chunk.kind,
|
|
9850
|
+
name: chunk.name,
|
|
9851
|
+
startLine: chunk.startLine,
|
|
9852
|
+
endLine: chunk.endLine,
|
|
9853
|
+
...chunk.docstring !== undefined ? { docstring: chunk.docstring } : undefined,
|
|
9854
|
+
...commit !== null ? { codeVersion: commit } : undefined
|
|
9855
|
+
}),
|
|
9856
|
+
contentType: `text/x-${language}`
|
|
9857
|
+
},
|
|
9858
|
+
...classKey !== undefined ? { containedBy: classKey } : undefined
|
|
9859
|
+
});
|
|
9860
|
+
}
|
|
9861
|
+
const outcomes = new Map;
|
|
9862
|
+
const record = (key, kind, id) => {
|
|
9863
|
+
outcomes.set(key, kind);
|
|
9864
|
+
if (kind === "skipped") {
|
|
9686
9865
|
dups += 1;
|
|
9687
|
-
unitIds.set(
|
|
9688
|
-
|
|
9689
|
-
if (chunkOutcome.kind === "updated")
|
|
9690
|
-
upd += 1;
|
|
9691
|
-
else
|
|
9692
|
-
units += 1;
|
|
9693
|
-
unitIds.set(chunkKey, chunkOutcome.id);
|
|
9694
|
-
freshIds.push(chunkOutcome.id);
|
|
9866
|
+
unitIds.set(key, id);
|
|
9867
|
+
return;
|
|
9695
9868
|
}
|
|
9696
|
-
if (
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9869
|
+
if (kind === "updated")
|
|
9870
|
+
upd += 1;
|
|
9871
|
+
else
|
|
9872
|
+
units += 1;
|
|
9873
|
+
unitIds.set(key, id);
|
|
9874
|
+
freshIds.push(id);
|
|
9875
|
+
};
|
|
9876
|
+
const upsertAll = (candidates2) => Effect49.gen(function* () {
|
|
9877
|
+
const ids = [];
|
|
9878
|
+
for (const spec of candidates2) {
|
|
9879
|
+
const outcome = yield* upsertUnit(spec.input, embedUnits);
|
|
9880
|
+
record(spec.key, outcome.kind, outcome.id);
|
|
9881
|
+
ids.push(outcome.id);
|
|
9882
|
+
}
|
|
9883
|
+
return ids;
|
|
9884
|
+
});
|
|
9885
|
+
if (deferEmbed) {
|
|
9886
|
+
const fresh = [];
|
|
9887
|
+
for (const spec of specs) {
|
|
9888
|
+
const existing = yield* core().store.getByKey(spec.key, namespace ?? "default").pipe(Effect49.catchTag("Store.NotFound", () => Effect49.succeed(undefined)));
|
|
9889
|
+
if (existing === undefined) {
|
|
9890
|
+
fresh.push(spec);
|
|
9891
|
+
continue;
|
|
9892
|
+
}
|
|
9893
|
+
const outcome = yield* upsertUnit(spec.input, false);
|
|
9894
|
+
record(spec.key, outcome.kind, outcome.id);
|
|
9895
|
+
if (outcome.kind !== "skipped" || existing.embedding == null || existing.embeddingModel !== core().defaultModel.id) {
|
|
9896
|
+
pendingEmbedIds.push(outcome.id);
|
|
9701
9897
|
}
|
|
9702
9898
|
}
|
|
9899
|
+
if (fresh.length > 0) {
|
|
9900
|
+
const freshKeys = fresh.map((spec) => spec.key);
|
|
9901
|
+
if (new Set(freshKeys).size !== freshKeys.length) {
|
|
9902
|
+
pendingEmbedIds.push(...yield* upsertAll(fresh));
|
|
9903
|
+
} else {
|
|
9904
|
+
const mems = yield* core().store.writeMany(fresh.map((spec) => spec.input));
|
|
9905
|
+
for (const mem of mems) {
|
|
9906
|
+
record(mem.logicalKey, "indexed", mem.id);
|
|
9907
|
+
pendingEmbedIds.push(mem.id);
|
|
9908
|
+
}
|
|
9909
|
+
}
|
|
9910
|
+
}
|
|
9911
|
+
} else if (!embedUnits) {
|
|
9912
|
+
yield* upsertAll(specs);
|
|
9913
|
+
} else {
|
|
9914
|
+
const fresh = [];
|
|
9915
|
+
for (const spec of specs) {
|
|
9916
|
+
const existing = yield* core().store.getByKey(spec.key, namespace ?? "default").pipe(Effect49.catchTag("Store.NotFound", () => Effect49.succeed(undefined)));
|
|
9917
|
+
if (existing === undefined) {
|
|
9918
|
+
fresh.push(spec);
|
|
9919
|
+
continue;
|
|
9920
|
+
}
|
|
9921
|
+
const outcome = yield* upsertUnit(spec.input, embed);
|
|
9922
|
+
record(spec.key, outcome.kind, outcome.id);
|
|
9923
|
+
}
|
|
9924
|
+
if (fresh.length > 0) {
|
|
9925
|
+
const freshKeys = fresh.map((spec) => spec.key);
|
|
9926
|
+
if (new Set(freshKeys).size !== freshKeys.length) {
|
|
9927
|
+
yield* upsertAll(fresh);
|
|
9928
|
+
} else {
|
|
9929
|
+
const mems = yield* core().store.writeMany(fresh.map((spec) => spec.input));
|
|
9930
|
+
const vectors = [];
|
|
9931
|
+
for (const spec of fresh) {
|
|
9932
|
+
vectors.push(yield* core().defaultEmbedder.embedSingle(spec.input.content));
|
|
9933
|
+
}
|
|
9934
|
+
yield* core().store.updateEmbeddingMany(mems.map((mem, i) => ({ id: mem.id, embedding: [...vectors[i]] })), core().defaultModel.id);
|
|
9935
|
+
for (const mem of mems)
|
|
9936
|
+
record(mem.logicalKey, "indexed", mem.id);
|
|
9937
|
+
}
|
|
9938
|
+
}
|
|
9939
|
+
}
|
|
9940
|
+
for (const spec of specs) {
|
|
9941
|
+
if (spec.containedBy !== undefined && outcomes.get(spec.key) !== "skipped") {
|
|
9942
|
+
pendingEdges.push({ from: spec.containedBy, to: spec.key });
|
|
9943
|
+
}
|
|
9703
9944
|
}
|
|
9704
9945
|
const importTargets = resolveImports(filePath, (extracted.imports ?? []).map((imp) => imp.source), extensions);
|
|
9705
9946
|
for (const target of importTargets) {
|
|
@@ -9726,8 +9967,8 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9726
9967
|
}
|
|
9727
9968
|
return { units, upd, dups };
|
|
9728
9969
|
}));
|
|
9729
|
-
if (
|
|
9730
|
-
failed.push({ filePath, message:
|
|
9970
|
+
if (Exit7.isFailure(exit)) {
|
|
9971
|
+
failed.push({ filePath, message: Cause5.pretty(exit.cause) });
|
|
9731
9972
|
} else {
|
|
9732
9973
|
indexed += exit.value.units;
|
|
9733
9974
|
updated += exit.value.upd;
|
|
@@ -9762,6 +10003,16 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9762
10003
|
for (const edge of pendingCallEdges) {
|
|
9763
10004
|
yield* Effect49.exit(edgeEffect({ ...edge, edgeKind: "code_calls" }));
|
|
9764
10005
|
}
|
|
10006
|
+
const EMBED_BATCH = 512;
|
|
10007
|
+
if (deferEmbed) {
|
|
10008
|
+
for (let i = 0;i < pendingEmbedIds.length; i += EMBED_BATCH) {
|
|
10009
|
+
yield* core().runtime.enqueue(MemoryEmbedBatch, {
|
|
10010
|
+
memoryIds: pendingEmbedIds.slice(i, i + EMBED_BATCH),
|
|
10011
|
+
modelKey: core().defaultModel.id,
|
|
10012
|
+
nonce: crypto.randomUUID()
|
|
10013
|
+
});
|
|
10014
|
+
}
|
|
10015
|
+
}
|
|
9765
10016
|
return {
|
|
9766
10017
|
files: walk.files.length,
|
|
9767
10018
|
indexed,
|
|
@@ -9770,7 +10021,8 @@ var makeFacade = (state, reload, dispose) => {
|
|
|
9770
10021
|
skipped,
|
|
9771
10022
|
unsupported: walk.unsupported,
|
|
9772
10023
|
commit,
|
|
9773
|
-
failed
|
|
10024
|
+
failed,
|
|
10025
|
+
...deferEmbed ? { pendingEmbeddings: pendingEmbedIds.length } : undefined
|
|
9774
10026
|
};
|
|
9775
10027
|
})),
|
|
9776
10028
|
updateEmbedding: (id, embedding, modelKey) => run(Effect49.gen(function* () {
|
|
@@ -9857,10 +10109,10 @@ var bootStack = async (options) => {
|
|
|
9857
10109
|
core,
|
|
9858
10110
|
parser,
|
|
9859
10111
|
extractor,
|
|
9860
|
-
dispose: () => Effect50.runPromise(Scope5.close(scope,
|
|
10112
|
+
dispose: () => Effect50.runPromise(Scope5.close(scope, Exit8.void).pipe(Effect50.andThen(rt.disposeEffect)))
|
|
9861
10113
|
};
|
|
9862
10114
|
} catch (cause) {
|
|
9863
|
-
await Effect50.runPromise(Scope5.close(scope,
|
|
10115
|
+
await Effect50.runPromise(Scope5.close(scope, Exit8.void).pipe(Effect50.andThen(runtime?.disposeEffect ?? Effect50.void))).catch(() => {
|
|
9864
10116
|
return;
|
|
9865
10117
|
});
|
|
9866
10118
|
return Promise.reject(cause);
|