akanjs 3.0.0-beta.18 → 3.0.0-beta.19
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/base/baseEnv.ts +12 -3
- package/base/databaseModes.ts +76 -0
- package/base/index.ts +1 -0
- package/base/primitiveRegistry.ts +27 -7
- package/common/CodeTranscript.ts +13 -2
- package/common/codeAgentWire.ts +17 -3
- package/constant/getDefault.ts +21 -2
- package/constant/mask.ts +35 -3
- package/dictionary/agent.dictionary.ts +9 -0
- package/dictionary/base.dictionary.ts +5 -0
- package/document/database.ts +39 -3
- package/document/queryEvaluator.ts +10 -1
- package/index.ts +10 -1
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0001.log +44 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0002.log +42 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0003.log +43 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0004.log +44 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0005.log +50 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0006.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0007.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0008.log +47 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0009.log +47 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0010.log +6 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0011.log +14 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0012.log +6 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0013.log +35 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0014.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0015.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0016.log +47 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0017.log +47 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0018.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0019.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0020.log +47 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0021.log +47 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0022.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0023.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0024.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0025.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0026.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0027.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0028.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0029.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0030.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0031.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0032.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0033.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0034.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0035.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0036.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0037.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0038.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0039.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0040.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0041.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0042.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0043.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0044.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0045.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0046.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0047.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0048.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0049.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0050.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0051.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0052.log +46 -0
- package/local/apps/crossTest/runtime/logs/crossTest-testing-local-2026-09-25-all-0053.log +46 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
- package/package.json +2 -1
- package/server/akanApp.ts +28 -1
- package/server/akanOption.ts +22 -1
- package/server/akanServer.ts +36 -4
- package/server/artifact/builderRpc.ts +7 -2
- package/server/artifact/ipcTypes.ts +1 -0
- package/server/artifact/routeClientCache.ts +5 -1
- package/server/di/diLifecycle.ts +31 -3
- package/server/di/predefinedAdaptor.ts +13 -3
- package/server/hmr/devHmrController.ts +8 -1
- package/server/mcp/McpDispatcher.ts +7 -5
- package/server/mcp/McpRateLimiter.ts +67 -21
- package/server/mcp/McpRouter.ts +14 -8
- package/server/mcp/PagePromptComposer.ts +6 -2
- package/server/ops/ageEncryption.ts +322 -0
- package/server/ops/appInfo.ts +92 -0
- package/server/ops/opsCommand.ts +120 -0
- package/server/ops/opsRoute.ts +155 -0
- package/server/ops/opsToken.ts +97 -0
- package/server/ops/snapshotJobs.ts +137 -0
- package/server/ops/snapshotRestore.ts +127 -0
- package/server/ops/snapshotTypes.ts +54 -0
- package/server/ops/sqliteFiles.ts +43 -0
- package/server/ops/sqliteSnapshot.ts +153 -0
- package/server/resolver/signal.resolver.ts +49 -10
- package/server/routing/soloAppRoutes.ts +5 -0
- package/server/rscWorkerHost.ts +9 -1
- package/server/webRouter.ts +11 -3
- package/service/agent.service.ts +8 -1
- package/service/injectInfo.ts +31 -13
- package/service/ipcTypes.ts +3 -0
- package/service/predefinedAdaptor/anthropicLlm.ts +36 -10
- package/service/predefinedAdaptor/cache.adaptor.ts +246 -94
- package/service/predefinedAdaptor/database.adaptor.ts +357 -74
- package/service/predefinedAdaptor/documentTransfer.ts +91 -0
- package/service/predefinedAdaptor/index.ts +2 -0
- package/service/predefinedAdaptor/insightQuery.ts +113 -43
- package/service/predefinedAdaptor/llm.adaptor.ts +33 -0
- package/service/predefinedAdaptor/llmOverflow.ts +73 -0
- package/service/predefinedAdaptor/openaiDialect.ts +23 -2
- package/service/predefinedAdaptor/openaiLlm.ts +11 -17
- package/service/predefinedAdaptor/queue.adaptor.ts +40 -21
- package/service/predefinedAdaptor/schedule.adaptor.ts +69 -8
- package/service/predefinedAdaptor/searchIndex.ts +63 -288
- package/service/predefinedAdaptor/solidCache.adaptor.ts +135 -12
- package/service/predefinedAdaptor/solidPubsub.adaptor.ts +27 -12
- package/service/predefinedAdaptor/solidQueue.adaptor.ts +66 -10
- package/service/predefinedAdaptor/solidSqlite.ts +8 -2
- package/service/predefinedAdaptor/sql/PostgresInsightSession.ts +116 -0
- package/service/predefinedAdaptor/sql/QueryCompiler.ts +47 -19
- package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +256 -60
- package/service/predefinedAdaptor/sql/SqliteInsightSession.ts +89 -0
- package/service/predefinedAdaptor/sql/dialect/postgres.ts +139 -51
- package/service/predefinedAdaptor/sql/dialect/sqlite.ts +17 -13
- package/service/predefinedAdaptor/sql/driver/bunSqlite.ts +29 -4
- package/service/predefinedAdaptor/sql/driver/libsql.ts +26 -12
- package/service/predefinedAdaptor/sql/driver/postgres.ts +13 -7
- package/service/predefinedAdaptor/sql/search/fts5.ts +260 -0
- package/service/predefinedAdaptor/sql/search/mirror.ts +76 -0
- package/service/predefinedAdaptor/sql/search/postgres.ts +455 -0
- package/service/predefinedAdaptor/sql/search/types.ts +54 -0
- package/service/predefinedAdaptor/sql/types.ts +79 -16
- package/service/predefinedAdaptor/sql/values.ts +14 -1
- package/service/predefinedAdaptor/storage.adaptor.ts +16 -0
- package/service/predefinedAdaptor/websocket.adaptor.ts +157 -168
- package/signal/agent.signal.ts +8 -4
- package/signal/agentMeter.ts +49 -0
- package/signal/agentTurnStream.ts +18 -7
- package/signal/index.ts +1 -0
- package/signal/internal.ts +2 -2
- package/signal/internalArg.ts +7 -0
- package/signal/mcp/McpDocument.ts +1 -1
- package/signal/schema/JsonSchemaBuilder.ts +27 -4
- package/signal/signalContext.ts +13 -2
- package/signal/types.ts +6 -0
- package/store/agent/index.ts +1 -1
- package/store/agentic/AgentValue.ts +9 -6
- package/store/agentic/formFields.ts +3 -0
- package/test/conformance.ts +313 -0
- package/test/index.ts +1 -0
- package/test/sampleOf.ts +19 -2
- package/test/signalTestRuntime.ts +2 -2
- package/test/testServer.ts +64 -12
- package/types/base/baseEnv.d.ts +2 -2
- package/types/base/databaseModes.d.ts +29 -0
- package/types/base/index.d.ts +1 -0
- package/types/base/primitiveRegistry.d.ts +21 -4
- package/types/common/codeAgentWire.d.ts +11 -1
- package/types/constant/getDefault.d.ts +10 -1
- package/types/constant/mask.d.ts +10 -1
- package/types/dictionary/agent.dictionary.d.ts +1 -1
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictionary.d.ts +9 -9
- package/types/document/database.d.ts +15 -3
- package/types/index.d.ts +9 -1
- package/types/server/akanOption.d.ts +10 -1
- package/types/server/artifact/builderRpc.d.ts +2 -1
- package/types/server/artifact/ipcTypes.d.ts +1 -0
- package/types/server/di/predefinedAdaptor.d.ts +5 -0
- package/types/server/mcp/McpRateLimiter.d.ts +15 -5
- package/types/server/mcp/McpRouter.d.ts +1 -1
- package/types/server/ops/ageEncryption.d.ts +24 -0
- package/types/server/ops/appInfo.d.ts +36 -0
- package/types/server/ops/opsCommand.d.ts +9 -0
- package/types/server/ops/opsRoute.d.ts +28 -0
- package/types/server/ops/opsToken.d.ts +30 -0
- package/types/server/ops/snapshotJobs.d.ts +25 -0
- package/types/server/ops/snapshotRestore.d.ts +24 -0
- package/types/server/ops/snapshotTypes.d.ts +46 -0
- package/types/server/ops/sqliteFiles.d.ts +10 -0
- package/types/server/ops/sqliteSnapshot.d.ts +31 -0
- package/types/server/resolver/signal.resolver.d.ts +5 -0
- package/types/server/routing/soloAppRoutes.d.ts +2 -1
- package/types/server/rscWorkerHost.d.ts +3 -1
- package/types/service/agent.service.d.ts +3 -0
- package/types/service/injectInfo.d.ts +9 -0
- package/types/service/ipcTypes.d.ts +6 -0
- package/types/service/predefinedAdaptor/anthropicLlm.d.ts +10 -1
- package/types/service/predefinedAdaptor/cache.adaptor.d.ts +45 -12
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +20 -3
- package/types/service/predefinedAdaptor/documentTransfer.d.ts +17 -0
- package/types/service/predefinedAdaptor/index.d.ts +2 -0
- package/types/service/predefinedAdaptor/insightQuery.d.ts +14 -12
- package/types/service/predefinedAdaptor/llm.adaptor.d.ts +31 -0
- package/types/service/predefinedAdaptor/llmOverflow.d.ts +26 -0
- package/types/service/predefinedAdaptor/openaiDialect.d.ts +14 -1
- package/types/service/predefinedAdaptor/openaiLlm.d.ts +3 -1
- package/types/service/predefinedAdaptor/queue.adaptor.d.ts +12 -7
- package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +7 -2
- package/types/service/predefinedAdaptor/searchIndex.d.ts +12 -25
- package/types/service/predefinedAdaptor/solidCache.adaptor.d.ts +15 -6
- package/types/service/predefinedAdaptor/solidPubsub.adaptor.d.ts +6 -4
- package/types/service/predefinedAdaptor/solidSqlite.d.ts +1 -0
- package/types/service/predefinedAdaptor/sql/PostgresInsightSession.d.ts +23 -0
- package/types/service/predefinedAdaptor/sql/QueryCompiler.d.ts +7 -3
- package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +11 -2
- package/types/service/predefinedAdaptor/sql/SqliteInsightSession.d.ts +19 -0
- package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +20 -10
- package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +5 -2
- package/types/service/predefinedAdaptor/sql/driver/bunSqlite.d.ts +9 -3
- package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +9 -5
- package/types/service/predefinedAdaptor/sql/driver/postgres.d.ts +4 -4
- package/types/service/predefinedAdaptor/sql/search/fts5.d.ts +33 -0
- package/types/service/predefinedAdaptor/sql/search/mirror.d.ts +20 -0
- package/types/service/predefinedAdaptor/sql/search/postgres.d.ts +54 -0
- package/types/service/predefinedAdaptor/sql/search/types.d.ts +49 -0
- package/types/service/predefinedAdaptor/sql/types.d.ts +73 -15
- package/types/service/predefinedAdaptor/sql/values.d.ts +3 -0
- package/types/service/predefinedAdaptor/storage.adaptor.d.ts +6 -0
- package/types/service/predefinedAdaptor/websocket.adaptor.d.ts +29 -13
- package/types/signal/agent.signal.d.ts +4 -1
- package/types/signal/agentMeter.d.ts +28 -0
- package/types/signal/agentTurnStream.d.ts +6 -1
- package/types/signal/index.d.ts +1 -0
- package/types/signal/internalArg.d.ts +4 -0
- package/types/signal/schema/JsonSchemaBuilder.d.ts +11 -2
- package/types/signal/types.d.ts +6 -0
- package/types/store/agent/index.d.ts +1 -1
- package/types/store/agentic/AgentValue.d.ts +3 -3
- package/types/test/conformance.d.ts +87 -0
- package/types/test/index.d.ts +1 -0
- package/types/test/sampleOf.d.ts +1 -1
- package/types/test/signalTestRuntime.d.ts +1 -1
- package/types/test/testServer.d.ts +4 -3
- package/types/ui/Agent/Chat.d.ts +4 -2
- package/types/vendor/use-agentic/AgentProgress.d.ts +12 -0
- package/types/vendor/use-agentic/AgentSession.d.ts +11 -1
- package/types/vendor/use-agentic/Compaction.d.ts +42 -5
- package/types/vendor/use-agentic/Transcript.d.ts +2 -0
- package/types/vendor/use-agentic/types.d.ts +29 -0
- package/ui/Agent/Bubble.tsx +47 -1
- package/ui/Agent/Chat.tsx +15 -6
- package/ui/Agent/fetchRunner.ts +2 -1
- package/ui/CsrImage.tsx +6 -3
- package/ui/Image.tsx +8 -10
- package/ui/Portal.tsx +2 -3
- package/ui/Refresh.tsx +1 -3
- package/ui/ScreenNavigator.tsx +6 -4
- package/ui/System/SSR.tsx +8 -5
- package/vendor/use-agentic/AgentProgress.ts +13 -1
- package/vendor/use-agentic/AgentSession.ts +119 -27
- package/vendor/use-agentic/Compaction.ts +82 -8
- package/vendor/use-agentic/Transcript.ts +6 -1
- package/vendor/use-agentic/WIRE.md +16 -2
- package/vendor/use-agentic/httpRunner.ts +19 -4
- package/vendor/use-agentic/types.ts +33 -2
package/base/baseEnv.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { DatabaseModes } from "./databaseModes";
|
|
2
|
+
|
|
1
3
|
type ProcessEnvLike = { env?: Record<string, string | undefined> };
|
|
2
4
|
|
|
3
5
|
const globalWithProcess = globalThis as unknown as { process?: ProcessEnvLike };
|
|
@@ -19,8 +21,6 @@ export type BackendEnv = {
|
|
|
19
21
|
hostname?: string | null;
|
|
20
22
|
port?: number;
|
|
21
23
|
database?: {
|
|
22
|
-
mode?: DatabaseMode;
|
|
23
|
-
driver?: "sqlite" | "libsql" | "postgres";
|
|
24
24
|
sqlite?: {
|
|
25
25
|
filePath?: string;
|
|
26
26
|
journalMode?: string;
|
|
@@ -41,6 +41,7 @@ export type BackendEnv = {
|
|
|
41
41
|
database?: string;
|
|
42
42
|
user?: string;
|
|
43
43
|
password?: string;
|
|
44
|
+
insightUrl?: string;
|
|
44
45
|
};
|
|
45
46
|
};
|
|
46
47
|
solid?: {
|
|
@@ -51,6 +52,7 @@ export type BackendEnv = {
|
|
|
51
52
|
cleanupIntervalMs?: number;
|
|
52
53
|
queuePollIntervalMs?: number;
|
|
53
54
|
queueLeaseMs?: number;
|
|
55
|
+
queueFailedRetentionMs?: number;
|
|
54
56
|
};
|
|
55
57
|
onCleanup?: () => Promise<void>;
|
|
56
58
|
};
|
|
@@ -133,7 +135,14 @@ export const getEnv = (): ClientEnv => {
|
|
|
133
135
|
appName,
|
|
134
136
|
environment,
|
|
135
137
|
operationMode,
|
|
136
|
-
databaseMode:
|
|
138
|
+
databaseMode:
|
|
139
|
+
typeof window === "undefined"
|
|
140
|
+
? DatabaseModes.settle({
|
|
141
|
+
requested: process.env.AKAN_DATABASE_MODE,
|
|
142
|
+
declared: process.env.AKAN_DATABASE_MODES,
|
|
143
|
+
local: environment === "local" || operationMode === "local",
|
|
144
|
+
})
|
|
145
|
+
: undefined,
|
|
137
146
|
} as const;
|
|
138
147
|
const side = typeof window === "undefined" ? "server" : "client";
|
|
139
148
|
const renderMode = (process.env.AKAN_PUBLIC_RENDER_ENV ?? "csr") as ClientEnv["renderMode"];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { DatabaseMode } from "./baseEnv";
|
|
2
|
+
|
|
3
|
+
export interface DatabaseModeRequest {
|
|
4
|
+
/** `AKAN_DATABASE_MODE`: the mode a deployment names. */
|
|
5
|
+
requested: string | undefined;
|
|
6
|
+
/** `AKAN_DATABASE_MODES`: what the build carries drivers for, first one the default. Unset allows any. */
|
|
7
|
+
declared: string | undefined;
|
|
8
|
+
/** A developer machine, which may leave the mode unnamed when the build carries several. */
|
|
9
|
+
local: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** The database modes, what each runs on, and how a process settles on one. The CLI and the server share it. */
|
|
13
|
+
export class DatabaseModes {
|
|
14
|
+
static readonly all = ["single", "multiple", "cluster"] as const satisfies readonly DatabaseMode[];
|
|
15
|
+
/** Packages a mode imports at runtime. A build carries them for every mode the app declares. */
|
|
16
|
+
static readonly drivers: { [mode in DatabaseMode]: readonly string[] } = {
|
|
17
|
+
single: [],
|
|
18
|
+
multiple: ["bullmq", "ioredis"],
|
|
19
|
+
cluster: ["bullmq", "ioredis", "postgres"],
|
|
20
|
+
};
|
|
21
|
+
static readonly #stores: { [mode in DatabaseMode]: string } = {
|
|
22
|
+
single: "sqlite · solid",
|
|
23
|
+
multiple: "sqlite · redis",
|
|
24
|
+
cluster: "postgres · redis",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
static describe(mode: DatabaseMode) {
|
|
28
|
+
return `${mode} (${DatabaseModes.#stores[mode]})`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static parse(value: string, source: string): DatabaseMode {
|
|
32
|
+
const mode = value.trim();
|
|
33
|
+
if ((DatabaseModes.all as readonly string[]).includes(mode)) return mode as DatabaseMode;
|
|
34
|
+
throw new Error(`${source} must be one of ${DatabaseModes.all.join(", ")}, not "${value}"`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static parseList(value: string, source: string): DatabaseMode[] {
|
|
38
|
+
const modes = value
|
|
39
|
+
.split(",")
|
|
40
|
+
.filter((mode) => mode.trim())
|
|
41
|
+
.map((mode) => DatabaseModes.parse(mode, source));
|
|
42
|
+
if (!modes.length) throw new Error(`${source} names no database mode`);
|
|
43
|
+
return [...new Set(modes)];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The mode this process runs in, or the reason it cannot pick one. A deployment that names no mode when the build
|
|
48
|
+
* carries several fails rather than falling back: the fallback would be a SQLite file inside each container, which a
|
|
49
|
+
* cluster deployment would find out about only once its instances disagreed.
|
|
50
|
+
*/
|
|
51
|
+
static resolve({ requested, declared, local }: DatabaseModeRequest): DatabaseMode {
|
|
52
|
+
const modes = declared?.trim() ? DatabaseModes.parseList(declared, "AKAN_DATABASE_MODES") : null;
|
|
53
|
+
if (requested?.trim()) {
|
|
54
|
+
const mode = DatabaseModes.parse(requested, "AKAN_DATABASE_MODE");
|
|
55
|
+
if (modes && !modes.includes(mode))
|
|
56
|
+
throw new Error(
|
|
57
|
+
`AKAN_DATABASE_MODE is ${mode}, but this build carries only ${modes.join(", ")}. Add "${mode}" to database.modes in akan.config.ts and rebuild.`,
|
|
58
|
+
);
|
|
59
|
+
return mode;
|
|
60
|
+
}
|
|
61
|
+
if (!modes) return "single";
|
|
62
|
+
if (modes.length === 1 || local) return modes[0] as DatabaseMode;
|
|
63
|
+
throw new Error(
|
|
64
|
+
`This build runs in ${modes.join(" or ")} mode, and AKAN_DATABASE_MODE names neither. Set it to say which this deployment is.`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** `resolve` for readers that cannot fail a boot; the boot itself resolves again and reports the reason. */
|
|
69
|
+
static settle(request: DatabaseModeRequest): DatabaseMode | undefined {
|
|
70
|
+
try {
|
|
71
|
+
return DatabaseModes.resolve(request);
|
|
72
|
+
} catch {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
package/base/index.ts
CHANGED
|
@@ -11,12 +11,8 @@ export const dayjs = dayjsLib;
|
|
|
11
11
|
export class PrimitiveRegistry {
|
|
12
12
|
static readonly #namePrimitiveMap = new Map<string, typeof PrimitiveScalar>();
|
|
13
13
|
static readonly #primitiveNameMap = new Map<typeof PrimitiveScalar, string>();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
!overwrite &&
|
|
17
|
-
(PrimitiveRegistry.#namePrimitiveMap.has(scalar.refName) || PrimitiveRegistry.#primitiveNameMap.has(scalar))
|
|
18
|
-
)
|
|
19
|
-
throw new Error(`Scalar ${scalar.refName} already registered`);
|
|
14
|
+
|
|
15
|
+
static register(scalar: typeof PrimitiveScalar) {
|
|
20
16
|
PrimitiveRegistry.#namePrimitiveMap.set(scalar.refName, scalar);
|
|
21
17
|
PrimitiveRegistry.#primitiveNameMap.set(scalar, scalar.refName);
|
|
22
18
|
}
|
|
@@ -42,9 +38,29 @@ export class PrimitiveRegistry {
|
|
|
42
38
|
static getAll(): (typeof PrimitiveScalar)[] {
|
|
43
39
|
return [...PrimitiveRegistry.#namePrimitiveMap.values()];
|
|
44
40
|
}
|
|
41
|
+
/** The agent face `modelRef` declares, or null for anything that is not a registered primitive declaring one. */
|
|
42
|
+
static agentOf(modelRef: unknown): PrimitiveAgentFace | null {
|
|
43
|
+
if (!PrimitiveRegistry.#primitiveNameMap.has(modelRef as typeof PrimitiveScalar)) return null;
|
|
44
|
+
return (modelRef as typeof PrimitiveScalar).agent ?? null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface PrimitiveJsonSchema {
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* How an agent — an MCP client or the in-page one — sees a primitive whose stored shape is not the one a model
|
|
54
|
+
* should read or write: `schema` is what it is published as on both sides of a call, and `read` turns a stored or
|
|
55
|
+
* wire value into that shape. There is no `write`, because every argument and every input field already runs
|
|
56
|
+
* through `parseValue`; a primitive that accepts the agent's shape there has taken the write.
|
|
57
|
+
*/
|
|
58
|
+
export interface PrimitiveAgentFace<Value = unknown> {
|
|
59
|
+
schema: PrimitiveJsonSchema;
|
|
60
|
+
read(value: Value): unknown;
|
|
45
61
|
}
|
|
46
62
|
|
|
47
|
-
export type PrimitiveValue = string | number | boolean | Dayjs | Date | Uint8Array | null | undefined;
|
|
63
|
+
export type PrimitiveValue = string | number | boolean | Dayjs | Date | Uint8Array | object | null | undefined;
|
|
48
64
|
export class PrimitiveScalar {
|
|
49
65
|
static refName: string;
|
|
50
66
|
static [SERVER_VALUE]: unknown;
|
|
@@ -52,6 +68,10 @@ export class PrimitiveScalar {
|
|
|
52
68
|
static [DEFAULT_VALUE]: unknown = null;
|
|
53
69
|
static [PURIFIED_VALUE]: unknown = null;
|
|
54
70
|
static [EXAMPLE_VALUE]: unknown = null;
|
|
71
|
+
/** The wire shape, for a primitive the built-in schema table cannot know. Absent, it is published as a string. */
|
|
72
|
+
static jsonSchema?: PrimitiveJsonSchema;
|
|
73
|
+
/** Absent, an agent sees the wire shape. See `PrimitiveAgentFace`. */
|
|
74
|
+
static agent?: PrimitiveAgentFace;
|
|
55
75
|
|
|
56
76
|
static validate(value: PrimitiveValue): boolean {
|
|
57
77
|
return true;
|
package/common/CodeTranscript.ts
CHANGED
|
@@ -179,6 +179,13 @@ export class CodeTranscript {
|
|
|
179
179
|
case "question":
|
|
180
180
|
this.#question = event.question;
|
|
181
181
|
return this.#push({ kind: "question", id: event.question.questionId, question: event.question });
|
|
182
|
+
case "question_skipped":
|
|
183
|
+
return this.#push({
|
|
184
|
+
kind: "question",
|
|
185
|
+
id: event.question.questionId,
|
|
186
|
+
question: event.question,
|
|
187
|
+
rendered: `(${event.reason})`,
|
|
188
|
+
});
|
|
182
189
|
case "question_resolved":
|
|
183
190
|
if (this.#question?.questionId === event.questionId) this.#question = undefined;
|
|
184
191
|
return this.#patch(event.questionId, (part) => {
|
|
@@ -197,8 +204,12 @@ export class CodeTranscript {
|
|
|
197
204
|
return;
|
|
198
205
|
case "compaction":
|
|
199
206
|
this.#compacting = event.phase === "start";
|
|
200
|
-
if (event.phase === "
|
|
201
|
-
|
|
207
|
+
if (event.phase === "start") return;
|
|
208
|
+
|
|
209
|
+
if ((event.error || event.aborted) && event.reason === "manual") return;
|
|
210
|
+
if (event.error) return this.#notice("warning", event.error);
|
|
211
|
+
if (event.aborted) return this.#notice("info", "Compaction cancelled.");
|
|
212
|
+
return this.#notice("info", `Compacted the conversation (${event.reason}).`);
|
|
202
213
|
case "retry":
|
|
203
214
|
return this.#notice(
|
|
204
215
|
"warning",
|
package/common/codeAgentWire.ts
CHANGED
|
@@ -190,10 +190,19 @@ export type CodeAgentEventBody =
|
|
|
190
190
|
}
|
|
191
191
|
| { type: "question"; question: CodeAgentQuestion }
|
|
192
192
|
| { type: "question_resolved"; questionId: string; answer: CodeAgentAnswer; rendered: string }
|
|
193
|
+
/** A question nobody could be asked — no host attached — answered with nothing; the model continued on its own. */
|
|
194
|
+
| { type: "question_skipped"; question: CodeAgentQuestion; reason: "no-host" }
|
|
193
195
|
| { type: "approval"; request: CodeAgentApprovalRequest }
|
|
194
196
|
| { type: "approval_resolved"; approvalId: string; approved: boolean }
|
|
195
197
|
| { type: "context"; used: number; max: number | undefined }
|
|
196
|
-
|
|
198
|
+
/** An `end` carrying neither `error` nor `aborted` is the only one that compacted anything. */
|
|
199
|
+
| {
|
|
200
|
+
type: "compaction";
|
|
201
|
+
phase: "start" | "end";
|
|
202
|
+
reason: "manual" | "threshold" | "overflow";
|
|
203
|
+
error?: string;
|
|
204
|
+
aborted?: boolean;
|
|
205
|
+
}
|
|
197
206
|
| { type: "retry"; attempt: number; maxAttempts: number; delayMs: number; message: string }
|
|
198
207
|
| { type: "queue"; steering: string[]; followUp: string[] }
|
|
199
208
|
| { type: "notice"; level: "info" | "warning" | "error"; message: string }
|
|
@@ -255,6 +264,7 @@ export const codeAgentEventPersistence: { [key in CodeAgentEventType]: "live" |
|
|
|
255
264
|
tool_end: "persist",
|
|
256
265
|
question: "persist",
|
|
257
266
|
question_resolved: "persist",
|
|
267
|
+
question_skipped: "persist",
|
|
258
268
|
approval: "live",
|
|
259
269
|
approval_resolved: "live",
|
|
260
270
|
context: "live",
|
|
@@ -393,14 +403,18 @@ export const codeAgentEventLabel = (event: CodeAgentEventBody): string => {
|
|
|
393
403
|
return `? ${event.question.prompt}`;
|
|
394
404
|
case "question_resolved":
|
|
395
405
|
return `= ${event.rendered}`;
|
|
406
|
+
case "question_skipped":
|
|
407
|
+
return `? ${event.question.prompt} (skipped: ${event.reason})`;
|
|
396
408
|
case "approval":
|
|
397
409
|
return `approve? ${event.request.summary}`;
|
|
398
410
|
case "approval_resolved":
|
|
399
411
|
return event.approved ? "approved" : "denied";
|
|
400
412
|
case "context":
|
|
401
413
|
return `context ${event.used}${event.max ? `/${event.max}` : ""}`;
|
|
402
|
-
case "compaction":
|
|
403
|
-
|
|
414
|
+
case "compaction": {
|
|
415
|
+
const outcome = event.error ? ` — ${event.error}` : event.aborted ? " — cancelled" : "";
|
|
416
|
+
return `compaction ${event.phase} (${event.reason})${outcome}`;
|
|
417
|
+
}
|
|
404
418
|
case "retry":
|
|
405
419
|
return `retry ${event.attempt}/${event.maxAttempts} in ${event.delayMs}ms — ${event.message}`;
|
|
406
420
|
case "queue":
|
package/constant/getDefault.ts
CHANGED
|
@@ -5,7 +5,10 @@ import type { DefaultOf } from "./types";
|
|
|
5
5
|
export interface DefaultPlan {
|
|
6
6
|
/** Fields whose default is a value that can be shared: a primitive, `null`, or the field's own literal. */
|
|
7
7
|
shared: Record<string, unknown>;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Fields that have to be produced per call — a thunk, a fresh array, a nested scalar record, or a primitive's
|
|
10
|
+
* structured default.
|
|
11
|
+
*/
|
|
9
12
|
perCall: Map<string, () => unknown>;
|
|
10
13
|
}
|
|
11
14
|
|
|
@@ -49,7 +52,23 @@ const buildPlan = (fieldObj: FieldObject): DefaultPlan => {
|
|
|
49
52
|
else if (field.isClass) {
|
|
50
53
|
if (field.isScalar) perCall.set(key, () => getDefault(field.modelRef[FIELD_META]));
|
|
51
54
|
else shared[key] = null;
|
|
52
|
-
} else
|
|
55
|
+
} else {
|
|
56
|
+
const primitiveDefault = (field.modelRef as unknown as typeof PrimitiveScalar)[DEFAULT_VALUE];
|
|
57
|
+
if (isStructured(primitiveDefault)) perCall.set(key, () => structuredClone(primitiveDefault));
|
|
58
|
+
else shared[key] = primitiveDefault;
|
|
59
|
+
}
|
|
53
60
|
}
|
|
54
61
|
return { shared, perCall };
|
|
55
62
|
};
|
|
63
|
+
|
|
64
|
+
const isStructured = (value: unknown): value is object =>
|
|
65
|
+
typeof value === "object" &&
|
|
66
|
+
value !== null &&
|
|
67
|
+
(Array.isArray(value) || Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A primitive's value is never an identity, so a plain object or array — an empty editor document as a primitive's
|
|
71
|
+
* `DEFAULT_VALUE` — is copied for each use, for the reason an array field default is. An instance (a `Dayjs`, a
|
|
72
|
+
* `Uint8Array`) is handed back as is: its own API is how it changes, and a structured copy would drop its prototype.
|
|
73
|
+
*/
|
|
74
|
+
export const freshPrimitiveValue = <T>(value: T): T => (isStructured(value) ? structuredClone(value) : value);
|
package/constant/mask.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FIELD_META } from "akanjs/base";
|
|
1
|
+
import { type Cls, FIELD_META, getNonArrayModel, type PrimitiveAgentFace, PrimitiveRegistry } from "akanjs/base";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* A model as masking reads it — the constructor, for the field metadata it carries at runtime.
|
|
@@ -14,7 +14,10 @@ export interface MaskModel {
|
|
|
14
14
|
interface MaskField {
|
|
15
15
|
fieldType?: string;
|
|
16
16
|
isClass?: boolean;
|
|
17
|
+
isMap?: boolean;
|
|
17
18
|
modelRef?: MaskModel;
|
|
19
|
+
of?: unknown;
|
|
20
|
+
arrDepth?: number;
|
|
18
21
|
visual?: boolean;
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -40,7 +43,8 @@ export const leakingFieldsOf = (model: MaskModel, value: Record<string, unknown>
|
|
|
40
43
|
/**
|
|
41
44
|
* Strips what a model marks `hidden`, `secret`, or `visual`, by the model the caller names rather than by the one
|
|
42
45
|
* the value happens to still carry. The first two are secrecy and the third is cost, but the answer is the same
|
|
43
|
-
* one — leave the field out — and this is the only place every AI-facing read already passes through.
|
|
46
|
+
* one — leave the field out — and this is the only place every AI-facing read already passes through. For the same
|
|
47
|
+
* reason it is where a primitive declaring an agent face is read into that face (`agentRead`).
|
|
44
48
|
*
|
|
45
49
|
* That distinction is the whole point. A check that reads the class off the value can only mask what arrives as an
|
|
46
50
|
* instance, so a `{ ...doc }` spread, a `toJSON()`, an `immerify()`, or a round-trip through `JSON.stringify` reaches
|
|
@@ -61,11 +65,39 @@ export const mask = (model: MaskModel, value: unknown): unknown => {
|
|
|
61
65
|
const masked: Record<string, unknown> = {};
|
|
62
66
|
for (const [key, field] of Object.entries(fields)) {
|
|
63
67
|
if (field.fieldType === "hidden" || field.fieldType === "secret" || field.visual || !(key in source)) continue;
|
|
64
|
-
masked[key] =
|
|
68
|
+
masked[key] = maskField(field, source[key]);
|
|
65
69
|
}
|
|
66
70
|
return masked;
|
|
67
71
|
};
|
|
68
72
|
|
|
73
|
+
/**
|
|
74
|
+
* What an agent reads of a primitive value: the primitive's `agent.read` when it declares an agent face, the value
|
|
75
|
+
* untouched otherwise. The read is applied through `arrDepth` levels of array, the way a field declares them.
|
|
76
|
+
*/
|
|
77
|
+
export const agentRead = (modelRef: unknown, value: unknown, arrDepth = 0): unknown => {
|
|
78
|
+
const face = PrimitiveRegistry.agentOf(modelRef);
|
|
79
|
+
return face ? readThrough(face, value, arrDepth) : value;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const readThrough = (face: PrimitiveAgentFace, value: unknown, arrDepth: number): unknown => {
|
|
83
|
+
if (value === null || value === undefined) return value;
|
|
84
|
+
if (arrDepth > 0 && Array.isArray(value)) return value.map((item) => readThrough(face, item, arrDepth - 1));
|
|
85
|
+
return face.read(value);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const maskField = (field: MaskField, value: unknown): unknown => {
|
|
89
|
+
if (field.isClass && field.modelRef) return mask(field.modelRef, value);
|
|
90
|
+
if (field.isMap) return maskMapValues(field.of, value);
|
|
91
|
+
return agentRead(field.modelRef, value, field.arrDepth ?? 0);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const maskMapValues = (of: unknown, value: unknown): unknown => {
|
|
95
|
+
const [valueRef, arrDepth] = getNonArrayModel(of as Cls);
|
|
96
|
+
if (!PrimitiveRegistry.agentOf(valueRef) || value === null || typeof value !== "object") return value;
|
|
97
|
+
const entries = value instanceof Map ? [...value.entries()] : Object.entries(value);
|
|
98
|
+
return Object.fromEntries(entries.map(([key, item]) => [key, agentRead(valueRef, item, arrDepth)]));
|
|
99
|
+
};
|
|
100
|
+
|
|
69
101
|
/**
|
|
70
102
|
* Drops what a model marks `hidden` or `secret`, and nothing else.
|
|
71
103
|
*
|
|
@@ -29,4 +29,13 @@ export const agentDictionary = serviceDictionary(["en", "ko"])
|
|
|
29
29
|
"{provider} refused this turn with status {status}. Reason: {reason}",
|
|
30
30
|
"{provider}가 이번 턴을 거절했습니다 (status {status}). 사유: {reason}",
|
|
31
31
|
],
|
|
32
|
+
|
|
33
|
+
contextOverflow: [
|
|
34
|
+
"This conversation no longer fits the model's context window at {provider}. Use /compact to summarize it, or /new to start over",
|
|
35
|
+
"대화가 {provider} 모델의 컨텍스트 창을 넘었습니다. /compact로 요약하거나 /new로 새로 시작할 수 있습니다.",
|
|
36
|
+
],
|
|
37
|
+
quotaExceeded: [
|
|
38
|
+
"The agent's usage limit for this account has been reached",
|
|
39
|
+
"이 계정의 에이전트 사용 한도에 도달했습니다.",
|
|
40
|
+
],
|
|
32
41
|
});
|
|
@@ -109,6 +109,11 @@ export const baseDictionary = serviceDictionary(["en", "ko"])
|
|
|
109
109
|
agentToolRunning: ["Running", "실행 중"],
|
|
110
110
|
agentToolResult: ["Show what this tool returned", "이 툴이 반환한 값 보기"],
|
|
111
111
|
agentTokens: ["~{count} tokens", "약 {count} 토큰"],
|
|
112
|
+
agentTokensOf: ["~{count} / {limit} tokens", "약 {count} / {limit} 토큰"],
|
|
113
|
+
agentCompactsAt: [
|
|
114
|
+
"The conversation summarizes itself past {limit} tokens",
|
|
115
|
+
"{limit} 토큰을 넘으면 대화를 스스로 요약합니다",
|
|
116
|
+
],
|
|
112
117
|
agentSummarizing: ["Summarizing the conversation…", "대화를 요약하는 중…"],
|
|
113
118
|
agentContinue: ["This is taking a while. Keep going?", "시간이 걸리고 있습니다. 계속할까요?"],
|
|
114
119
|
agentKeepGoing: ["Keep going", "계속하기"],
|
package/document/database.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MergedValues, PromiseOrObject } from "akanjs/base";
|
|
2
2
|
import { Logger } from "akanjs/common";
|
|
3
3
|
import type { DocumentModel, QueryOf } from "akanjs/constant";
|
|
4
|
-
import type { CacheAdaptor, CacheSetOptions } from "akanjs/service";
|
|
4
|
+
import type { CacheAdaptor, CacheSetOptions, CacheValue } from "akanjs/service";
|
|
5
5
|
import type { DataLoader } from "./dataLoader";
|
|
6
6
|
import type { DocumentUpdateInput } from "./documentQuery";
|
|
7
7
|
import type { ExtractQuery, ExtractSort, FilterInstance } from "./filterMeta";
|
|
@@ -16,15 +16,51 @@ export class CacheDatabase<T = unknown> {
|
|
|
16
16
|
) {
|
|
17
17
|
this.logger = new Logger(`${refName}Cache`);
|
|
18
18
|
}
|
|
19
|
-
async set(topic: string, key: string, value:
|
|
19
|
+
async set(topic: string, key: string, value: CacheValue, option: CacheSetOptions = {}) {
|
|
20
20
|
await this.cache.set(this.refName, `${topic}:${key}`, value, option);
|
|
21
21
|
}
|
|
22
|
-
async get<T extends
|
|
22
|
+
async get<T extends CacheValue = CacheValue>(topic: string, key: string): Promise<T | undefined> {
|
|
23
23
|
return await this.cache.get<T>(this.refName, `${topic}:${key}`);
|
|
24
24
|
}
|
|
25
25
|
async delete(topic: string, key: string) {
|
|
26
26
|
await this.cache.delete(this.refName, `${topic}:${key}`);
|
|
27
27
|
}
|
|
28
|
+
async getDel<T extends CacheValue = CacheValue>(topic: string, key: string): Promise<T | undefined> {
|
|
29
|
+
return await this.cache.getDel<T>(this.refName, `${topic}:${key}`);
|
|
30
|
+
}
|
|
31
|
+
async setIfAbsent(topic: string, key: string, value: CacheValue, option: CacheSetOptions = {}) {
|
|
32
|
+
return await this.cache.setIfAbsent(this.refName, `${topic}:${key}`, value, option);
|
|
33
|
+
}
|
|
34
|
+
async incr(topic: string, key: string, by = 1, option: CacheSetOptions = {}) {
|
|
35
|
+
return await this.cache.incr(this.refName, `${topic}:${key}`, by, option);
|
|
36
|
+
}
|
|
37
|
+
async hset(topic: string, key: string, subKey: string, value: CacheValue, option: CacheSetOptions = {}) {
|
|
38
|
+
await this.cache.hset(this.refName, `${topic}:${key}`, subKey, value, option);
|
|
39
|
+
}
|
|
40
|
+
async hget<T extends CacheValue = CacheValue>(topic: string, key: string, subKey: string): Promise<T | undefined> {
|
|
41
|
+
return await this.cache.hget<T>(this.refName, `${topic}:${key}`, subKey);
|
|
42
|
+
}
|
|
43
|
+
async hdelete(topic: string, key: string, subKey: string) {
|
|
44
|
+
await this.cache.hdelete(this.refName, `${topic}:${key}`, subKey);
|
|
45
|
+
}
|
|
46
|
+
async hkeys(topic: string, key: string) {
|
|
47
|
+
return await this.cache.hkeys(this.refName, `${topic}:${key}`);
|
|
48
|
+
}
|
|
49
|
+
async hentries<T extends CacheValue = CacheValue>(topic: string, key: string): Promise<[string, T][]> {
|
|
50
|
+
return await this.cache.hentries<T>(this.refName, `${topic}:${key}`);
|
|
51
|
+
}
|
|
52
|
+
async hclear(topic: string, key: string) {
|
|
53
|
+
await this.cache.hclear(this.refName, `${topic}:${key}`);
|
|
54
|
+
}
|
|
55
|
+
async hgetDel<T extends CacheValue = CacheValue>(topic: string, key: string, subKey: string): Promise<T | undefined> {
|
|
56
|
+
return await this.cache.hgetDel<T>(this.refName, `${topic}:${key}`, subKey);
|
|
57
|
+
}
|
|
58
|
+
async hsetIfAbsent(topic: string, key: string, subKey: string, value: CacheValue, option: CacheSetOptions = {}) {
|
|
59
|
+
return await this.cache.hsetIfAbsent(this.refName, `${topic}:${key}`, subKey, value, option);
|
|
60
|
+
}
|
|
61
|
+
async hincr(topic: string, key: string, subKey: string, by = 1, option: CacheSetOptions = {}) {
|
|
62
|
+
return await this.cache.hincr(this.refName, `${topic}:${key}`, subKey, by, option);
|
|
63
|
+
}
|
|
28
64
|
}
|
|
29
65
|
/**
|
|
30
66
|
* What `update<Filter>` returns. The patch cannot be a trailing parameter — a filter's own args may be optional,
|
|
@@ -217,7 +217,12 @@ export class DocumentQueryEvaluator {
|
|
|
217
217
|
return this.#has(read, operand);
|
|
218
218
|
case "contains":
|
|
219
219
|
|
|
220
|
-
return
|
|
220
|
+
return (
|
|
221
|
+
read.value !== null &&
|
|
222
|
+
DocumentQueryEvaluator.#foldAscii(String(read.value)).includes(
|
|
223
|
+
DocumentQueryEvaluator.#foldAscii(String(operand)),
|
|
224
|
+
)
|
|
225
|
+
);
|
|
221
226
|
}
|
|
222
227
|
}
|
|
223
228
|
|
|
@@ -313,6 +318,10 @@ export class DocumentQueryEvaluator {
|
|
|
313
318
|
return leftPoints.length === rightPoints.length ? 0 : leftPoints.length < rightPoints.length ? -1 : 1;
|
|
314
319
|
}
|
|
315
320
|
|
|
321
|
+
static #foldAscii(text: string) {
|
|
322
|
+
return text.replace(/[A-Z]/g, (char) => char.toLowerCase());
|
|
323
|
+
}
|
|
324
|
+
|
|
316
325
|
static #isNode(value: unknown): value is DocumentQueryNode {
|
|
317
326
|
return !!value && typeof value === "object" && "kind" in value;
|
|
318
327
|
}
|
package/index.ts
CHANGED
|
@@ -229,9 +229,18 @@ export interface AkanApiConfig {
|
|
|
229
229
|
websocketPrefix: string;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
export interface AkanDatabaseConfig {
|
|
233
|
+
/**
|
|
234
|
+
* The modes this app's build can run in. `akan build` bundles the drivers of each, the image lets a deployment
|
|
235
|
+
* pick one of them with `AKAN_DATABASE_MODE` and no other, and `akan start` runs the first unless the shell names
|
|
236
|
+
* another. A deployment of a build carrying several has to name one.
|
|
237
|
+
*/
|
|
238
|
+
modes: DatabaseMode[];
|
|
239
|
+
}
|
|
240
|
+
|
|
232
241
|
export interface AppConfigResult {
|
|
233
242
|
docker: DockerConfig;
|
|
234
|
-
|
|
243
|
+
database: AkanDatabaseConfig;
|
|
235
244
|
/**
|
|
236
245
|
* Where this app mounts its endpoints. Declared here rather than only in `main.ts` because the value is baked
|
|
237
246
|
* into every client bundle: a prebuilt CSR shell or a mobile bundle never reaches the server that would tell
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[crossTest] 58035 - 09/25/2026, 16:51:41 PM VERBOSE crossTest is serving on port 47811 +114ms
|
|
2
|
+
[crossTest] 58035 - 09/25/2026, 16:51:41 PM VERBOSE 🚀 crossTest is running on port 47811 +117ms
|
|
3
|
+
[scheduler] 58035 - 09/25/2026, 16:52:41 PM DEBUG Schedule interval searchIndexRetry finished 2ms +60110ms
|
|
4
|
+
[scheduler] 58035 - 09/25/2026, 16:53:41 PM DEBUG Schedule interval searchIndexRetry finished 1ms +120110ms
|
|
5
|
+
[crossTest] 58035 - 09/25/2026, 16:53:57 PM DEBUG Received SIGTERM, starting graceful shutdown... +135947ms
|
|
6
|
+
[crossTest] 58035 - 09/25/2026, 16:53:57 PM INFO Shutting down gracefully... +135947ms
|
|
7
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Running destroy internals... +135947ms
|
|
8
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroy internals in 1ms +135948ms
|
|
9
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroying services... +135948ms
|
|
10
|
+
[BaseService] 58035 - 09/25/2026, 16:53:57 PM VERBOSE base service destroying... +135948ms
|
|
11
|
+
[AgentService] 58035 - 09/25/2026, 16:53:57 PM VERBOSE agent service destroying... +135948ms
|
|
12
|
+
[CrossItemService] 58035 - 09/25/2026, 16:53:57 PM VERBOSE crossItem service destroying... +135948ms
|
|
13
|
+
[BaseService] 58035 - 09/25/2026, 16:53:57 PM VERBOSE base service destroyed in 0ms +135948ms
|
|
14
|
+
[AgentService] 58035 - 09/25/2026, 16:53:57 PM VERBOSE agent service destroyed in 0ms +135948ms
|
|
15
|
+
[CrossItemService] 58035 - 09/25/2026, 16:53:57 PM VERBOSE crossItem service destroyed in 0ms +135948ms
|
|
16
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroy services in 0ms +135948ms
|
|
17
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroying adaptors... +135948ms
|
|
18
|
+
[crossItemModel] 58035 - 09/25/2026, 16:53:57 PM VERBOSE crossItemModel adaptor destroying... +135948ms
|
|
19
|
+
[crossItemModel] 58035 - 09/25/2026, 16:53:57 PM VERBOSE crossItemModel adaptor destroyed in 0ms +135948ms
|
|
20
|
+
[sqliteDatabase] 58035 - 09/25/2026, 16:53:57 PM VERBOSE sqliteDatabase adaptor destroying... +135948ms
|
|
21
|
+
[sqliteDatabase] 58035 - 09/25/2026, 16:53:57 PM VERBOSE sqliteDatabase adaptor destroyed in 5ms +135953ms
|
|
22
|
+
[bullQueue] 58035 - 09/25/2026, 16:53:57 PM VERBOSE bullQueue adaptor destroying... +135953ms
|
|
23
|
+
[scheduler] 58035 - 09/25/2026, 16:53:57 PM VERBOSE scheduler adaptor destroying... +135953ms
|
|
24
|
+
[wsRedis] 58035 - 09/25/2026, 16:53:57 PM VERBOSE wsRedis adaptor destroying... +135953ms
|
|
25
|
+
[scheduler] 58035 - 09/25/2026, 16:53:57 PM VERBOSE scheduler adaptor destroyed in 0ms +135953ms
|
|
26
|
+
[bullQueue] 58035 - 09/25/2026, 16:53:57 PM VERBOSE bullQueue adaptor destroyed in 0ms +135953ms
|
|
27
|
+
[wsRedis] 58035 - 09/25/2026, 16:53:57 PM VERBOSE WebSocket Redis adaptor destroyed +135957ms
|
|
28
|
+
[wsRedis] 58035 - 09/25/2026, 16:53:57 PM VERBOSE wsRedis adaptor destroyed in 4ms +135957ms
|
|
29
|
+
[redisCache] 58035 - 09/25/2026, 16:53:57 PM VERBOSE redisCache adaptor destroying... +135957ms
|
|
30
|
+
[blobStorage] 58035 - 09/25/2026, 16:53:57 PM VERBOSE blobStorage adaptor destroying... +135957ms
|
|
31
|
+
[consoleLogger] 58035 - 09/25/2026, 16:53:57 PM VERBOSE consoleLogger adaptor destroying... +135957ms
|
|
32
|
+
[jsonCompressor] 58035 - 09/25/2026, 16:53:57 PM VERBOSE jsonCompressor adaptor destroying... +135957ms
|
|
33
|
+
[openaiLlm] 58035 - 09/25/2026, 16:53:57 PM VERBOSE openaiLlm adaptor destroying... +135957ms
|
|
34
|
+
[llmAdaptorRole] 58035 - 09/25/2026, 16:53:57 PM VERBOSE llmAdaptorRole adaptor destroying... +135957ms
|
|
35
|
+
[redisCache] 58035 - 09/25/2026, 16:53:57 PM VERBOSE redisCache adaptor destroyed in 0ms +135957ms
|
|
36
|
+
[blobStorage] 58035 - 09/25/2026, 16:53:57 PM VERBOSE blobStorage adaptor destroyed in 0ms +135957ms
|
|
37
|
+
[consoleLogger] 58035 - 09/25/2026, 16:53:57 PM VERBOSE consoleLogger adaptor destroyed in 0ms +135957ms
|
|
38
|
+
[jsonCompressor] 58035 - 09/25/2026, 16:53:57 PM VERBOSE jsonCompressor adaptor destroyed in 0ms +135957ms
|
|
39
|
+
[openaiLlm] 58035 - 09/25/2026, 16:53:57 PM VERBOSE openaiLlm adaptor destroyed in 0ms +135957ms
|
|
40
|
+
[llmAdaptorRole] 58035 - 09/25/2026, 16:53:57 PM VERBOSE llmAdaptorRole adaptor destroyed in 0ms +135957ms
|
|
41
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroy adaptors in 9ms +135957ms
|
|
42
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroying uses... +135957ms
|
|
43
|
+
[DiLifecycle] 58035 - 09/25/2026, 16:53:57 PM VERBOSE Destroy uses in 0ms +135957ms
|
|
44
|
+
[crossTest] 58035 - 09/25/2026, 16:53:57 PM INFO Shutdown completed successfully in 10ms +135957ms
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[crossTest] 59872 - 09/25/2026, 16:53:58 PM VERBOSE crossTest is serving on port 47811 +109ms
|
|
2
|
+
[crossTest] 59872 - 09/25/2026, 16:53:58 PM VERBOSE 🚀 crossTest is running on port 47811 +112ms
|
|
3
|
+
[crossTest] 59872 - 09/25/2026, 16:54:10 PM DEBUG Received SIGTERM, starting graceful shutdown... +11999ms
|
|
4
|
+
[crossTest] 59872 - 09/25/2026, 16:54:10 PM INFO Shutting down gracefully... +11999ms
|
|
5
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Running destroy internals... +12000ms
|
|
6
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroy internals in 0ms +12000ms
|
|
7
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroying services... +12000ms
|
|
8
|
+
[BaseService] 59872 - 09/25/2026, 16:54:10 PM VERBOSE base service destroying... +12000ms
|
|
9
|
+
[AgentService] 59872 - 09/25/2026, 16:54:10 PM VERBOSE agent service destroying... +12000ms
|
|
10
|
+
[CrossItemService] 59872 - 09/25/2026, 16:54:10 PM VERBOSE crossItem service destroying... +12000ms
|
|
11
|
+
[BaseService] 59872 - 09/25/2026, 16:54:10 PM VERBOSE base service destroyed in 0ms +12000ms
|
|
12
|
+
[AgentService] 59872 - 09/25/2026, 16:54:10 PM VERBOSE agent service destroyed in 0ms +12000ms
|
|
13
|
+
[CrossItemService] 59872 - 09/25/2026, 16:54:10 PM VERBOSE crossItem service destroyed in 0ms +12000ms
|
|
14
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroy services in 0ms +12000ms
|
|
15
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroying adaptors... +12000ms
|
|
16
|
+
[crossItemModel] 59872 - 09/25/2026, 16:54:10 PM VERBOSE crossItemModel adaptor destroying... +12000ms
|
|
17
|
+
[crossItemModel] 59872 - 09/25/2026, 16:54:10 PM VERBOSE crossItemModel adaptor destroyed in 0ms +12000ms
|
|
18
|
+
[sqliteDatabase] 59872 - 09/25/2026, 16:54:10 PM VERBOSE sqliteDatabase adaptor destroying... +12000ms
|
|
19
|
+
[sqliteDatabase] 59872 - 09/25/2026, 16:54:10 PM VERBOSE sqliteDatabase adaptor destroyed in 5ms +12005ms
|
|
20
|
+
[bullQueue] 59872 - 09/25/2026, 16:54:10 PM VERBOSE bullQueue adaptor destroying... +12005ms
|
|
21
|
+
[scheduler] 59872 - 09/25/2026, 16:54:10 PM VERBOSE scheduler adaptor destroying... +12005ms
|
|
22
|
+
[wsRedis] 59872 - 09/25/2026, 16:54:10 PM VERBOSE wsRedis adaptor destroying... +12005ms
|
|
23
|
+
[scheduler] 59872 - 09/25/2026, 16:54:10 PM VERBOSE scheduler adaptor destroyed in 1ms +12006ms
|
|
24
|
+
[bullQueue] 59872 - 09/25/2026, 16:54:10 PM VERBOSE bullQueue adaptor destroyed in 1ms +12006ms
|
|
25
|
+
[wsRedis] 59872 - 09/25/2026, 16:54:10 PM VERBOSE WebSocket Redis adaptor destroyed +12010ms
|
|
26
|
+
[wsRedis] 59872 - 09/25/2026, 16:54:10 PM VERBOSE wsRedis adaptor destroyed in 5ms +12010ms
|
|
27
|
+
[redisCache] 59872 - 09/25/2026, 16:54:10 PM VERBOSE redisCache adaptor destroying... +12010ms
|
|
28
|
+
[blobStorage] 59872 - 09/25/2026, 16:54:10 PM VERBOSE blobStorage adaptor destroying... +12010ms
|
|
29
|
+
[consoleLogger] 59872 - 09/25/2026, 16:54:10 PM VERBOSE consoleLogger adaptor destroying... +12010ms
|
|
30
|
+
[jsonCompressor] 59872 - 09/25/2026, 16:54:10 PM VERBOSE jsonCompressor adaptor destroying... +12010ms
|
|
31
|
+
[openaiLlm] 59872 - 09/25/2026, 16:54:10 PM VERBOSE openaiLlm adaptor destroying... +12010ms
|
|
32
|
+
[llmAdaptorRole] 59872 - 09/25/2026, 16:54:10 PM VERBOSE llmAdaptorRole adaptor destroying... +12010ms
|
|
33
|
+
[redisCache] 59872 - 09/25/2026, 16:54:10 PM VERBOSE redisCache adaptor destroyed in 0ms +12010ms
|
|
34
|
+
[blobStorage] 59872 - 09/25/2026, 16:54:10 PM VERBOSE blobStorage adaptor destroyed in 0ms +12010ms
|
|
35
|
+
[consoleLogger] 59872 - 09/25/2026, 16:54:10 PM VERBOSE consoleLogger adaptor destroyed in 0ms +12010ms
|
|
36
|
+
[jsonCompressor] 59872 - 09/25/2026, 16:54:10 PM VERBOSE jsonCompressor adaptor destroyed in 0ms +12010ms
|
|
37
|
+
[openaiLlm] 59872 - 09/25/2026, 16:54:10 PM VERBOSE openaiLlm adaptor destroyed in 0ms +12010ms
|
|
38
|
+
[llmAdaptorRole] 59872 - 09/25/2026, 16:54:10 PM VERBOSE llmAdaptorRole adaptor destroyed in 0ms +12010ms
|
|
39
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroy adaptors in 10ms +12010ms
|
|
40
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroying uses... +12010ms
|
|
41
|
+
[DiLifecycle] 59872 - 09/25/2026, 16:54:10 PM VERBOSE Destroy uses in 0ms +12010ms
|
|
42
|
+
[crossTest] 59872 - 09/25/2026, 16:54:10 PM INFO Shutdown completed successfully in 11ms +12010ms
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[crossTest] 60280 - 09/25/2026, 16:54:26 PM VERBOSE crossTest is serving on port 47811 +111ms
|
|
2
|
+
[crossTest] 60280 - 09/25/2026, 16:54:26 PM VERBOSE 🚀 crossTest is running on port 47811 +114ms
|
|
3
|
+
[scheduler] 60280 - 09/25/2026, 16:55:26 PM DEBUG Schedule interval searchIndexRetry finished 3ms +60108ms
|
|
4
|
+
[crossTest] 60280 - 09/25/2026, 16:56:12 PM DEBUG Received SIGTERM, starting graceful shutdown... +105905ms
|
|
5
|
+
[crossTest] 60280 - 09/25/2026, 16:56:12 PM INFO Shutting down gracefully... +105905ms
|
|
6
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Running destroy internals... +105905ms
|
|
7
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroy internals in 0ms +105905ms
|
|
8
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroying services... +105905ms
|
|
9
|
+
[BaseService] 60280 - 09/25/2026, 16:56:12 PM VERBOSE base service destroying... +105906ms
|
|
10
|
+
[AgentService] 60280 - 09/25/2026, 16:56:12 PM VERBOSE agent service destroying... +105906ms
|
|
11
|
+
[CrossItemService] 60280 - 09/25/2026, 16:56:12 PM VERBOSE crossItem service destroying... +105906ms
|
|
12
|
+
[BaseService] 60280 - 09/25/2026, 16:56:12 PM VERBOSE base service destroyed in 0ms +105906ms
|
|
13
|
+
[AgentService] 60280 - 09/25/2026, 16:56:12 PM VERBOSE agent service destroyed in 0ms +105906ms
|
|
14
|
+
[CrossItemService] 60280 - 09/25/2026, 16:56:12 PM VERBOSE crossItem service destroyed in 0ms +105906ms
|
|
15
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroy services in 1ms +105906ms
|
|
16
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroying adaptors... +105906ms
|
|
17
|
+
[crossItemModel] 60280 - 09/25/2026, 16:56:12 PM VERBOSE crossItemModel adaptor destroying... +105906ms
|
|
18
|
+
[crossItemModel] 60280 - 09/25/2026, 16:56:12 PM VERBOSE crossItemModel adaptor destroyed in 0ms +105906ms
|
|
19
|
+
[sqliteDatabase] 60280 - 09/25/2026, 16:56:12 PM VERBOSE sqliteDatabase adaptor destroying... +105906ms
|
|
20
|
+
[sqliteDatabase] 60280 - 09/25/2026, 16:56:12 PM VERBOSE sqliteDatabase adaptor destroyed in 4ms +105910ms
|
|
21
|
+
[bullQueue] 60280 - 09/25/2026, 16:56:12 PM VERBOSE bullQueue adaptor destroying... +105910ms
|
|
22
|
+
[scheduler] 60280 - 09/25/2026, 16:56:12 PM VERBOSE scheduler adaptor destroying... +105910ms
|
|
23
|
+
[wsRedis] 60280 - 09/25/2026, 16:56:12 PM VERBOSE wsRedis adaptor destroying... +105910ms
|
|
24
|
+
[scheduler] 60280 - 09/25/2026, 16:56:12 PM VERBOSE scheduler adaptor destroyed in 1ms +105911ms
|
|
25
|
+
[bullQueue] 60280 - 09/25/2026, 16:56:12 PM VERBOSE bullQueue adaptor destroyed in 1ms +105911ms
|
|
26
|
+
[wsRedis] 60280 - 09/25/2026, 16:56:12 PM VERBOSE WebSocket Redis adaptor destroyed +105912ms
|
|
27
|
+
[wsRedis] 60280 - 09/25/2026, 16:56:12 PM VERBOSE wsRedis adaptor destroyed in 2ms +105912ms
|
|
28
|
+
[redisCache] 60280 - 09/25/2026, 16:56:12 PM VERBOSE redisCache adaptor destroying... +105912ms
|
|
29
|
+
[blobStorage] 60280 - 09/25/2026, 16:56:12 PM VERBOSE blobStorage adaptor destroying... +105912ms
|
|
30
|
+
[consoleLogger] 60280 - 09/25/2026, 16:56:12 PM VERBOSE consoleLogger adaptor destroying... +105912ms
|
|
31
|
+
[jsonCompressor] 60280 - 09/25/2026, 16:56:12 PM VERBOSE jsonCompressor adaptor destroying... +105912ms
|
|
32
|
+
[openaiLlm] 60280 - 09/25/2026, 16:56:12 PM VERBOSE openaiLlm adaptor destroying... +105912ms
|
|
33
|
+
[llmAdaptorRole] 60280 - 09/25/2026, 16:56:12 PM VERBOSE llmAdaptorRole adaptor destroying... +105912ms
|
|
34
|
+
[redisCache] 60280 - 09/25/2026, 16:56:12 PM VERBOSE redisCache adaptor destroyed in 0ms +105912ms
|
|
35
|
+
[blobStorage] 60280 - 09/25/2026, 16:56:12 PM VERBOSE blobStorage adaptor destroyed in 0ms +105912ms
|
|
36
|
+
[consoleLogger] 60280 - 09/25/2026, 16:56:12 PM VERBOSE consoleLogger adaptor destroyed in 0ms +105912ms
|
|
37
|
+
[jsonCompressor] 60280 - 09/25/2026, 16:56:12 PM VERBOSE jsonCompressor adaptor destroyed in 0ms +105912ms
|
|
38
|
+
[openaiLlm] 60280 - 09/25/2026, 16:56:12 PM VERBOSE openaiLlm adaptor destroyed in 1ms +105913ms
|
|
39
|
+
[llmAdaptorRole] 60280 - 09/25/2026, 16:56:12 PM VERBOSE llmAdaptorRole adaptor destroyed in 1ms +105913ms
|
|
40
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroy adaptors in 7ms +105913ms
|
|
41
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroying uses... +105913ms
|
|
42
|
+
[DiLifecycle] 60280 - 09/25/2026, 16:56:12 PM VERBOSE Destroy uses in 0ms +105913ms
|
|
43
|
+
[crossTest] 60280 - 09/25/2026, 16:56:12 PM INFO Shutdown completed successfully in 8ms +105913ms
|