@askdkc/kiokuko 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ja.md +112 -0
- package/README.ko.md +112 -0
- package/README.md +147 -0
- package/README.zh-CN.md +112 -0
- package/dist/agent-file/atomic-write.d.ts +6 -0
- package/dist/agent-file/atomic-write.d.ts.map +1 -0
- package/dist/agent-file/atomic-write.js +36 -0
- package/dist/agent-file/atomic-write.js.map +1 -0
- package/dist/agent-file/managed-block.d.ts +12 -0
- package/dist/agent-file/managed-block.d.ts.map +1 -0
- package/dist/agent-file/managed-block.js +56 -0
- package/dist/agent-file/managed-block.js.map +1 -0
- package/dist/agent-file/render.d.ts +14 -0
- package/dist/agent-file/render.d.ts.map +1 -0
- package/dist/agent-file/render.js +41 -0
- package/dist/agent-file/render.js.map +1 -0
- package/dist/akinator/domain.d.ts +25 -0
- package/dist/akinator/domain.d.ts.map +1 -0
- package/dist/akinator/domain.js +255 -0
- package/dist/akinator/domain.js.map +1 -0
- package/dist/akinator/orchestrator.d.ts +8 -0
- package/dist/akinator/orchestrator.d.ts.map +1 -0
- package/dist/akinator/orchestrator.js +11 -0
- package/dist/akinator/orchestrator.js.map +1 -0
- package/dist/akinator/service.d.ts +35 -0
- package/dist/akinator/service.d.ts.map +1 -0
- package/dist/akinator/service.js +296 -0
- package/dist/akinator/service.js.map +1 -0
- package/dist/akinator/store.d.ts +96 -0
- package/dist/akinator/store.d.ts.map +1 -0
- package/dist/akinator/store.js +583 -0
- package/dist/akinator/store.js.map +1 -0
- package/dist/akinator/types.d.ts +49 -0
- package/dist/akinator/types.d.ts.map +1 -0
- package/dist/akinator/types.js +2 -0
- package/dist/akinator/types.js.map +1 -0
- package/dist/bin/kiokuko.d.ts +3 -0
- package/dist/bin/kiokuko.d.ts.map +1 -0
- package/dist/bin/kiokuko.js +6 -0
- package/dist/bin/kiokuko.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +362 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/runtime-discovery.d.ts +15 -0
- package/dist/client/runtime-discovery.d.ts.map +1 -0
- package/dist/client/runtime-discovery.js +45 -0
- package/dist/client/runtime-discovery.js.map +1 -0
- package/dist/client/server-client.d.ts +20 -0
- package/dist/client/server-client.d.ts.map +1 -0
- package/dist/client/server-client.js +424 -0
- package/dist/client/server-client.js.map +1 -0
- package/dist/commands/agent.d.ts +10 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +283 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/backup.d.ts +5 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +14 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/call.d.ts +7 -0
- package/dist/commands/call.d.ts.map +1 -0
- package/dist/commands/call.js +10 -0
- package/dist/commands/call.js.map +1 -0
- package/dist/commands/doctor.d.ts +31 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +142 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/export.d.ts +21 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +68 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/import.d.ts +15 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +265 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +26 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/ledger.d.ts +7 -0
- package/dist/commands/ledger.d.ts.map +1 -0
- package/dist/commands/ledger.js +66 -0
- package/dist/commands/ledger.js.map +1 -0
- package/dist/commands/link.d.ts +6 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +6 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/promote.d.ts +6 -0
- package/dist/commands/promote.d.ts.map +1 -0
- package/dist/commands/promote.js +6 -0
- package/dist/commands/promote.js.map +1 -0
- package/dist/commands/purge.d.ts +10 -0
- package/dist/commands/purge.d.ts.map +1 -0
- package/dist/commands/purge.js +26 -0
- package/dist/commands/purge.js.map +1 -0
- package/dist/commands/read.d.ts +6 -0
- package/dist/commands/read.d.ts.map +1 -0
- package/dist/commands/read.js +4 -0
- package/dist/commands/read.js.map +1 -0
- package/dist/commands/recall.d.ts +6 -0
- package/dist/commands/recall.d.ts.map +1 -0
- package/dist/commands/recall.js +4 -0
- package/dist/commands/recall.js.map +1 -0
- package/dist/commands/record.d.ts +6 -0
- package/dist/commands/record.d.ts.map +1 -0
- package/dist/commands/record.js +4 -0
- package/dist/commands/record.js.map +1 -0
- package/dist/commands/search.d.ts +6 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +4 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/serve.d.ts +34 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +120 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/server-status.d.ts +20 -0
- package/dist/commands/server-status.d.ts.map +1 -0
- package/dist/commands/server-status.js +21 -0
- package/dist/commands/server-status.js.map +1 -0
- package/dist/commands/server.d.ts +13 -0
- package/dist/commands/server.d.ts.map +1 -0
- package/dist/commands/server.js +89 -0
- package/dist/commands/server.js.map +1 -0
- package/dist/commands/setup.d.ts +32 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +121 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/supersede.d.ts +6 -0
- package/dist/commands/supersede.d.ts.map +1 -0
- package/dist/commands/supersede.js +6 -0
- package/dist/commands/supersede.js.map +1 -0
- package/dist/commands/use.d.ts +28 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +176 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/config/paths.d.ts +18 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +104 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/project-config.d.ts +10 -0
- package/dist/config/project-config.d.ts.map +1 -0
- package/dist/config/project-config.js +59 -0
- package/dist/config/project-config.js.map +1 -0
- package/dist/context/broker.d.ts +80 -0
- package/dist/context/broker.d.ts.map +1 -0
- package/dist/context/broker.js +437 -0
- package/dist/context/broker.js.map +1 -0
- package/dist/context/delivery.d.ts +66 -0
- package/dist/context/delivery.d.ts.map +1 -0
- package/dist/context/delivery.js +758 -0
- package/dist/context/delivery.js.map +1 -0
- package/dist/context/feedback.d.ts +75 -0
- package/dist/context/feedback.d.ts.map +1 -0
- package/dist/context/feedback.js +997 -0
- package/dist/context/feedback.js.map +1 -0
- package/dist/context/ranking.d.ts +98 -0
- package/dist/context/ranking.d.ts.map +1 -0
- package/dist/context/ranking.js +513 -0
- package/dist/context/ranking.js.map +1 -0
- package/dist/context/recommendations.d.ts +85 -0
- package/dist/context/recommendations.d.ts.map +1 -0
- package/dist/context/recommendations.js +342 -0
- package/dist/context/recommendations.js.map +1 -0
- package/dist/db/adapter.d.ts +25 -0
- package/dist/db/adapter.d.ts.map +1 -0
- package/dist/db/adapter.js +37 -0
- package/dist/db/adapter.js.map +1 -0
- package/dist/db/capabilities.d.ts +13 -0
- package/dist/db/capabilities.d.ts.map +1 -0
- package/dist/db/capabilities.js +25 -0
- package/dist/db/capabilities.js.map +1 -0
- package/dist/db/connection.d.ts +6 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +42 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +102 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/transaction.d.ts +4 -0
- package/dist/db/transaction.d.ts.map +1 -0
- package/dist/db/transaction.js +39 -0
- package/dist/db/transaction.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +32 -0
- package/dist/errors.js.map +1 -0
- package/dist/gateway/agent-service.d.ts +69 -0
- package/dist/gateway/agent-service.d.ts.map +1 -0
- package/dist/gateway/agent-service.js +581 -0
- package/dist/gateway/agent-service.js.map +1 -0
- package/dist/gateway/checkpoint-service.d.ts +42 -0
- package/dist/gateway/checkpoint-service.d.ts.map +1 -0
- package/dist/gateway/checkpoint-service.js +295 -0
- package/dist/gateway/checkpoint-service.js.map +1 -0
- package/dist/knowledge/sources.d.ts +72 -0
- package/dist/knowledge/sources.d.ts.map +1 -0
- package/dist/knowledge/sources.js +406 -0
- package/dist/knowledge/sources.js.map +1 -0
- package/dist/ledger/archive.d.ts +50 -0
- package/dist/ledger/archive.d.ts.map +1 -0
- package/dist/ledger/archive.js +1072 -0
- package/dist/ledger/archive.js.map +1 -0
- package/dist/ledger/hash.d.ts +22 -0
- package/dist/ledger/hash.d.ts.map +1 -0
- package/dist/ledger/hash.js +25 -0
- package/dist/ledger/hash.js.map +1 -0
- package/dist/ledger/maintenance.d.ts +78 -0
- package/dist/ledger/maintenance.d.ts.map +1 -0
- package/dist/ledger/maintenance.js +683 -0
- package/dist/ledger/maintenance.js.map +1 -0
- package/dist/ledger/projection.d.ts +37 -0
- package/dist/ledger/projection.d.ts.map +1 -0
- package/dist/ledger/projection.js +307 -0
- package/dist/ledger/projection.js.map +1 -0
- package/dist/ledger/promotion.d.ts +28 -0
- package/dist/ledger/promotion.d.ts.map +1 -0
- package/dist/ledger/promotion.js +308 -0
- package/dist/ledger/promotion.js.map +1 -0
- package/dist/ledger/query.d.ts +55 -0
- package/dist/ledger/query.d.ts.map +1 -0
- package/dist/ledger/query.js +321 -0
- package/dist/ledger/query.js.map +1 -0
- package/dist/ledger/redaction.d.ts +8 -0
- package/dist/ledger/redaction.d.ts.map +1 -0
- package/dist/ledger/redaction.js +40 -0
- package/dist/ledger/redaction.js.map +1 -0
- package/dist/ledger/store.d.ts +46 -0
- package/dist/ledger/store.d.ts.map +1 -0
- package/dist/ledger/store.js +324 -0
- package/dist/ledger/store.js.map +1 -0
- package/dist/ledger/types.d.ts +119 -0
- package/dist/ledger/types.d.ts.map +1 -0
- package/dist/ledger/types.js +22 -0
- package/dist/ledger/types.js.map +1 -0
- package/dist/ledger/validate.d.ts +10 -0
- package/dist/ledger/validate.d.ts.map +1 -0
- package/dist/ledger/validate.js +183 -0
- package/dist/ledger/validate.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +86 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/memory/audit.d.ts +14 -0
- package/dist/memory/audit.d.ts.map +1 -0
- package/dist/memory/audit.js +16 -0
- package/dist/memory/audit.js.map +1 -0
- package/dist/memory/entries.d.ts +65 -0
- package/dist/memory/entries.d.ts.map +1 -0
- package/dist/memory/entries.js +200 -0
- package/dist/memory/entries.js.map +1 -0
- package/dist/memory/lifecycle.d.ts +29 -0
- package/dist/memory/lifecycle.d.ts.map +1 -0
- package/dist/memory/lifecycle.js +61 -0
- package/dist/memory/lifecycle.js.map +1 -0
- package/dist/memory/retrieval.d.ts +44 -0
- package/dist/memory/retrieval.d.ts.map +1 -0
- package/dist/memory/retrieval.js +174 -0
- package/dist/memory/retrieval.js.map +1 -0
- package/dist/memory/scoped-memory.d.ts +41 -0
- package/dist/memory/scoped-memory.d.ts.map +1 -0
- package/dist/memory/scoped-memory.js +65 -0
- package/dist/memory/scoped-memory.js.map +1 -0
- package/dist/memory/secrets.d.ts +6 -0
- package/dist/memory/secrets.d.ts.map +1 -0
- package/dist/memory/secrets.js +17 -0
- package/dist/memory/secrets.js.map +1 -0
- package/dist/memory/workspaces.d.ts +17 -0
- package/dist/memory/workspaces.d.ts.map +1 -0
- package/dist/memory/workspaces.js +92 -0
- package/dist/memory/workspaces.js.map +1 -0
- package/dist/repository/binding.d.ts +19 -0
- package/dist/repository/binding.d.ts.map +1 -0
- package/dist/repository/binding.js +78 -0
- package/dist/repository/binding.js.map +1 -0
- package/dist/repository/detect-root.d.ts +12 -0
- package/dist/repository/detect-root.d.ts.map +1 -0
- package/dist/repository/detect-root.js +57 -0
- package/dist/repository/detect-root.js.map +1 -0
- package/dist/repository/git-origin.d.ts +2 -0
- package/dist/repository/git-origin.d.ts.map +1 -0
- package/dist/repository/git-origin.js +15 -0
- package/dist/repository/git-origin.js.map +1 -0
- package/dist/repository/identity.d.ts +19 -0
- package/dist/repository/identity.d.ts.map +1 -0
- package/dist/repository/identity.js +23 -0
- package/dist/repository/identity.js.map +1 -0
- package/dist/repository/remote-url.d.ts +4 -0
- package/dist/repository/remote-url.d.ts.map +1 -0
- package/dist/repository/remote-url.js +36 -0
- package/dist/repository/remote-url.js.map +1 -0
- package/dist/security/sanitize.d.ts +4 -0
- package/dist/security/sanitize.d.ts.map +1 -0
- package/dist/security/sanitize.js +174 -0
- package/dist/security/sanitize.js.map +1 -0
- package/dist/serialization/envelope.d.ts +20 -0
- package/dist/serialization/envelope.d.ts.map +1 -0
- package/dist/serialization/envelope.js +11 -0
- package/dist/serialization/envelope.js.map +1 -0
- package/dist/serialization/validate.d.ts +31 -0
- package/dist/serialization/validate.d.ts.map +1 -0
- package/dist/serialization/validate.js +168 -0
- package/dist/serialization/validate.js.map +1 -0
- package/dist/server/agent-application.d.ts +6 -0
- package/dist/server/agent-application.d.ts.map +1 -0
- package/dist/server/agent-application.js +60 -0
- package/dist/server/agent-application.js.map +1 -0
- package/dist/server/app.d.ts +5 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +87 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +22 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/http.d.ts +69 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +349 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/idempotency.d.ts +12 -0
- package/dist/server/idempotency.d.ts.map +1 -0
- package/dist/server/idempotency.js +210 -0
- package/dist/server/idempotency.js.map +1 -0
- package/dist/server/instance-lock.d.ts +17 -0
- package/dist/server/instance-lock.d.ts.map +1 -0
- package/dist/server/instance-lock.js +118 -0
- package/dist/server/instance-lock.js.map +1 -0
- package/dist/server/router.d.ts +29 -0
- package/dist/server/router.d.ts.map +1 -0
- package/dist/server/router.js +112 -0
- package/dist/server/router.js.map +1 -0
- package/dist/server/routes/agent-events.d.ts +5 -0
- package/dist/server/routes/agent-events.d.ts.map +1 -0
- package/dist/server/routes/agent-events.js +46 -0
- package/dist/server/routes/agent-events.js.map +1 -0
- package/dist/server/routes/agent-intake.d.ts +5 -0
- package/dist/server/routes/agent-intake.d.ts.map +1 -0
- package/dist/server/routes/agent-intake.js +42 -0
- package/dist/server/routes/agent-intake.js.map +1 -0
- package/dist/server/routes/agent-promotions.d.ts +5 -0
- package/dist/server/routes/agent-promotions.d.ts.map +1 -0
- package/dist/server/routes/agent-promotions.js +52 -0
- package/dist/server/routes/agent-promotions.js.map +1 -0
- package/dist/server/routes/agent-runs.d.ts +25 -0
- package/dist/server/routes/agent-runs.d.ts.map +1 -0
- package/dist/server/routes/agent-runs.js +151 -0
- package/dist/server/routes/agent-runs.js.map +1 -0
- package/dist/server/routes/task5-support.d.ts +11 -0
- package/dist/server/routes/task5-support.d.ts.map +1 -0
- package/dist/server/routes/task5-support.js +22 -0
- package/dist/server/routes/task5-support.js.map +1 -0
- package/dist/server/routes/task5.d.ts +5 -0
- package/dist/server/routes/task5.d.ts.map +1 -0
- package/dist/server/routes/task5.js +72 -0
- package/dist/server/routes/task5.js.map +1 -0
- package/dist/server/runtime-descriptor.d.ts +24 -0
- package/dist/server/runtime-descriptor.d.ts.map +1 -0
- package/dist/server/runtime-descriptor.js +156 -0
- package/dist/server/runtime-descriptor.js.map +1 -0
- package/dist/server/write-queue.d.ts +20 -0
- package/dist/server/write-queue.d.ts.map +1 -0
- package/dist/server/write-queue.js +83 -0
- package/dist/server/write-queue.js.map +1 -0
- package/dist/setup/managed-text.d.ts +6 -0
- package/dist/setup/managed-text.d.ts.map +1 -0
- package/dist/setup/managed-text.js +42 -0
- package/dist/setup/managed-text.js.map +1 -0
- package/dist/setup/opencode-config.d.ts +3 -0
- package/dist/setup/opencode-config.d.ts.map +1 -0
- package/dist/setup/opencode-config.js +26 -0
- package/dist/setup/opencode-config.js.map +1 -0
- package/dist/setup/render.d.ts +8 -0
- package/dist/setup/render.d.ts.map +1 -0
- package/dist/setup/render.js +45 -0
- package/dist/setup/render.js.map +1 -0
- package/dist/web/server.d.ts +16 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +424 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web/ui.d.ts +2 -0
- package/dist/web/ui.d.ts.map +1 -0
- package/dist/web/ui.js +271 -0
- package/dist/web/ui.js.map +1 -0
- package/migrations/001_initial.sql +89 -0
- package/migrations/002_fts.sql +66 -0
- package/migrations/003_akinator.sql +30 -0
- package/migrations/004_agent_gateway.sql +259 -0
- package/package.json +45 -0
- package/templates/AGENTS.md +29 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { chmod, lstat, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { getDatabaseLockPath } from '../config/paths.js';
|
|
5
|
+
import { KiokukoError } from '../errors.js';
|
|
6
|
+
function lockPath(databasePath, options) {
|
|
7
|
+
if (options.runtimeDirectory) {
|
|
8
|
+
const platform = options.platform ?? process.platform;
|
|
9
|
+
const platformPath = platform === 'win32' ? path.win32 : path.posix;
|
|
10
|
+
const resolvedPath = platformPath.resolve(databasePath);
|
|
11
|
+
const fingerprint = createHash('sha256').update(resolvedPath, 'utf8').digest('hex');
|
|
12
|
+
const join = platform === 'win32' ? path.win32.join : path.posix.join;
|
|
13
|
+
return join(options.runtimeDirectory, `${fingerprint}.lock`);
|
|
14
|
+
}
|
|
15
|
+
return getDatabaseLockPath(databasePath, options);
|
|
16
|
+
}
|
|
17
|
+
function lockRecord(value) {
|
|
18
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
19
|
+
throw new KiokukoError('CONFLICT', 'Database instance lock is unavailable');
|
|
20
|
+
}
|
|
21
|
+
const record = value;
|
|
22
|
+
if (typeof record.instanceId !== 'string' || typeof record.pid !== 'number' || !Number.isInteger(record.pid) || record.pid <= 0) {
|
|
23
|
+
throw new KiokukoError('CONFLICT', 'Database instance lock is unavailable');
|
|
24
|
+
}
|
|
25
|
+
return { instanceId: record.instanceId, pid: record.pid };
|
|
26
|
+
}
|
|
27
|
+
function assertSecureLockFile(info) {
|
|
28
|
+
if (info.isSymbolicLink())
|
|
29
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Database instance lock must not be a symbolic link');
|
|
30
|
+
if (!info.isFile())
|
|
31
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Database instance lock must be a regular file');
|
|
32
|
+
if (process.platform !== 'win32' && (Number(info.mode) & 0o077) !== 0) {
|
|
33
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Database instance lock permissions are too broad');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function readLockRecord(lockFilePath) {
|
|
37
|
+
assertSecureLockFile(await lstat(lockFilePath));
|
|
38
|
+
try {
|
|
39
|
+
return lockRecord(JSON.parse(await readFile(lockFilePath, 'utf8')));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof KiokukoError)
|
|
43
|
+
throw error;
|
|
44
|
+
throw new KiokukoError('CONFLICT', 'Database instance lock is unavailable');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function isPidAlive(pid) {
|
|
48
|
+
try {
|
|
49
|
+
process.kill(pid, 0);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (error instanceof Error && 'code' in error) {
|
|
54
|
+
if (error.code === 'EPERM')
|
|
55
|
+
return true;
|
|
56
|
+
if (error.code === 'ESRCH')
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function acquireInstanceLock(databasePath, options = {}) {
|
|
63
|
+
const instanceId = options.instanceId ?? randomUUID();
|
|
64
|
+
const pid = options.pid ?? process.pid;
|
|
65
|
+
const pidLiveness = options.isPidAlive ?? isPidAlive;
|
|
66
|
+
const lockFilePath = lockPath(databasePath, options);
|
|
67
|
+
await mkdir(path.dirname(lockFilePath), { recursive: true, mode: 0o700 });
|
|
68
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
69
|
+
try {
|
|
70
|
+
await writeFile(lockFilePath, `${JSON.stringify({ instanceId, pid })}\n`, { encoding: 'utf8', flag: 'wx', mode: 0o600 });
|
|
71
|
+
await chmod(lockFilePath, 0o600);
|
|
72
|
+
return {
|
|
73
|
+
path: lockFilePath,
|
|
74
|
+
instanceId,
|
|
75
|
+
release: () => releaseInstanceLock(lockFilePath, instanceId),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
|
|
80
|
+
throw error;
|
|
81
|
+
const existing = await readLockRecord(lockFilePath);
|
|
82
|
+
if (await pidLiveness(existing.pid)) {
|
|
83
|
+
throw new KiokukoError('CONFLICT', 'Another live Kiokuko instance owns this database');
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
await unlink(lockFilePath);
|
|
87
|
+
}
|
|
88
|
+
catch (unlinkError) {
|
|
89
|
+
if (!(unlinkError instanceof Error && 'code' in unlinkError && unlinkError.code === 'ENOENT'))
|
|
90
|
+
throw unlinkError;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new KiokukoError('CONFLICT', 'Database instance lock is busy');
|
|
95
|
+
}
|
|
96
|
+
export async function releaseInstanceLock(lockFilePath, expectedInstanceId) {
|
|
97
|
+
let record;
|
|
98
|
+
try {
|
|
99
|
+
record = await readLockRecord(lockFilePath);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
|
|
103
|
+
return false;
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
if (record.instanceId !== expectedInstanceId)
|
|
107
|
+
return false;
|
|
108
|
+
try {
|
|
109
|
+
await unlink(lockFilePath);
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
|
|
114
|
+
return false;
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=instance-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-lock.js","sourceRoot":"","sources":["../../src/server/instance-lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
export interface ReadinessState {
|
|
3
|
+
readonly ready: boolean;
|
|
4
|
+
}
|
|
5
|
+
export type Readiness = ReadinessState | (() => boolean | Promise<boolean>);
|
|
6
|
+
export interface RouterDependencies {
|
|
7
|
+
readonly expectedToken: string;
|
|
8
|
+
readonly readiness: Readiness;
|
|
9
|
+
readonly v1?: V1RouteHandler;
|
|
10
|
+
}
|
|
11
|
+
export type HttpHandler = (request: IncomingMessage, response: ServerResponse) => void | Promise<void>;
|
|
12
|
+
export type JsonObject = Record<string, unknown>;
|
|
13
|
+
export interface V1RouteRequest {
|
|
14
|
+
readonly method: string;
|
|
15
|
+
readonly url: URL;
|
|
16
|
+
readonly headers: IncomingMessage['headers'];
|
|
17
|
+
readonly rawHeaders?: readonly string[];
|
|
18
|
+
readonly body?: JsonObject;
|
|
19
|
+
}
|
|
20
|
+
export interface V1RouteOperationRequest {
|
|
21
|
+
readonly method: string;
|
|
22
|
+
readonly url: URL;
|
|
23
|
+
}
|
|
24
|
+
export type V1RouteOperationResolver = (request: V1RouteOperationRequest) => string | undefined;
|
|
25
|
+
export type V1RouteHandler = ((request: V1RouteRequest) => unknown | Promise<unknown>) & {
|
|
26
|
+
operationFor?: V1RouteOperationResolver;
|
|
27
|
+
};
|
|
28
|
+
export declare function createRouter(dependencies: RouterDependencies): HttpHandler;
|
|
29
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,SAAS,GAAG,cAAc,GAAG,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAE5E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEvG,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;CACnB;AAED,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,uBAAuB,KAAK,MAAM,GAAG,SAAS,CAAC;AAChG,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG;IACvF,YAAY,CAAC,EAAE,wBAAwB,CAAC;CACzC,CAAC;AAsEF,wBAAgB,YAAY,CAAC,YAAY,EAAE,kBAAkB,GAAG,WAAW,CAuC1E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { KiokukoError } from '../errors.js';
|
|
2
|
+
import { requireBearerAuthorization } from './auth.js';
|
|
3
|
+
const MAX_BODY_BYTES = 2 * 1024 * 1024;
|
|
4
|
+
const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
5
|
+
function writeJson(response, status, value) {
|
|
6
|
+
const body = JSON.stringify(value);
|
|
7
|
+
if (body === undefined || Buffer.byteLength(body) > MAX_RESPONSE_BYTES) {
|
|
8
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Response exceeds the safe size bound');
|
|
9
|
+
}
|
|
10
|
+
response.writeHead(status, {
|
|
11
|
+
'cache-control': 'no-store',
|
|
12
|
+
'content-length': Buffer.byteLength(body),
|
|
13
|
+
'content-type': 'application/json; charset=utf-8',
|
|
14
|
+
});
|
|
15
|
+
response.end(body);
|
|
16
|
+
}
|
|
17
|
+
async function readJsonObject(request) {
|
|
18
|
+
const chunks = [];
|
|
19
|
+
let size = 0;
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
let settled = false;
|
|
22
|
+
request.on('data', (chunk) => {
|
|
23
|
+
if (settled)
|
|
24
|
+
return;
|
|
25
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
26
|
+
size += buffer.byteLength;
|
|
27
|
+
if (size > MAX_BODY_BYTES) {
|
|
28
|
+
settled = true;
|
|
29
|
+
request.resume();
|
|
30
|
+
reject(new KiokukoError('VALIDATION_ERROR', 'Request body is too large'));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
chunks.push(buffer);
|
|
34
|
+
});
|
|
35
|
+
request.on('end', () => {
|
|
36
|
+
if (settled)
|
|
37
|
+
return;
|
|
38
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
39
|
+
if (text.trim().length === 0) {
|
|
40
|
+
settled = true;
|
|
41
|
+
reject(new KiokukoError('VALIDATION_ERROR', 'Request body must contain JSON'));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const value = JSON.parse(text);
|
|
46
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
47
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Request body must be a JSON object');
|
|
48
|
+
}
|
|
49
|
+
settled = true;
|
|
50
|
+
resolve(value);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (settled)
|
|
54
|
+
return;
|
|
55
|
+
settled = true;
|
|
56
|
+
reject(error instanceof KiokukoError ? error : new KiokukoError('VALIDATION_ERROR', 'Request body is not valid JSON'));
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
request.on('error', (error) => {
|
|
60
|
+
if (settled)
|
|
61
|
+
return;
|
|
62
|
+
settled = true;
|
|
63
|
+
reject(error);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function readReadiness(readiness) {
|
|
68
|
+
return typeof readiness === 'function' ? readiness() : readiness.ready;
|
|
69
|
+
}
|
|
70
|
+
export function createRouter(dependencies) {
|
|
71
|
+
return async (request, response) => {
|
|
72
|
+
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
73
|
+
if (request.method === 'GET' && url.pathname === '/health/live') {
|
|
74
|
+
writeJson(response, 200, { ok: true });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (request.method === 'GET' && url.pathname === '/health/ready') {
|
|
78
|
+
requireBearerAuthorization(request.headers.authorization, dependencies.expectedToken);
|
|
79
|
+
const ready = await readReadiness(dependencies.readiness);
|
|
80
|
+
writeJson(response, ready ? 200 : 503, { ok: ready });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (url.pathname === '/api/v1' || url.pathname.startsWith('/api/v1/')) {
|
|
84
|
+
requireBearerAuthorization(request.headers.authorization, dependencies.expectedToken);
|
|
85
|
+
if (dependencies.v1 === undefined)
|
|
86
|
+
throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
|
|
87
|
+
const routeRequest = {
|
|
88
|
+
headers: request.headers,
|
|
89
|
+
method: request.method ?? 'GET',
|
|
90
|
+
rawHeaders: request.rawHeaders,
|
|
91
|
+
url,
|
|
92
|
+
};
|
|
93
|
+
const hasRequestBody = request.method === 'POST' || request.method === 'PUT' || request.method === 'PATCH';
|
|
94
|
+
if (hasRequestBody) {
|
|
95
|
+
const contentType = request.headers['content-type'];
|
|
96
|
+
if (typeof contentType !== 'string' || !/^application\/json(?:\s*;|\s*$)/i.test(contentType)) {
|
|
97
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Request content type is invalid');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const requestWithBody = hasRequestBody
|
|
101
|
+
? { ...routeRequest, body: await readJsonObject(request) }
|
|
102
|
+
: routeRequest;
|
|
103
|
+
const result = await dependencies.v1(requestWithBody);
|
|
104
|
+
if (result === undefined)
|
|
105
|
+
throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
|
|
106
|
+
writeJson(response, 200, result);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
writeJson(response, 404, { ok: false });
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { V1RouteHandler } from '../router.js';
|
|
2
|
+
import { type AgentRouteContext } from './agent-runs.js';
|
|
3
|
+
export declare function createAgentEventsRoute(context: AgentRouteContext): V1RouteHandler;
|
|
4
|
+
export declare function agentEventsOperation(method: string, pathname: string): string | undefined;
|
|
5
|
+
//# sourceMappingURL=agent-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-events.d.ts","sourceRoot":"","sources":["../../../src/server/routes/agent-events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAOL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAIzB,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CA+BjF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKzF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { successEnvelope } from '../../serialization/envelope.js';
|
|
2
|
+
import { decodeRunId, decimalQuery, queryParameters, requireIdempotencyKey, requireNoQuery, runIdSegment, } from './agent-runs.js';
|
|
3
|
+
const EVENTS_SUFFIX = 'events';
|
|
4
|
+
export function createAgentEventsRoute(context) {
|
|
5
|
+
return async (request) => {
|
|
6
|
+
const rawRunId = runIdSegment(request.url.pathname, EVENTS_SUFFIX);
|
|
7
|
+
if (rawRunId === undefined || (request.method !== 'POST' && request.method !== 'GET'))
|
|
8
|
+
return undefined;
|
|
9
|
+
const runId = decodeRunId(rawRunId);
|
|
10
|
+
if (request.method === 'POST') {
|
|
11
|
+
requireNoQuery(request.url);
|
|
12
|
+
const idempotencyKey = requireIdempotencyKey(request);
|
|
13
|
+
const data = await context.enqueueWrite(() => context.service.appendEvents({
|
|
14
|
+
runId,
|
|
15
|
+
idempotencyKey,
|
|
16
|
+
request: request.body,
|
|
17
|
+
}));
|
|
18
|
+
return successEnvelope('agent.events', data);
|
|
19
|
+
}
|
|
20
|
+
if (request.method === 'GET') {
|
|
21
|
+
const values = queryParameters(request.url, ['after', 'type', 'limit']);
|
|
22
|
+
const input = { runId };
|
|
23
|
+
const type = values.get('type');
|
|
24
|
+
if (type !== undefined)
|
|
25
|
+
input.type = type;
|
|
26
|
+
const after = decimalQuery(values, 'after');
|
|
27
|
+
if (after !== undefined)
|
|
28
|
+
input.after = after;
|
|
29
|
+
const limit = decimalQuery(values, 'limit');
|
|
30
|
+
if (limit !== undefined)
|
|
31
|
+
input.limit = limit;
|
|
32
|
+
return successEnvelope('agent.events.list', context.service.listEvents(input));
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function agentEventsOperation(method, pathname) {
|
|
38
|
+
if (runIdSegment(pathname, EVENTS_SUFFIX) === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
if (method === 'POST')
|
|
41
|
+
return 'agent.events';
|
|
42
|
+
if (method === 'GET')
|
|
43
|
+
return 'agent.events.list';
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=agent-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-events.js","sourceRoot":"","sources":["../../../src/server/routes/agent-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EACL,WAAW,EACX,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,YAAY,GAEb,MAAM,iBAAiB,CAAC;AAEzB,MAAM,aAAa,GAAG,QAAQ,CAAC;AAE/B,MAAM,UAAU,sBAAsB,CAAC,OAA0B;IAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACnE,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACxG,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;gBACzE,KAAK;gBACL,cAAc;gBACd,OAAO,EAAE,OAAO,CAAC,IAAI;aACtB,CAAC,CAAC,CAAC;YACJ,OAAO,eAAe,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YACxE,MAAM,KAAK,GAA4B,EAAE,KAAK,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAChC,IAAI,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;YAC1C,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC5C,IAAI,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;YAC7C,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC5C,IAAI,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;YAC7C,OAAO,eAAe,CAAC,mBAAmB,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,QAAgB;IACnE,IAAI,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1E,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,cAAc,CAAC;IAC7C,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,mBAAmB,CAAC;IACjD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { V1RouteHandler } from '../router.js';
|
|
2
|
+
import { type AgentRouteContext } from './agent-runs.js';
|
|
3
|
+
export declare function createAgentIntakeRoute(context: AgentRouteContext): V1RouteHandler;
|
|
4
|
+
export declare function agentIntakeOperation(method: string, pathname: string): string | undefined;
|
|
5
|
+
//# sourceMappingURL=agent-intake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-intake.d.ts","sourceRoot":"","sources":["../../../src/server/routes/agent-intake.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAML,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAMzB,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CA8BjF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { successEnvelope } from '../../serialization/envelope.js';
|
|
2
|
+
import { decodeRunId, isRunsPath, requireIdempotencyKey, requireNoQuery, runIdSegment, } from './agent-runs.js';
|
|
3
|
+
import { attachInitialContext } from './task5-support.js';
|
|
4
|
+
const ANSWERS_SUFFIX = 'intake/answers';
|
|
5
|
+
const INTAKE_SUFFIX = 'intake';
|
|
6
|
+
export function createAgentIntakeRoute(context) {
|
|
7
|
+
return async (request) => {
|
|
8
|
+
if (isRunsPath(request.url.pathname))
|
|
9
|
+
return undefined;
|
|
10
|
+
if (request.method === 'POST') {
|
|
11
|
+
const rawRunId = runIdSegment(request.url.pathname, ANSWERS_SUFFIX);
|
|
12
|
+
if (rawRunId !== undefined) {
|
|
13
|
+
const runId = decodeRunId(rawRunId);
|
|
14
|
+
requireNoQuery(request.url);
|
|
15
|
+
const idempotencyKey = requireIdempotencyKey(request);
|
|
16
|
+
const data = await context.enqueueWrite(() => context.service.answerIntake({
|
|
17
|
+
runId,
|
|
18
|
+
idempotencyKey,
|
|
19
|
+
request: request.body,
|
|
20
|
+
}));
|
|
21
|
+
return successEnvelope('agent.answer', await attachInitialContext(context, data.runId, data));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (request.method === 'GET') {
|
|
25
|
+
const rawRunId = runIdSegment(request.url.pathname, INTAKE_SUFFIX);
|
|
26
|
+
if (rawRunId !== undefined) {
|
|
27
|
+
requireNoQuery(request.url);
|
|
28
|
+
const runId = decodeRunId(rawRunId);
|
|
29
|
+
return successEnvelope('agent.intake.read', context.service.readIntake({ runId }));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function agentIntakeOperation(method, pathname) {
|
|
36
|
+
if (method === 'POST' && runIdSegment(pathname, ANSWERS_SUFFIX) !== undefined)
|
|
37
|
+
return 'agent.answer';
|
|
38
|
+
if (method === 'GET' && runIdSegment(pathname, INTAKE_SUFFIX) !== undefined)
|
|
39
|
+
return 'agent.intake.read';
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=agent-intake.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-intake.js","sourceRoot":"","sources":["../../../src/server/routes/agent-intake.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EACL,WAAW,EACX,UAAU,EACV,qBAAqB,EACrB,cAAc,EACd,YAAY,GAEb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,cAAc,GAAG,gBAAgB,CAAC;AACxC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAE/B,MAAM,UAAU,sBAAsB,CAAC,OAA0B;IAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC;QAEvD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YACpE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;gBACpC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;gBACtD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;oBACzE,KAAK;oBACL,cAAc;oBACd,OAAO,EAAE,OAAO,CAAC,IAAI;iBACtB,CAAC,CAAC,CAAC;gBACJ,OAAO,eAAe,CAAC,cAAc,EAAE,MAAM,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YAChG,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YACnE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;gBACpC,OAAO,eAAe,CAAC,mBAAmB,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,QAAgB;IACnE,IAAI,MAAM,KAAK,MAAM,IAAI,YAAY,CAAC,QAAQ,EAAE,cAAc,CAAC,KAAK,SAAS;QAAE,OAAO,cAAc,CAAC;IACrG,IAAI,MAAM,KAAK,KAAK,IAAI,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC;IACxG,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { V1RouteHandler } from '../router.js';
|
|
2
|
+
import { type AgentRouteContext } from './agent-runs.js';
|
|
3
|
+
export declare function createAgentPromotionsRoute(context: AgentRouteContext): V1RouteHandler;
|
|
4
|
+
export declare function agentPromotionsOperation(method: string, pathname: string): string | undefined;
|
|
5
|
+
//# sourceMappingURL=agent-promotions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-promotions.d.ts","sourceRoot":"","sources":["../../../src/server/routes/agent-promotions.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAoBzB,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CA2BrF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE7F"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { withImmediateTransaction } from '../../db/transaction.js';
|
|
3
|
+
import { KiokukoError } from '../../errors.js';
|
|
4
|
+
import { executeIdempotentInTransaction } from '../idempotency.js';
|
|
5
|
+
import { promoteLedgerProposalInTransaction } from '../../ledger/promotion.js';
|
|
6
|
+
import { successEnvelope } from '../../serialization/envelope.js';
|
|
7
|
+
import { decodeRunId, requireIdempotencyKey, requireNoQuery, runIdSegment, } from './agent-runs.js';
|
|
8
|
+
const PROMOTIONS_SUFFIX = 'promotions';
|
|
9
|
+
const PROMOTION_FIELDS = new Set(['proposalEventId', 'deliveryId', 'actor', 'createdAt', 'confirmed']);
|
|
10
|
+
function invalid() {
|
|
11
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Request is invalid');
|
|
12
|
+
}
|
|
13
|
+
function promotionBody(value) {
|
|
14
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
15
|
+
invalid();
|
|
16
|
+
const body = value;
|
|
17
|
+
if (Object.keys(body).some((field) => !PROMOTION_FIELDS.has(field)))
|
|
18
|
+
invalid();
|
|
19
|
+
return body;
|
|
20
|
+
}
|
|
21
|
+
function promotionScope(runId) {
|
|
22
|
+
return `agent.promotions.${createHash('sha256').update(runId, 'utf8').digest('hex').slice(0, 32)}`;
|
|
23
|
+
}
|
|
24
|
+
export function createAgentPromotionsRoute(context) {
|
|
25
|
+
return async (request) => {
|
|
26
|
+
const rawRunId = runIdSegment(request.url.pathname, PROMOTIONS_SUFFIX);
|
|
27
|
+
if (rawRunId === undefined || request.method !== 'POST')
|
|
28
|
+
return undefined;
|
|
29
|
+
requireNoQuery(request.url);
|
|
30
|
+
const runId = decodeRunId(rawRunId);
|
|
31
|
+
const idempotencyKey = requireIdempotencyKey(request);
|
|
32
|
+
const body = promotionBody(request.body);
|
|
33
|
+
const data = await context.enqueueWrite(() => {
|
|
34
|
+
const run = context.service.readRun({ runId });
|
|
35
|
+
return withImmediateTransaction(context.database, () => executeIdempotentInTransaction(context.database, {
|
|
36
|
+
scope: promotionScope(runId),
|
|
37
|
+
key: idempotencyKey,
|
|
38
|
+
request: { runId, body },
|
|
39
|
+
createdAt: new Date().toISOString(),
|
|
40
|
+
}, () => promoteLedgerProposalInTransaction(context.database, {
|
|
41
|
+
...body,
|
|
42
|
+
workspace: run.workspace,
|
|
43
|
+
runId,
|
|
44
|
+
})));
|
|
45
|
+
});
|
|
46
|
+
return successEnvelope('agent.promotions', data);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function agentPromotionsOperation(method, pathname) {
|
|
50
|
+
return method === 'POST' && runIdSegment(pathname, PROMOTIONS_SUFFIX) !== undefined ? 'agent.promotions' : undefined;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=agent-promotions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-promotions.js","sourceRoot":"","sources":["../../../src/server/routes/agent-promotions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AgentGatewayService } from '../../gateway/agent-service.js';
|
|
2
|
+
import type { CheckpointService, FeedbackService } from '../../gateway/checkpoint-service.js';
|
|
3
|
+
import type { ContextBroker } from '../../context/broker.js';
|
|
4
|
+
import type { V1RouteHandler, V1RouteRequest } from '../router.js';
|
|
5
|
+
declare const RUNS_PATH = "/api/v1/agent/runs";
|
|
6
|
+
type QueryField = 'workspace' | 'client' | 'status' | 'cursor' | 'limit' | 'after' | 'type';
|
|
7
|
+
export interface AgentRouteContext {
|
|
8
|
+
readonly database: import('../../db/adapter.js').SqliteDatabase;
|
|
9
|
+
readonly service: AgentGatewayService;
|
|
10
|
+
readonly checkpointService: CheckpointService;
|
|
11
|
+
readonly feedbackService: FeedbackService;
|
|
12
|
+
readonly broker: ContextBroker;
|
|
13
|
+
readonly enqueueWrite: <T>(operation: () => T | PromiseLike<T>) => Promise<T>;
|
|
14
|
+
}
|
|
15
|
+
export declare function queryParameters(url: URL, allowed: readonly QueryField[]): Map<QueryField, string>;
|
|
16
|
+
export declare function requireNoQuery(url: URL): void;
|
|
17
|
+
export declare function decimalQuery(values: ReadonlyMap<QueryField, string>, field: 'limit' | 'after'): number | undefined;
|
|
18
|
+
export declare function decodeRunId(raw: string): string;
|
|
19
|
+
export declare function runIdSegment(pathname: string, suffix?: string): string | undefined;
|
|
20
|
+
export declare function requireIdempotencyKey(request: V1RouteRequest): string;
|
|
21
|
+
export declare function isRunsPath(pathname: string): boolean;
|
|
22
|
+
export declare function createAgentRunsRoute(context: AgentRouteContext): V1RouteHandler;
|
|
23
|
+
export declare function agentRunsOperation(method: string, pathname: string): string | undefined;
|
|
24
|
+
export { RUNS_PATH };
|
|
25
|
+
//# sourceMappingURL=agent-runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-runs.d.ts","sourceRoot":"","sources":["../../../src/server/routes/agent-runs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnE,QAAA,MAAM,SAAS,uBAAuB,CAAC;AAKvC,KAAK,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,qBAAqB,EAAE,cAAc,CAAC;IAChE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CAC/E;AAMD,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAQjG;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAE7C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAOlH;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAW/C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAalF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAerE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAmD/E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMvF;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|