lingxios 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/db/schema.sql +306 -0
- package/dist/src/app/artifacts.d.ts +8 -0
- package/dist/src/app/artifacts.js +114 -0
- package/dist/src/app/artifacts.js.map +1 -0
- package/dist/src/app/doctor.d.ts +22 -0
- package/dist/src/app/doctor.js +44 -0
- package/dist/src/app/doctor.js.map +1 -0
- package/dist/src/app/index.d.ts +123 -0
- package/dist/src/app/index.js +291 -0
- package/dist/src/app/index.js.map +1 -0
- package/dist/src/app/input.d.ts +22 -0
- package/dist/src/app/input.js +60 -0
- package/dist/src/app/input.js.map +1 -0
- package/dist/src/app/recover-wait.d.ts +5 -0
- package/dist/src/app/recover-wait.js +59 -0
- package/dist/src/app/recover-wait.js.map +1 -0
- package/dist/src/app/resources.d.ts +5 -0
- package/dist/src/app/resources.js +9 -0
- package/dist/src/app/resources.js.map +1 -0
- package/dist/src/app/storage.d.ts +2 -0
- package/dist/src/app/storage.js +41 -0
- package/dist/src/app/storage.js.map +1 -0
- package/dist/src/cli/doctor.d.ts +2 -0
- package/dist/src/cli/doctor.js +20 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/eval.d.ts +2 -0
- package/dist/src/cli/eval.js +44 -0
- package/dist/src/cli/eval.js.map +1 -0
- package/dist/src/config.d.ts +22 -0
- package/dist/src/config.js +56 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/context/attachments.d.ts +10 -0
- package/dist/src/context/attachments.js +18 -0
- package/dist/src/context/attachments.js.map +1 -0
- package/dist/src/context/document-text.d.ts +1 -0
- package/dist/src/context/document-text.js +29 -0
- package/dist/src/context/document-text.js.map +1 -0
- package/dist/src/context/document-worker.d.ts +1 -0
- package/dist/src/context/document-worker.js +62 -0
- package/dist/src/context/document-worker.js.map +1 -0
- package/dist/src/context/evidence.d.ts +19 -0
- package/dist/src/context/evidence.js +37 -0
- package/dist/src/context/evidence.js.map +1 -0
- package/dist/src/context/request.d.ts +21 -0
- package/dist/src/context/request.js +32 -0
- package/dist/src/context/request.js.map +1 -0
- package/dist/src/context/research-evidence.d.ts +4 -0
- package/dist/src/context/research-evidence.js +24 -0
- package/dist/src/context/research-evidence.js.map +1 -0
- package/dist/src/context/resource-checks.d.ts +7 -0
- package/dist/src/context/resource-checks.js +15 -0
- package/dist/src/context/resource-checks.js.map +1 -0
- package/dist/src/context/task-contract.d.ts +11 -0
- package/dist/src/context/task-contract.js +23 -0
- package/dist/src/context/task-contract.js.map +1 -0
- package/dist/src/context/text.d.ts +2 -0
- package/dist/src/context/text.js +7 -0
- package/dist/src/context/text.js.map +1 -0
- package/dist/src/control-plane/http-server.d.ts +22 -0
- package/dist/src/control-plane/http-server.js +196 -0
- package/dist/src/control-plane/http-server.js.map +1 -0
- package/dist/src/control-plane/memory-store.d.ts +71 -0
- package/dist/src/control-plane/memory-store.js +389 -0
- package/dist/src/control-plane/memory-store.js.map +1 -0
- package/dist/src/control-plane/pg-store.d.ts +62 -0
- package/dist/src/control-plane/pg-store.js +386 -0
- package/dist/src/control-plane/pg-store.js.map +1 -0
- package/dist/src/control-plane/service.d.ts +52 -0
- package/dist/src/control-plane/service.js +630 -0
- package/dist/src/control-plane/service.js.map +1 -0
- package/dist/src/control-plane/stores.d.ts +184 -0
- package/dist/src/control-plane/stores.js +19 -0
- package/dist/src/control-plane/stores.js.map +1 -0
- package/dist/src/errors.d.ts +66 -0
- package/dist/src/errors.js +102 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/eval/calibration.d.ts +16 -0
- package/dist/src/eval/calibration.js +28 -0
- package/dist/src/eval/calibration.js.map +1 -0
- package/dist/src/eval/index.d.ts +40 -0
- package/dist/src/eval/index.js +40 -0
- package/dist/src/eval/index.js.map +1 -0
- package/dist/src/eval/review.d.ts +20 -0
- package/dist/src/eval/review.js +49 -0
- package/dist/src/eval/review.js.map +1 -0
- package/dist/src/host/http-client.d.ts +48 -0
- package/dist/src/host/http-client.js +127 -0
- package/dist/src/host/http-client.js.map +1 -0
- package/dist/src/host/port.d.ts +26 -0
- package/dist/src/host/port.js +2 -0
- package/dist/src/host/port.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/integrations/lingxiloop/actions.d.ts +25 -0
- package/dist/src/integrations/lingxiloop/actions.js +77 -0
- package/dist/src/integrations/lingxiloop/actions.js.map +1 -0
- package/dist/src/integrations/lingxiloop/app.d.ts +167 -0
- package/dist/src/integrations/lingxiloop/app.js +434 -0
- package/dist/src/integrations/lingxiloop/app.js.map +1 -0
- package/dist/src/integrations/lingxiloop/approvals.d.ts +148 -0
- package/dist/src/integrations/lingxiloop/approvals.js +540 -0
- package/dist/src/integrations/lingxiloop/approvals.js.map +1 -0
- package/dist/src/integrations/lingxiloop/attachments.d.ts +8 -0
- package/dist/src/integrations/lingxiloop/attachments.js +38 -0
- package/dist/src/integrations/lingxiloop/attachments.js.map +1 -0
- package/dist/src/integrations/lingxiloop/calendar-approvals.d.ts +21 -0
- package/dist/src/integrations/lingxiloop/calendar-approvals.js +126 -0
- package/dist/src/integrations/lingxiloop/calendar-approvals.js.map +1 -0
- package/dist/src/integrations/lingxiloop/calendar-writes.d.ts +15 -0
- package/dist/src/integrations/lingxiloop/calendar-writes.js +79 -0
- package/dist/src/integrations/lingxiloop/calendar-writes.js.map +1 -0
- package/dist/src/integrations/lingxiloop/calendar.d.ts +19 -0
- package/dist/src/integrations/lingxiloop/calendar.js +43 -0
- package/dist/src/integrations/lingxiloop/calendar.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-events.d.ts +7 -0
- package/dist/src/integrations/lingxiloop/canvas-events.js +53 -0
- package/dist/src/integrations/lingxiloop/canvas-events.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-summary.d.ts +5 -0
- package/dist/src/integrations/lingxiloop/canvas-summary.js +52 -0
- package/dist/src/integrations/lingxiloop/canvas-summary.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-work-report.d.ts +12 -0
- package/dist/src/integrations/lingxiloop/canvas-work-report.js +120 -0
- package/dist/src/integrations/lingxiloop/canvas-work-report.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-work.d.ts +11 -0
- package/dist/src/integrations/lingxiloop/canvas-work.js +306 -0
- package/dist/src/integrations/lingxiloop/canvas-work.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas.d.ts +12 -0
- package/dist/src/integrations/lingxiloop/canvas.js +79 -0
- package/dist/src/integrations/lingxiloop/canvas.js.map +1 -0
- package/dist/src/integrations/lingxiloop/chat.d.ts +11 -0
- package/dist/src/integrations/lingxiloop/chat.js +46 -0
- package/dist/src/integrations/lingxiloop/chat.js.map +1 -0
- package/dist/src/integrations/lingxiloop/document-approvals.d.ts +21 -0
- package/dist/src/integrations/lingxiloop/document-approvals.js +75 -0
- package/dist/src/integrations/lingxiloop/document-approvals.js.map +1 -0
- package/dist/src/integrations/lingxiloop/document-content.d.ts +80 -0
- package/dist/src/integrations/lingxiloop/document-content.js +195 -0
- package/dist/src/integrations/lingxiloop/document-content.js.map +1 -0
- package/dist/src/integrations/lingxiloop/document-writes.d.ts +8 -0
- package/dist/src/integrations/lingxiloop/document-writes.js +49 -0
- package/dist/src/integrations/lingxiloop/document-writes.js.map +1 -0
- package/dist/src/integrations/lingxiloop/documents.d.ts +22 -0
- package/dist/src/integrations/lingxiloop/documents.js +38 -0
- package/dist/src/integrations/lingxiloop/documents.js.map +1 -0
- package/dist/src/integrations/lingxiloop/event-outbox.d.ts +5 -0
- package/dist/src/integrations/lingxiloop/event-outbox.js +47 -0
- package/dist/src/integrations/lingxiloop/event-outbox.js.map +1 -0
- package/dist/src/integrations/lingxiloop/index.d.ts +3 -0
- package/dist/src/integrations/lingxiloop/index.js +3 -0
- package/dist/src/integrations/lingxiloop/index.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-attempts.d.ts +13 -0
- package/dist/src/integrations/lingxiloop/learning-attempts.js +58 -0
- package/dist/src/integrations/lingxiloop/learning-attempts.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-evaluation.d.ts +8 -0
- package/dist/src/integrations/lingxiloop/learning-evaluation.js +64 -0
- package/dist/src/integrations/lingxiloop/learning-evaluation.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-evidence.d.ts +7 -0
- package/dist/src/integrations/lingxiloop/learning-evidence.js +88 -0
- package/dist/src/integrations/lingxiloop/learning-evidence.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-missions.d.ts +18 -0
- package/dist/src/integrations/lingxiloop/learning-missions.js +95 -0
- package/dist/src/integrations/lingxiloop/learning-missions.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning.d.ts +22 -0
- package/dist/src/integrations/lingxiloop/learning.js +150 -0
- package/dist/src/integrations/lingxiloop/learning.js.map +1 -0
- package/dist/src/integrations/lingxiloop/memory.d.ts +14 -0
- package/dist/src/integrations/lingxiloop/memory.js +133 -0
- package/dist/src/integrations/lingxiloop/memory.js.map +1 -0
- package/dist/src/integrations/lingxiloop/polls.d.ts +9 -0
- package/dist/src/integrations/lingxiloop/polls.js +47 -0
- package/dist/src/integrations/lingxiloop/polls.js.map +1 -0
- package/dist/src/integrations/lingxiloop/presentations.d.ts +11 -0
- package/dist/src/integrations/lingxiloop/presentations.js +34 -0
- package/dist/src/integrations/lingxiloop/presentations.js.map +1 -0
- package/dist/src/integrations/lingxiloop/questionnaire.d.ts +21 -0
- package/dist/src/integrations/lingxiloop/questionnaire.js +57 -0
- package/dist/src/integrations/lingxiloop/questionnaire.js.map +1 -0
- package/dist/src/integrations/lingxiloop/research.d.ts +19 -0
- package/dist/src/integrations/lingxiloop/research.js +20 -0
- package/dist/src/integrations/lingxiloop/research.js.map +1 -0
- package/dist/src/integrations/lingxiloop/routines.d.ts +91 -0
- package/dist/src/integrations/lingxiloop/routines.js +198 -0
- package/dist/src/integrations/lingxiloop/routines.js.map +1 -0
- package/dist/src/integrations/lingxiloop/service-contracts.d.ts +1045 -0
- package/dist/src/integrations/lingxiloop/service-contracts.js +2 -0
- package/dist/src/integrations/lingxiloop/service-contracts.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher-context.d.ts +32 -0
- package/dist/src/integrations/lingxiloop/teacher-context.js +25 -0
- package/dist/src/integrations/lingxiloop/teacher-context.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher-digest.d.ts +13 -0
- package/dist/src/integrations/lingxiloop/teacher-digest.js +152 -0
- package/dist/src/integrations/lingxiloop/teacher-digest.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher-preview.d.ts +22 -0
- package/dist/src/integrations/lingxiloop/teacher-preview.js +41 -0
- package/dist/src/integrations/lingxiloop/teacher-preview.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher.d.ts +24 -0
- package/dist/src/integrations/lingxiloop/teacher.js +224 -0
- package/dist/src/integrations/lingxiloop/teacher.js.map +1 -0
- package/dist/src/kernel/manager.d.ts +52 -0
- package/dist/src/kernel/manager.js +407 -0
- package/dist/src/kernel/manager.js.map +1 -0
- package/dist/src/logging.d.ts +21 -0
- package/dist/src/logging.js +54 -0
- package/dist/src/logging.js.map +1 -0
- package/dist/src/memory/evidence.d.ts +6 -0
- package/dist/src/memory/evidence.js +43 -0
- package/dist/src/memory/evidence.js.map +1 -0
- package/dist/src/memory/processor.d.ts +3 -0
- package/dist/src/memory/processor.js +66 -0
- package/dist/src/memory/processor.js.map +1 -0
- package/dist/src/memory/semantic.d.ts +19 -0
- package/dist/src/memory/semantic.js +93 -0
- package/dist/src/memory/semantic.js.map +1 -0
- package/dist/src/memory/store.d.ts +20 -0
- package/dist/src/memory/store.js +34 -0
- package/dist/src/memory/store.js.map +1 -0
- package/dist/src/memory/synthesis.d.ts +24 -0
- package/dist/src/memory/synthesis.js +138 -0
- package/dist/src/memory/synthesis.js.map +1 -0
- package/dist/src/metrics.d.ts +43 -0
- package/dist/src/metrics.js +130 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/model/driver.d.ts +60 -0
- package/dist/src/model/driver.js +2 -0
- package/dist/src/model/driver.js.map +1 -0
- package/dist/src/model/embeddings.d.ts +24 -0
- package/dist/src/model/embeddings.js +97 -0
- package/dist/src/model/embeddings.js.map +1 -0
- package/dist/src/model/openai.d.ts +45 -0
- package/dist/src/model/openai.js +340 -0
- package/dist/src/model/openai.js.map +1 -0
- package/dist/src/outcome/assessment.d.ts +16 -0
- package/dist/src/outcome/assessment.js +45 -0
- package/dist/src/outcome/assessment.js.map +1 -0
- package/dist/src/outcome/content-check.d.ts +19 -0
- package/dist/src/outcome/content-check.js +44 -0
- package/dist/src/outcome/content-check.js.map +1 -0
- package/dist/src/outcome/envelope.d.ts +34 -0
- package/dist/src/outcome/envelope.js +42 -0
- package/dist/src/outcome/envelope.js.map +1 -0
- package/dist/src/protocol/constants.d.ts +25 -0
- package/dist/src/protocol/constants.js +26 -0
- package/dist/src/protocol/constants.js.map +1 -0
- package/dist/src/protocol/kernel-wire.d.ts +74 -0
- package/dist/src/protocol/kernel-wire.js +2 -0
- package/dist/src/protocol/kernel-wire.js.map +1 -0
- package/dist/src/protocol/outcome.d.ts +16 -0
- package/dist/src/protocol/outcome.js +14 -0
- package/dist/src/protocol/outcome.js.map +1 -0
- package/dist/src/protocol/types.d.ts +266 -0
- package/dist/src/protocol/types.js +19 -0
- package/dist/src/protocol/types.js.map +1 -0
- package/dist/src/research/address.d.ts +2 -0
- package/dist/src/research/address.js +32 -0
- package/dist/src/research/address.js.map +1 -0
- package/dist/src/research/fetch.d.ts +7 -0
- package/dist/src/research/fetch.js +83 -0
- package/dist/src/research/fetch.js.map +1 -0
- package/dist/src/research/index.d.ts +26 -0
- package/dist/src/research/index.js +109 -0
- package/dist/src/research/index.js.map +1 -0
- package/dist/src/runtime/compaction.d.ts +41 -0
- package/dist/src/runtime/compaction.js +86 -0
- package/dist/src/runtime/compaction.js.map +1 -0
- package/dist/src/runtime/corrections.d.ts +20 -0
- package/dist/src/runtime/corrections.js +27 -0
- package/dist/src/runtime/corrections.js.map +1 -0
- package/dist/src/runtime/policy.d.ts +42 -0
- package/dist/src/runtime/policy.js +91 -0
- package/dist/src/runtime/policy.js.map +1 -0
- package/dist/src/runtime/resource-refresh.d.ts +8 -0
- package/dist/src/runtime/resource-refresh.js +37 -0
- package/dist/src/runtime/resource-refresh.js.map +1 -0
- package/dist/src/runtime/runtime.d.ts +51 -0
- package/dist/src/runtime/runtime.js +804 -0
- package/dist/src/runtime/runtime.js.map +1 -0
- package/dist/src/runtime/tool.d.ts +13 -0
- package/dist/src/runtime/tool.js +42 -0
- package/dist/src/runtime/tool.js.map +1 -0
- package/dist/src/ui/index.d.ts +27 -0
- package/dist/src/ui/index.js +54 -0
- package/dist/src/ui/index.js.map +1 -0
- package/dist/src/versions.d.ts +9 -0
- package/dist/src/versions.js +11 -0
- package/dist/src/versions.js.map +1 -0
- package/dist/src/worker/index.d.ts +3 -0
- package/dist/src/worker/index.js +57 -0
- package/dist/src/worker/index.js.map +1 -0
- package/dist/src/worker/main.d.ts +2 -0
- package/dist/src/worker/main.js +9 -0
- package/dist/src/worker/main.js.map +1 -0
- package/dist/src/worker/worker.d.ts +45 -0
- package/dist/src/worker/worker.js +154 -0
- package/dist/src/worker/worker.js.map +1 -0
- package/kernel/runner.py +507 -0
- package/package.json +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# LingxiOS
|
|
2
|
+
|
|
3
|
+
AgentOS and Harness in one npm package: durable PostgreSQL work queues, fenced workers, versioned requests, Python execution, action receipts, goal outcomes and committed messages/files.
|
|
4
|
+
|
|
5
|
+
The first release targets the core runtime. The optional LingxiLoop integration contains the implemented bindings; it does not claim complete product capability coverage. There is one initial schema and no legacy migration or dual-write path.
|
|
6
|
+
|
|
7
|
+
## Run a request
|
|
8
|
+
|
|
9
|
+
Requires Node.js 22.13+, Python 3 and a PostgreSQL pool. Apply `packageResources().schema` to a new application database before starting. The application checks the installed schema and does not fall back to in-memory storage.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { createLingxiOS } from 'lingxios'
|
|
13
|
+
import { pool } from './database.js'
|
|
14
|
+
|
|
15
|
+
const app = await createLingxiOS({
|
|
16
|
+
database: pool,
|
|
17
|
+
model: { apiKey: process.env.AGENT_OS_MODEL_API_KEY! },
|
|
18
|
+
kernel: { homesRoot: '/persistent/agent-homes' },
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// Authenticate and authorize this identity in the calling server.
|
|
23
|
+
const identity = {
|
|
24
|
+
runId: 'request-1', tenantId: 'tenant', agentId: 'assistant', sessionId: 'conversation',
|
|
25
|
+
}
|
|
26
|
+
await app.enqueue({
|
|
27
|
+
...identity, id: identity.runId, principalId: 'authenticated-user',
|
|
28
|
+
text: 'Calculate six times seven using Python.',
|
|
29
|
+
})
|
|
30
|
+
await app.runNext()
|
|
31
|
+
console.log(await app.readMessage(identity))
|
|
32
|
+
console.log(await app.readOutcome(identity))
|
|
33
|
+
} finally {
|
|
34
|
+
await app.stop()
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The default model is `deepseek-ai/DeepSeek-V4-Flash` at SiliconFlow, with `reasoning_effort=high`. The calling application owns the database pool. Use `start()` for continuous local workers, or `/worker` and the authenticated HTTP control plane for separate worker processes.
|
|
39
|
+
|
|
40
|
+
## Public entries
|
|
41
|
+
|
|
42
|
+
| Entry | Purpose |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `lingxios` | Application, diagnostics and packaged schema/runner locations |
|
|
45
|
+
| `lingxios/worker` | Worker process and startup configuration |
|
|
46
|
+
| `lingxios/ui` | Browser-safe committed message and event consumers |
|
|
47
|
+
| `lingxios/eval` | Recorded resource checks and model review |
|
|
48
|
+
| `lingxios/lingxiloop` | Optional native product bindings |
|
|
49
|
+
|
|
50
|
+
Goal status is separate from worker lifecycle. `satisfied` records the model's requirement assessment; it is not independent proof of correctness. Unknown actions, missing receipts and known resource failures prevent a satisfied result. Input/approval waits retain the same request and version. Committed files are hashed snapshots; recovering an interrupted worker does not blindly repeat unknown effects.
|
|
51
|
+
|
|
52
|
+
Python execution needs deployment isolation suitable for your trust model; Python-level guards are not an OS security boundary. Committed artifacts currently require shared persistent filesystem storage and are limited to 16 MiB each.
|
|
53
|
+
|
|
54
|
+
See [runtime API and deployment details](docs/packaged-runtime.md). `npm test` includes standalone tarball installation. `npm run check:release` also requires isolated PostgreSQL fixtures and the native LingxiLoop reference checkout; it does not deploy a product or contact real email recipients.
|
package/db/schema.sql
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
-- LingxiOS Agent OS — control-plane schema (protocol v2)
|
|
2
|
+
--
|
|
3
|
+
-- Apply with: psql -f db/schema.sql
|
|
4
|
+
-- All tables are owned by the control plane; workers never touch the database.
|
|
5
|
+
|
|
6
|
+
CREATE SCHEMA IF NOT EXISTS lingxios;
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS lingxios.schema_version (
|
|
9
|
+
singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton),
|
|
10
|
+
version INT NOT NULL
|
|
11
|
+
);
|
|
12
|
+
INSERT INTO lingxios.schema_version(singleton, version) VALUES(TRUE, 1) ON CONFLICT DO NOTHING;
|
|
13
|
+
|
|
14
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_work_items (
|
|
15
|
+
id TEXT PRIMARY KEY,
|
|
16
|
+
fence BIGINT NOT NULL DEFAULT 0,
|
|
17
|
+
tenant_id TEXT NOT NULL,
|
|
18
|
+
agent_id TEXT NOT NULL,
|
|
19
|
+
session_id TEXT NOT NULL,
|
|
20
|
+
thread_id TEXT,
|
|
21
|
+
kind TEXT NOT NULL,
|
|
22
|
+
lane TEXT NOT NULL CHECK (lane IN ('interactive','approval','collaboration','background')),
|
|
23
|
+
trigger_ref TEXT NOT NULL,
|
|
24
|
+
principal_id TEXT,
|
|
25
|
+
priority INT NOT NULL DEFAULT 0,
|
|
26
|
+
status TEXT NOT NULL DEFAULT 'queued'
|
|
27
|
+
CHECK (status IN ('queued','leased','completed','failed','cancelled')),
|
|
28
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
29
|
+
available_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
30
|
+
attempts INT NOT NULL DEFAULT 0,
|
|
31
|
+
preemptions INT NOT NULL DEFAULT 0,
|
|
32
|
+
lease_token_hash TEXT,
|
|
33
|
+
leased_by TEXT,
|
|
34
|
+
lease_expires_at TIMESTAMPTZ,
|
|
35
|
+
cancel_requested_at TIMESTAMPTZ,
|
|
36
|
+
preempt_requested_at TIMESTAMPTZ,
|
|
37
|
+
steer_inputs JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
38
|
+
result_text TEXT,
|
|
39
|
+
goal_outcome JSONB,
|
|
40
|
+
error TEXT,
|
|
41
|
+
meta JSONB,
|
|
42
|
+
finished_at TIMESTAMPTZ,
|
|
43
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
CREATE INDEX IF NOT EXISTS agent_work_items_claim_idx
|
|
47
|
+
ON lingxios.agent_work_items (status, available_at)
|
|
48
|
+
WHERE status IN ('queued','leased');
|
|
49
|
+
|
|
50
|
+
-- Package-owned schedules; no dependency on the retired product agent runtime.
|
|
51
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_routines (
|
|
52
|
+
id TEXT PRIMARY KEY,
|
|
53
|
+
tenant_id TEXT NOT NULL,
|
|
54
|
+
agent_id TEXT NOT NULL,
|
|
55
|
+
session_id TEXT NOT NULL,
|
|
56
|
+
principal_id TEXT NOT NULL,
|
|
57
|
+
project_id TEXT,
|
|
58
|
+
course_id TEXT,
|
|
59
|
+
thread_id TEXT,
|
|
60
|
+
kind TEXT NOT NULL,
|
|
61
|
+
title TEXT,
|
|
62
|
+
instructions TEXT,
|
|
63
|
+
schedule JSONB NOT NULL,
|
|
64
|
+
timezone TEXT NOT NULL,
|
|
65
|
+
status TEXT NOT NULL CHECK (status IN ('active','paused')),
|
|
66
|
+
version INT NOT NULL DEFAULT 1 CHECK (version>0),
|
|
67
|
+
next_run_at TIMESTAMPTZ,
|
|
68
|
+
pause_reason TEXT,
|
|
69
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
70
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
71
|
+
CHECK (kind<>'teacher_digest' OR (project_id IS NOT NULL AND course_id IS NOT NULL AND thread_id IS NULL)),
|
|
72
|
+
CHECK (kind='teacher_digest' OR (title IS NOT NULL AND instructions IS NOT NULL AND course_id IS NULL)),
|
|
73
|
+
CHECK ((status='active' AND next_run_at IS NOT NULL) OR (status='paused' AND next_run_at IS NULL))
|
|
74
|
+
);
|
|
75
|
+
CREATE UNIQUE INDEX IF NOT EXISTS agent_teacher_digest_scope_idx ON lingxios.agent_routines(tenant_id,agent_id,session_id,kind) WHERE kind='teacher_digest';
|
|
76
|
+
CREATE INDEX IF NOT EXISTS agent_routines_due_idx ON lingxios.agent_routines(next_run_at) WHERE status='active';
|
|
77
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_routine_runs (
|
|
78
|
+
routine_id TEXT NOT NULL REFERENCES lingxios.agent_routines(id) ON DELETE CASCADE,
|
|
79
|
+
routine_version INT NOT NULL,
|
|
80
|
+
scheduled_at TIMESTAMPTZ NOT NULL,
|
|
81
|
+
work_id TEXT NOT NULL UNIQUE REFERENCES lingxios.agent_work_items(id) ON DELETE CASCADE,
|
|
82
|
+
PRIMARY KEY(routine_id,routine_version,scheduled_at)
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
-- One live lease per session key.
|
|
86
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_os_session_leases (
|
|
87
|
+
session_key TEXT PRIMARY KEY,
|
|
88
|
+
work_id TEXT NOT NULL,
|
|
89
|
+
fence BIGINT NOT NULL,
|
|
90
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
91
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
-- Session -> worker routing with home epochs.
|
|
95
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_os_session_routes (
|
|
96
|
+
session_key TEXT PRIMARY KEY,
|
|
97
|
+
worker_id TEXT NOT NULL,
|
|
98
|
+
home_epoch BIGINT NOT NULL DEFAULT 1,
|
|
99
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
-- Worker liveness.
|
|
103
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_os_workers (
|
|
104
|
+
worker_id TEXT PRIMARY KEY,
|
|
105
|
+
last_seen_at TIMESTAMPTZ NOT NULL,
|
|
106
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
-- Durable conversational sessions (optimistic concurrency via revision).
|
|
110
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_os_sessions (
|
|
111
|
+
session_key TEXT PRIMARY KEY,
|
|
112
|
+
tenant_id TEXT NOT NULL,
|
|
113
|
+
agent_id TEXT NOT NULL,
|
|
114
|
+
session_id TEXT NOT NULL,
|
|
115
|
+
thread_id TEXT,
|
|
116
|
+
summary TEXT,
|
|
117
|
+
history JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
118
|
+
applied_work_ids JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
119
|
+
revision BIGINT NOT NULL DEFAULT 0,
|
|
120
|
+
compaction_epoch INT NOT NULL DEFAULT 0,
|
|
121
|
+
prompt_context JSONB,
|
|
122
|
+
request_snapshot JSONB,
|
|
123
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
-- Run event ledger: dedupe on (run_id, seq); the attempt range is enforced by
|
|
127
|
+
-- the control plane before insert.
|
|
128
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_run_events (
|
|
129
|
+
run_id TEXT NOT NULL,
|
|
130
|
+
seq BIGINT NOT NULL,
|
|
131
|
+
tenant_id TEXT NOT NULL,
|
|
132
|
+
agent_id TEXT NOT NULL,
|
|
133
|
+
kind TEXT NOT NULL,
|
|
134
|
+
stage TEXT NOT NULL,
|
|
135
|
+
visibility TEXT NOT NULL CHECK (visibility IN ('user','internal')),
|
|
136
|
+
data JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
137
|
+
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
138
|
+
PRIMARY KEY (run_id, seq)
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
-- An intent without a receipt is uncertain, never automatically re-executed.
|
|
142
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_action_intents (
|
|
143
|
+
idempotency_key TEXT PRIMARY KEY,
|
|
144
|
+
fingerprint TEXT NOT NULL,
|
|
145
|
+
intent JSONB NOT NULL CHECK (jsonb_typeof(intent) = 'object'),
|
|
146
|
+
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
-- Receipts complement pre-execution intents; missing receipts require reconciliation.
|
|
150
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_action_ledger (
|
|
151
|
+
idempotency_key TEXT PRIMARY KEY REFERENCES lingxios.agent_action_intents(idempotency_key),
|
|
152
|
+
result JSONB NOT NULL,
|
|
153
|
+
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_messages (
|
|
157
|
+
run_id TEXT PRIMARY KEY,
|
|
158
|
+
tenant_id TEXT NOT NULL,
|
|
159
|
+
agent_id TEXT NOT NULL,
|
|
160
|
+
session_id TEXT NOT NULL,
|
|
161
|
+
message JSONB NOT NULL,
|
|
162
|
+
home_epoch BIGINT NOT NULL DEFAULT 1 CHECK (home_epoch > 0),
|
|
163
|
+
committed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_delivery_outbox (
|
|
167
|
+
run_id TEXT PRIMARY KEY REFERENCES lingxios.agent_messages(run_id),
|
|
168
|
+
work JSONB NOT NULL,
|
|
169
|
+
delivered_at TIMESTAMPTZ,
|
|
170
|
+
available_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
171
|
+
claim_token TEXT,
|
|
172
|
+
attempts INTEGER NOT NULL DEFAULT 0
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_calendar_outbox (
|
|
176
|
+
id TEXT PRIMARY KEY REFERENCES lingxios.agent_action_intents(idempotency_key),
|
|
177
|
+
work_id TEXT NOT NULL REFERENCES lingxios.agent_work_items(id),
|
|
178
|
+
event JSONB NOT NULL CHECK (jsonb_typeof(event)='object' AND event->>'type'='calendar.changed'),
|
|
179
|
+
delivered_at TIMESTAMPTZ,
|
|
180
|
+
available_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
181
|
+
claim_token TEXT,
|
|
182
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts BETWEEN 0 AND 30)
|
|
183
|
+
);
|
|
184
|
+
CREATE INDEX IF NOT EXISTS agent_calendar_outbox_pending
|
|
185
|
+
ON lingxios.agent_calendar_outbox(available_at,id) WHERE delivered_at IS NULL;
|
|
186
|
+
|
|
187
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_canvas_outbox (
|
|
188
|
+
id TEXT PRIMARY KEY,
|
|
189
|
+
event JSONB NOT NULL CHECK (jsonb_typeof(event)='object' AND event->>'type'='canvas.changed'),
|
|
190
|
+
delivered_at TIMESTAMPTZ,
|
|
191
|
+
available_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
192
|
+
claim_token TEXT,
|
|
193
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts BETWEEN 0 AND 30)
|
|
194
|
+
);
|
|
195
|
+
CREATE INDEX IF NOT EXISTS agent_canvas_outbox_pending
|
|
196
|
+
ON lingxios.agent_canvas_outbox(available_at,id) WHERE delivered_at IS NULL;
|
|
197
|
+
|
|
198
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_document_outbox (
|
|
199
|
+
id TEXT PRIMARY KEY,
|
|
200
|
+
event JSONB NOT NULL CHECK (jsonb_typeof(event)='object' AND event->>'type' IN ('doc.changed','doc.update')),
|
|
201
|
+
delivered_at TIMESTAMPTZ,
|
|
202
|
+
available_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
203
|
+
claim_token TEXT,
|
|
204
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts BETWEEN 0 AND 30)
|
|
205
|
+
);
|
|
206
|
+
CREATE INDEX IF NOT EXISTS agent_document_outbox_pending
|
|
207
|
+
ON lingxios.agent_document_outbox(available_at,id) WHERE delivered_at IS NULL;
|
|
208
|
+
|
|
209
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_memories (
|
|
210
|
+
tenant_id TEXT NOT NULL,
|
|
211
|
+
id TEXT NOT NULL,
|
|
212
|
+
scope_type TEXT NOT NULL CHECK (scope_type IN ('learner','course','agent_role')),
|
|
213
|
+
scope_id TEXT NOT NULL,
|
|
214
|
+
body TEXT NOT NULL CHECK (length(body) BETWEEN 1 AND 2000),
|
|
215
|
+
kind TEXT NOT NULL,
|
|
216
|
+
origin TEXT NOT NULL CHECK (origin IN ('explicit','synthesized')),
|
|
217
|
+
pinned BOOLEAN NOT NULL DEFAULT FALSE,
|
|
218
|
+
version INTEGER NOT NULL DEFAULT 1 CHECK (version > 0),
|
|
219
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','expired')),
|
|
220
|
+
source_refs JSONB NOT NULL CHECK (jsonb_typeof(source_refs)='array' AND jsonb_array_length(source_refs) BETWEEN 1 AND 64),
|
|
221
|
+
valid_until TIMESTAMPTZ,
|
|
222
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
223
|
+
PRIMARY KEY (tenant_id,id)
|
|
224
|
+
);
|
|
225
|
+
CREATE INDEX IF NOT EXISTS agent_memories_scope ON lingxios.agent_memories(tenant_id,scope_type,scope_id,updated_at DESC);
|
|
226
|
+
|
|
227
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_memory_embeddings (
|
|
228
|
+
tenant_id TEXT NOT NULL,
|
|
229
|
+
memory_id TEXT NOT NULL,
|
|
230
|
+
version INTEGER NOT NULL CHECK (version > 0),
|
|
231
|
+
model_key TEXT NOT NULL,
|
|
232
|
+
model TEXT NOT NULL,
|
|
233
|
+
embedding DOUBLE PRECISION[] NOT NULL CHECK (cardinality(embedding) BETWEEN 1 AND 4096),
|
|
234
|
+
PRIMARY KEY (tenant_id,memory_id,model_key),
|
|
235
|
+
FOREIGN KEY (tenant_id,memory_id) REFERENCES lingxios.agent_memories(tenant_id,id) ON DELETE CASCADE
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_memory_versions (
|
|
239
|
+
tenant_id TEXT NOT NULL,
|
|
240
|
+
memory_id TEXT NOT NULL,
|
|
241
|
+
version INTEGER NOT NULL CHECK (version > 0),
|
|
242
|
+
snapshot JSONB NOT NULL CHECK (jsonb_typeof(snapshot)='object'),
|
|
243
|
+
replaced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
244
|
+
PRIMARY KEY (tenant_id,memory_id,version),
|
|
245
|
+
FOREIGN KEY (tenant_id,memory_id) REFERENCES lingxios.agent_memories(tenant_id,id) ON DELETE CASCADE
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
-- Archive the replaced version in the mutation transaction. Explicit forgetting
|
|
249
|
+
-- deletes its history through the foreign key instead of retaining forgotten text.
|
|
250
|
+
CREATE OR REPLACE FUNCTION lingxios.archive_memory_version() RETURNS trigger
|
|
251
|
+
LANGUAGE plpgsql AS $$
|
|
252
|
+
BEGIN
|
|
253
|
+
IF NEW.version <= OLD.version THEN
|
|
254
|
+
RAISE EXCEPTION 'memory versions must increase';
|
|
255
|
+
END IF;
|
|
256
|
+
INSERT INTO lingxios.agent_memory_versions(tenant_id,memory_id,version,snapshot)
|
|
257
|
+
VALUES(OLD.tenant_id,OLD.id,OLD.version,to_jsonb(OLD));
|
|
258
|
+
RETURN NEW;
|
|
259
|
+
END;
|
|
260
|
+
$$;
|
|
261
|
+
CREATE OR REPLACE TRIGGER agent_memory_version_history
|
|
262
|
+
BEFORE UPDATE OF version ON lingxios.agent_memories
|
|
263
|
+
FOR EACH ROW WHEN (OLD.version IS DISTINCT FROM NEW.version)
|
|
264
|
+
EXECUTE FUNCTION lingxios.archive_memory_version();
|
|
265
|
+
|
|
266
|
+
CREATE TABLE IF NOT EXISTS lingxios.agent_memory_evidence (
|
|
267
|
+
source_run_id TEXT PRIMARY KEY REFERENCES lingxios.agent_messages(run_id),
|
|
268
|
+
tenant_id TEXT NOT NULL,
|
|
269
|
+
agent_id TEXT NOT NULL,
|
|
270
|
+
principal_id TEXT NOT NULL,
|
|
271
|
+
session_id TEXT NOT NULL,
|
|
272
|
+
request_version INTEGER NOT NULL CHECK (request_version > 0),
|
|
273
|
+
source_ref TEXT NOT NULL,
|
|
274
|
+
input_sha256 TEXT NOT NULL CHECK (input_sha256 ~ '^[a-f0-9]{64}$'),
|
|
275
|
+
input_text TEXT NOT NULL CHECK (length(input_text) <= 16000),
|
|
276
|
+
assistant_text TEXT NOT NULL CHECK (length(assistant_text) <= 16000),
|
|
277
|
+
input_truncated BOOLEAN NOT NULL,
|
|
278
|
+
assistant_truncated BOOLEAN NOT NULL,
|
|
279
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','processed','rejected','superseded')),
|
|
280
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
-- Invalidate sources atomically on every cancellation/continuation path, including
|
|
284
|
+
-- server-side ingress that does not call the worker's control-plane methods.
|
|
285
|
+
CREATE OR REPLACE FUNCTION lingxios.supersede_memory_evidence() RETURNS trigger
|
|
286
|
+
LANGUAGE plpgsql AS $$
|
|
287
|
+
BEGIN
|
|
288
|
+
WITH superseded AS (
|
|
289
|
+
UPDATE lingxios.agent_memory_evidence SET status='superseded'
|
|
290
|
+
WHERE source_run_id=NEW.id AND status IN ('pending','processed')
|
|
291
|
+
AND (NEW.cancel_requested_at IS NOT NULL OR NEW.status='cancelled'
|
|
292
|
+
OR request_version<>jsonb_array_length(NEW.steer_inputs)+1)
|
|
293
|
+
RETURNING source_run_id,tenant_id)
|
|
294
|
+
UPDATE lingxios.agent_memories memory SET status='expired',version=version+1,updated_at=NOW()
|
|
295
|
+
FROM superseded source WHERE memory.tenant_id=source.tenant_id AND memory.origin='synthesized'
|
|
296
|
+
AND NOT memory.pinned AND memory.status='active'
|
|
297
|
+
AND memory.source_refs @> jsonb_build_array(jsonb_build_object('workId',source.source_run_id));
|
|
298
|
+
RETURN NEW;
|
|
299
|
+
END;
|
|
300
|
+
$$;
|
|
301
|
+
CREATE OR REPLACE TRIGGER agent_work_memory_evidence
|
|
302
|
+
AFTER UPDATE OF cancel_requested_at,status,steer_inputs ON lingxios.agent_work_items
|
|
303
|
+
FOR EACH ROW
|
|
304
|
+
WHEN (OLD.cancel_requested_at IS DISTINCT FROM NEW.cancel_requested_at
|
|
305
|
+
OR OLD.status IS DISTINCT FROM NEW.status OR OLD.steer_inputs IS DISTINCT FROM NEW.steer_inputs)
|
|
306
|
+
EXECUTE FUNCTION lingxios.supersede_memory_evidence();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SqlPool } from '../control-plane/pg-store.js';
|
|
2
|
+
import type { AssistantMessage, KernelArtifact, WorkItem } from '../protocol/types.js';
|
|
3
|
+
import type { MessageIdentity, RequestInput } from './index.js';
|
|
4
|
+
export declare function persistArtifacts(homesRoot: string, work: Omit<WorkItem, 'leaseToken'>, message: AssistantMessage): Promise<void>;
|
|
5
|
+
export declare function readArtifact(database: SqlPool, homesRoot: string, identity: MessageIdentity & Pick<RequestInput, 'principalId' | 'threadId'>, path: string): Promise<{
|
|
6
|
+
artifact: KernelArtifact;
|
|
7
|
+
bytes: Buffer<ArrayBuffer>;
|
|
8
|
+
} | null>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { open, realpath, mkdir, link, unlink } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
4
|
+
import { kernelHome } from '../kernel/manager.js';
|
|
5
|
+
import { snapshotArtifacts } from '../outcome/envelope.js';
|
|
6
|
+
function artifactDirectory(root, identity) {
|
|
7
|
+
const hash = createHash('sha256').update(JSON.stringify([identity.tenantId, identity.agentId, identity.runId])).digest('hex');
|
|
8
|
+
return resolve(root, '.committed-artifacts', hash);
|
|
9
|
+
}
|
|
10
|
+
const inside = (parent, child) => {
|
|
11
|
+
const path = relative(parent, child);
|
|
12
|
+
return path !== '..' && !path.startsWith('../') && !path.startsWith('..\\') && !isAbsolute(path);
|
|
13
|
+
};
|
|
14
|
+
async function checkedFile(root, directory, filename, artifact) {
|
|
15
|
+
// ponytail: bounded buffers; add streaming storage for files above 16 MiB.
|
|
16
|
+
if (artifact.size > 16 * 1024 * 1024)
|
|
17
|
+
throw new Error('artifact exceeds the 16 MiB limit');
|
|
18
|
+
const home = await realpath(directory);
|
|
19
|
+
const file = await realpath(resolve(home, filename));
|
|
20
|
+
if (!inside(root, home) || !inside(home, file))
|
|
21
|
+
throw new Error('artifact is outside its committed home');
|
|
22
|
+
const handle = await open(file, 'r');
|
|
23
|
+
try {
|
|
24
|
+
const before = await handle.stat();
|
|
25
|
+
if (!before.isFile() || before.size !== artifact.size)
|
|
26
|
+
throw new Error('artifact changed since commitment');
|
|
27
|
+
const bytes = Buffer.alloc(artifact.size + 1);
|
|
28
|
+
let length = 0;
|
|
29
|
+
while (length < bytes.length) {
|
|
30
|
+
const read = await handle.read(bytes, length, bytes.length - length, null);
|
|
31
|
+
if (!read.bytesRead)
|
|
32
|
+
break;
|
|
33
|
+
length += read.bytesRead;
|
|
34
|
+
}
|
|
35
|
+
const after = await handle.stat();
|
|
36
|
+
const content = bytes.subarray(0, length);
|
|
37
|
+
if (length !== artifact.size || before.mtimeMs !== after.mtimeMs || after.size !== artifact.size
|
|
38
|
+
|| createHash('sha256').update(content).digest('hex') !== artifact.sha256.toLowerCase())
|
|
39
|
+
throw new Error('artifact changed since commitment');
|
|
40
|
+
return { artifact, bytes: content };
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await handle.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function persistArtifacts(homesRoot, work, message) {
|
|
47
|
+
const artifacts = snapshotArtifacts(message.envelope.artifacts);
|
|
48
|
+
if (!artifacts.length)
|
|
49
|
+
return;
|
|
50
|
+
const root = await realpath(homesRoot);
|
|
51
|
+
const directory = artifactDirectory(root, { ...work, runId: work.id });
|
|
52
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
53
|
+
if (await realpath(directory) !== directory)
|
|
54
|
+
throw new Error('artifact storage must not traverse directory links');
|
|
55
|
+
for (const artifact of artifacts) {
|
|
56
|
+
const destination = resolve(directory, artifact.sha256.toLowerCase());
|
|
57
|
+
try {
|
|
58
|
+
await checkedFile(root, directory, artifact.sha256.toLowerCase(), artifact);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error.code !== 'ENOENT')
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
const { bytes } = await checkedFile(root, kernelHome(root, work), artifact.path, artifact);
|
|
66
|
+
const temporary = resolve(directory, randomUUID());
|
|
67
|
+
const handle = await open(temporary, 'wx', 0o600);
|
|
68
|
+
try {
|
|
69
|
+
await handle.writeFile(bytes);
|
|
70
|
+
await handle.sync();
|
|
71
|
+
await handle.close();
|
|
72
|
+
try {
|
|
73
|
+
await link(temporary, destination);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error.code !== 'EEXIST')
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
await checkedFile(root, directory, artifact.sha256.toLowerCase(), artifact);
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
await handle.close();
|
|
83
|
+
await unlink(temporary);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function readArtifact(database, homesRoot, identity, path) {
|
|
88
|
+
if (!identity.principalId?.trim())
|
|
89
|
+
throw new Error('authenticated principalId is required');
|
|
90
|
+
const { rows } = await database.query(`SELECT message.message,message.home_epoch FROM lingxios.agent_messages message
|
|
91
|
+
JOIN lingxios.agent_work_items work ON work.id=message.run_id AND work.tenant_id=message.tenant_id
|
|
92
|
+
AND work.agent_id=message.agent_id AND work.session_id=message.session_id
|
|
93
|
+
WHERE message.run_id=$1 AND message.tenant_id=$2 AND message.agent_id=$3 AND message.session_id=$4
|
|
94
|
+
AND work.principal_id=$5 AND work.thread_id IS NOT DISTINCT FROM $6`, [identity.runId, identity.tenantId, identity.agentId, identity.sessionId, identity.principalId, identity.threadId ?? null]);
|
|
95
|
+
if (!rows[0])
|
|
96
|
+
return null;
|
|
97
|
+
const message = rows[0]['message'];
|
|
98
|
+
const artifact = snapshotArtifacts(message.envelope.artifacts).find(item => item.path === path);
|
|
99
|
+
if (!artifact)
|
|
100
|
+
return null;
|
|
101
|
+
try {
|
|
102
|
+
const root = await realpath(homesRoot);
|
|
103
|
+
const directory = artifactDirectory(root, identity);
|
|
104
|
+
if (await realpath(directory) !== directory)
|
|
105
|
+
throw new Error('artifact storage must not traverse directory links');
|
|
106
|
+
return await checkedFile(root, directory, artifact.sha256.toLowerCase(), artifact);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (error.code === 'ENOENT')
|
|
110
|
+
return null;
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/app/artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SqlQueryable } from '../control-plane/pg-store.js';
|
|
2
|
+
export interface DoctorCheck {
|
|
3
|
+
name: string;
|
|
4
|
+
status: 'passed' | 'failed' | 'not_run';
|
|
5
|
+
detail: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function doctor(options?: {
|
|
8
|
+
database?: SqlQueryable;
|
|
9
|
+
pythonCommand?: string;
|
|
10
|
+
env?: NodeJS.ProcessEnv;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
ready: boolean;
|
|
13
|
+
versions: Readonly<{
|
|
14
|
+
readonly runtime: "1.0.0";
|
|
15
|
+
readonly controlPlane: 2;
|
|
16
|
+
readonly kernel: 2;
|
|
17
|
+
readonly schema: 1;
|
|
18
|
+
readonly lingxiLoop: 1;
|
|
19
|
+
readonly assistantMessage: 2;
|
|
20
|
+
}>;
|
|
21
|
+
checks: DoctorCheck[];
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { packageResources } from './resources.js';
|
|
5
|
+
import { checkStorage } from './storage.js';
|
|
6
|
+
import { releaseVersions } from '../versions.js';
|
|
7
|
+
export async function doctor(options = {}) {
|
|
8
|
+
const env = options.env ?? process.env;
|
|
9
|
+
const checks = [];
|
|
10
|
+
const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
|
|
11
|
+
checks.push({ name: 'node', status: (nodeMajor > 22 || nodeMajor === 22 && nodeMinor >= 13) ? 'passed' : 'failed', detail: process.versions.node });
|
|
12
|
+
const python = options.pythonCommand ?? env['AGENT_OS_PYTHON'] ?? (process.platform === 'win32' ? 'python' : 'python3');
|
|
13
|
+
try {
|
|
14
|
+
const { stdout } = await promisify(execFile)(python, ['-I', '-c', 'import sys; assert sys.version_info >= (3, 10); print(sys.version.split()[0])'], { timeout: 10_000 });
|
|
15
|
+
checks.push({ name: 'python', status: 'passed', detail: stdout.trim() });
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
checks.push({ name: 'python', status: 'failed', detail: 'Python >=3.10 must be executable; set AGENT_OS_PYTHON if needed' });
|
|
19
|
+
}
|
|
20
|
+
for (const [name, path] of Object.entries(packageResources())) {
|
|
21
|
+
try {
|
|
22
|
+
await access(path);
|
|
23
|
+
checks.push({ name, status: 'passed', detail: path });
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
checks.push({ name, status: 'failed', detail: 'required packaged resource is missing' });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
checks.push({ name: 'model_configuration', status: env['AGENT_OS_MODEL_API_KEY']?.trim() ? 'passed' : 'failed', detail: 'Checks credential configuration presence only; model defaults to DeepSeek-V4-Flash with high reasoning. Provider access and quality are not tested.' });
|
|
30
|
+
if (options.database) {
|
|
31
|
+
try {
|
|
32
|
+
await checkStorage(options.database);
|
|
33
|
+
checks.push({ name: 'database', status: 'passed', detail: 'Initial schema version 1, required columns and memory triggers are readable; write permissions and all constraints are not verified' });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
checks.push({ name: 'database', status: 'failed', detail: 'Database unavailable or explicit schema installation is required' });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
checks.push({ name: 'database', status: 'not_run', detail: 'Pass the existing database pool to doctor to verify storage' });
|
|
41
|
+
}
|
|
42
|
+
return { ready: checks.every((check) => check.status === 'passed'), versions: releaseVersions, checks };
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/app/doctor.ts"],"names":[],"mappings":"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"}
|