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
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol-wide constants.
|
|
3
|
+
*
|
|
4
|
+
* Version numbers gate compatibility between independently deployed pieces
|
|
5
|
+
* (control plane, workers, kernels). Bump a version only for a breaking wire
|
|
6
|
+
* change; additive optional fields do not require a bump.
|
|
7
|
+
*/
|
|
8
|
+
/** Control-plane HTTP API and worker claim protocol. */
|
|
9
|
+
export const AGENT_OS_PROTOCOL_VERSION = 2;
|
|
10
|
+
/** Kernel stdio (NDJSON) protocol between the manager and `kernel/runner.py`. */
|
|
11
|
+
export const KERNEL_PROTOCOL_VERSION = 2;
|
|
12
|
+
/**
|
|
13
|
+
* Each lease attempt of a run owns a disjoint event-sequence range:
|
|
14
|
+
* `((fence - 1) * RUN_SEQUENCE_SPAN, fence * RUN_SEQUENCE_SPAN]`.
|
|
15
|
+
*
|
|
16
|
+
* A retried attempt therefore never collides with — and is never deduplicated
|
|
17
|
+
* against — events persisted by an earlier attempt of the same run.
|
|
18
|
+
*/
|
|
19
|
+
export const RUN_SEQUENCE_SPAN = 100_000;
|
|
20
|
+
/** Upper bound applied to any single tool/host payload surfaced to the model. */
|
|
21
|
+
export const MAX_TOOL_OUTPUT_CHARS = 8_000;
|
|
22
|
+
/** Name of the single tool exposed to the model. */
|
|
23
|
+
export const IPYTHON_TOOL_NAME = 'ipython';
|
|
24
|
+
/** Name of the in-kernel SDK module the model calls (`host.<capability>.<method>`). */
|
|
25
|
+
export const KERNEL_SDK_MODULE = 'host';
|
|
26
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAU,CAAA;AAEnD,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAU,CAAA;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAgB,CAAA;AAEjD,iFAAiF;AACjF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAc,CAAA;AAEnD,oDAAoD;AACpD,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAkB,CAAA;AAEnD,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAe,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NDJSON stdio protocol between the kernel manager and `kernel/runner.py`.
|
|
3
|
+
*
|
|
4
|
+
* Framing: one JSON object per line, ASCII-safe (non-ASCII escaped) so the
|
|
5
|
+
* transport is locale-independent (`python -I` ignores PYTHONIOENCODING).
|
|
6
|
+
*
|
|
7
|
+
* Concurrency model: the manager serializes executions per kernel; while an
|
|
8
|
+
* execution is in flight the only messages the manager may write are the
|
|
9
|
+
* `host_result` replies to that execution's `host_call`s. The runner blocks
|
|
10
|
+
* synchronously inside a host call, which is what makes the bridge appear as
|
|
11
|
+
* ordinary synchronous Python to model-authored code.
|
|
12
|
+
*/
|
|
13
|
+
import type { CapabilityGrant, HostDirective, KernelArtifact } from './types.js';
|
|
14
|
+
export interface KernelExecuteRequest {
|
|
15
|
+
type: 'execute';
|
|
16
|
+
id: string;
|
|
17
|
+
code: string;
|
|
18
|
+
context: {
|
|
19
|
+
runId: string;
|
|
20
|
+
cellId: string;
|
|
21
|
+
capabilities: CapabilityGrant[];
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface KernelHostResultMessage {
|
|
25
|
+
type: 'host_result';
|
|
26
|
+
requestId: string;
|
|
27
|
+
ok: boolean;
|
|
28
|
+
value?: unknown;
|
|
29
|
+
error?: string;
|
|
30
|
+
approval?: {
|
|
31
|
+
id: string;
|
|
32
|
+
status: 'PENDING';
|
|
33
|
+
};
|
|
34
|
+
directive?: HostDirective;
|
|
35
|
+
}
|
|
36
|
+
export interface KernelShutdownRequest {
|
|
37
|
+
type: 'shutdown';
|
|
38
|
+
}
|
|
39
|
+
export type ManagerToKernel = KernelExecuteRequest | KernelHostResultMessage | KernelShutdownRequest;
|
|
40
|
+
export interface KernelReadyMessage {
|
|
41
|
+
type: 'ready';
|
|
42
|
+
protocol: number;
|
|
43
|
+
python: string;
|
|
44
|
+
engine: 'ipython' | 'basic';
|
|
45
|
+
home: string;
|
|
46
|
+
}
|
|
47
|
+
export interface KernelHostCallMessage {
|
|
48
|
+
type: 'host_call';
|
|
49
|
+
/** Execution id this call belongs to — required for correlation. */
|
|
50
|
+
id: string;
|
|
51
|
+
requestId: string;
|
|
52
|
+
callIndex: number;
|
|
53
|
+
action: string;
|
|
54
|
+
args: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
export interface KernelExecutionResultMessage {
|
|
57
|
+
type: 'execution_result';
|
|
58
|
+
id: string;
|
|
59
|
+
ok: boolean;
|
|
60
|
+
stdout: string;
|
|
61
|
+
stderr: string;
|
|
62
|
+
result: unknown;
|
|
63
|
+
error: string | null;
|
|
64
|
+
approvalId: string | null;
|
|
65
|
+
truncated: boolean;
|
|
66
|
+
durationMs: number;
|
|
67
|
+
artifacts: KernelArtifact[];
|
|
68
|
+
directives: HostDirective[];
|
|
69
|
+
}
|
|
70
|
+
export interface KernelProtocolErrorMessage {
|
|
71
|
+
type: 'protocol_error';
|
|
72
|
+
error: string;
|
|
73
|
+
}
|
|
74
|
+
export type KernelToManager = KernelReadyMessage | KernelHostCallMessage | KernelExecutionResultMessage | KernelProtocolErrorMessage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel-wire.js","sourceRoot":"","sources":["../../../src/protocol/kernel-wire.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type Verification = 'passed' | 'not_run' | 'inconclusive';
|
|
2
|
+
export type GoalOutcome = {
|
|
3
|
+
requestVersion: number;
|
|
4
|
+
verification: Verification;
|
|
5
|
+
gaps?: string[];
|
|
6
|
+
question?: string;
|
|
7
|
+
} & ({
|
|
8
|
+
status: 'satisfied' | 'partial' | 'awaiting_input' | 'blocked';
|
|
9
|
+
} | {
|
|
10
|
+
status: 'awaiting_approval';
|
|
11
|
+
approvalId: string;
|
|
12
|
+
} | {
|
|
13
|
+
status: 'delegated';
|
|
14
|
+
taskRef: string;
|
|
15
|
+
});
|
|
16
|
+
export declare function isGoalOutcome(value: unknown): value is GoalOutcome;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function isGoalOutcome(value) {
|
|
2
|
+
if (!value || typeof value !== 'object')
|
|
3
|
+
return false;
|
|
4
|
+
const item = value;
|
|
5
|
+
return Number.isSafeInteger(item['requestVersion']) && Number(item['requestVersion']) > 0
|
|
6
|
+
&& typeof item['verification'] === 'string' && ['passed', 'not_run', 'inconclusive'].includes(item['verification'])
|
|
7
|
+
&& typeof item['status'] === 'string' && ['satisfied', 'partial', 'awaiting_input', 'awaiting_approval', 'delegated', 'blocked'].includes(item['status'])
|
|
8
|
+
&& (item['gaps'] === undefined || (Array.isArray(item['gaps']) && item['gaps'].every((gap) => typeof gap === 'string')))
|
|
9
|
+
&& (item['question'] === undefined || (item['status'] === 'awaiting_input' && typeof item['question'] === 'string' && item['question'].trim().length > 0 && item['question'].length <= 4_000))
|
|
10
|
+
&& (item['status'] !== 'satisfied' || item['gaps'] === undefined || item['gaps'].length === 0)
|
|
11
|
+
&& (item['status'] !== 'awaiting_approval' || (typeof item['approvalId'] === 'string' && item['approvalId'].trim().length > 0))
|
|
12
|
+
&& (item['status'] !== 'delegated' || (typeof item['taskRef'] === 'string' && item['taskRef'].trim().length > 0));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=outcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outcome.js","sourceRoot":"","sources":["../../../src/protocol/outcome.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACrD,MAAM,IAAI,GAAG,KAAgC,CAAA;IAC7C,OAAO,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC;WACpF,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,QAAQ,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;WAChH,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,QAAQ,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;WACtJ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC;WACrH,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,gBAAgB,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;WAC3L,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS,IAAK,IAAI,CAAC,MAAM,CAAe,CAAC,MAAM,KAAK,CAAC,CAAC;WAC1G,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,mBAAmB,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;WAC5H,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,WAAW,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;AACrH,CAAC"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core protocol types shared by the control plane, workers, kernels, and
|
|
3
|
+
* extensions. This module is intentionally logic-free: every layer depends on
|
|
4
|
+
* it and it depends on nothing.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Why a work item exists. `turn` is the ordinary conversational turn handled
|
|
8
|
+
* by the runtime's agent loop; every other kind is routed to a registered
|
|
9
|
+
* {@link import('../runtime/runtime.js').WorkProcessor}.
|
|
10
|
+
*/
|
|
11
|
+
export type WorkKind = 'turn' | 'resume' | (string & {});
|
|
12
|
+
/** Scheduling lane. Higher lanes are claimed before lower ones. */
|
|
13
|
+
export type WorkLane = 'interactive' | 'approval' | 'collaboration' | 'background';
|
|
14
|
+
export declare const WORK_LANE_PRIORITY: Readonly<Record<WorkLane, number>>;
|
|
15
|
+
export type WorkStatus = 'queued' | 'leased' | 'completed' | 'failed' | 'cancelled';
|
|
16
|
+
/**
|
|
17
|
+
* A durable unit of agent work, claimed under a fenced lease.
|
|
18
|
+
*
|
|
19
|
+
* Invariants:
|
|
20
|
+
* - `fence` increases by exactly one on every lease acquisition and every
|
|
21
|
+
* yield, and never decreases. Every mutating control-plane call carries
|
|
22
|
+
* `(id, fence, leaseToken)` and is rejected unless all three match the
|
|
23
|
+
* current lease.
|
|
24
|
+
* - `id` doubles as the run id: a retried attempt reuses every externally
|
|
25
|
+
* visible identity, and attempt separation happens through the fence-scoped
|
|
26
|
+
* event-sequence ranges (see `RUN_SEQUENCE_SPAN`).
|
|
27
|
+
*/
|
|
28
|
+
export interface WorkItem {
|
|
29
|
+
id: string;
|
|
30
|
+
fence: number;
|
|
31
|
+
/**
|
|
32
|
+
* Increments when the session is re-routed to a different worker, so a
|
|
33
|
+
* kernel filesystem home written by a lost worker is never reused.
|
|
34
|
+
*/
|
|
35
|
+
homeEpoch: number;
|
|
36
|
+
tenantId: string;
|
|
37
|
+
agentId: string;
|
|
38
|
+
sessionId: string;
|
|
39
|
+
/** Optional sub-thread inside the session. */
|
|
40
|
+
threadId?: string;
|
|
41
|
+
kind: WorkKind;
|
|
42
|
+
lane: WorkLane;
|
|
43
|
+
/** Opaque reference to whatever triggered this work (message id, cron id…). */
|
|
44
|
+
triggerRef: string;
|
|
45
|
+
/** Human principal whose authorization the work runs under, if any. */
|
|
46
|
+
principalId?: string;
|
|
47
|
+
createdAt?: string;
|
|
48
|
+
availableAt?: string;
|
|
49
|
+
attempts?: number;
|
|
50
|
+
preemptions?: number;
|
|
51
|
+
/** Bearer proof of the current lease. Never persisted in clear text. */
|
|
52
|
+
leaseToken: string;
|
|
53
|
+
/** Deployment-defined extra routing/context payload (opaque to the core). */
|
|
54
|
+
meta?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
export interface WorkCompletion {
|
|
57
|
+
goalOutcome?: import('./outcome.js').GoalOutcome;
|
|
58
|
+
status: 'completed' | 'failed' | 'cancelled';
|
|
59
|
+
resultText?: string;
|
|
60
|
+
error?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A capability grants access to one host-bridge namespace, optionally
|
|
64
|
+
* restricted to specific methods. Grants are enforced twice: advisorily
|
|
65
|
+
* inside the kernel (the model cannot even *name* an ungranted method) and
|
|
66
|
+
* authoritatively in the control plane before any action executes.
|
|
67
|
+
*/
|
|
68
|
+
export interface CapabilityGrant {
|
|
69
|
+
name: string;
|
|
70
|
+
/** When present, only these methods are callable. */
|
|
71
|
+
methods?: readonly string[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One product side effect requested by kernel code via
|
|
75
|
+
* `host.<namespace>.<method>(...)`.
|
|
76
|
+
*
|
|
77
|
+
* `idempotencyKey` is the JSON tuple `[runId, cellId, callIndex]` — deterministic
|
|
78
|
+
* across kernel restarts replaying the same cell — so the control-plane
|
|
79
|
+
* action ledger can reject changed intents and avoid blindly replaying effects.
|
|
80
|
+
*/
|
|
81
|
+
export interface HostAction {
|
|
82
|
+
runId: string;
|
|
83
|
+
cellId: string;
|
|
84
|
+
callIndex: number;
|
|
85
|
+
/** `<namespace>.<method>` */
|
|
86
|
+
action: string;
|
|
87
|
+
args: Record<string, unknown>;
|
|
88
|
+
idempotencyKey: string;
|
|
89
|
+
}
|
|
90
|
+
export declare function actionKeyOf(action: Pick<HostAction, 'runId' | 'cellId' | 'callIndex'>): string;
|
|
91
|
+
export interface HostActionResult {
|
|
92
|
+
ok: boolean;
|
|
93
|
+
executionState?: 'unknown';
|
|
94
|
+
value?: unknown;
|
|
95
|
+
error?: string;
|
|
96
|
+
/** Present when the action suspended into a human approval. */
|
|
97
|
+
approval?: {
|
|
98
|
+
id: string;
|
|
99
|
+
status: 'PENDING';
|
|
100
|
+
};
|
|
101
|
+
/** Optional host instruction back to the runtime. */
|
|
102
|
+
directive?: HostDirective;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A host directive lets an action tell the runtime that the turn is finished
|
|
106
|
+
* out-of-band (e.g. work was handed to another surface, or the host asked the
|
|
107
|
+
* user a blocking question). The runtime completes the run successfully
|
|
108
|
+
* without a final assistant message.
|
|
109
|
+
*/
|
|
110
|
+
export interface HostDirective {
|
|
111
|
+
type: 'defer' | 'task_contract';
|
|
112
|
+
reason?: string;
|
|
113
|
+
data?: Record<string, unknown>;
|
|
114
|
+
}
|
|
115
|
+
export interface ApprovalResolution {
|
|
116
|
+
approvalId: string;
|
|
117
|
+
approved: boolean;
|
|
118
|
+
result?: unknown;
|
|
119
|
+
error?: string;
|
|
120
|
+
}
|
|
121
|
+
export interface KernelArtifact {
|
|
122
|
+
path: string;
|
|
123
|
+
size: number;
|
|
124
|
+
mime: string;
|
|
125
|
+
sha256: string;
|
|
126
|
+
}
|
|
127
|
+
export interface KernelExecution {
|
|
128
|
+
executionId: string;
|
|
129
|
+
stdout: string;
|
|
130
|
+
stderr: string;
|
|
131
|
+
result: unknown;
|
|
132
|
+
durationMs: number;
|
|
133
|
+
truncated: boolean;
|
|
134
|
+
artifacts: KernelArtifact[];
|
|
135
|
+
directives: HostDirective[];
|
|
136
|
+
}
|
|
137
|
+
export type RunStage = 'started' | 'delta' | 'completed' | 'failed' | 'cancelled';
|
|
138
|
+
/**
|
|
139
|
+
* A single durable event of a run attempt. `seq` must fall inside the
|
|
140
|
+
* attempt's fence-scoped range; the control plane rejects events outside it
|
|
141
|
+
* and deduplicates on `(runId, seq)`.
|
|
142
|
+
*/
|
|
143
|
+
export interface RunEvent {
|
|
144
|
+
runId: string;
|
|
145
|
+
seq: number;
|
|
146
|
+
kind: string;
|
|
147
|
+
stage: RunStage;
|
|
148
|
+
/** `user` events may be surfaced to end users; `internal` never are. */
|
|
149
|
+
visibility: 'user' | 'internal';
|
|
150
|
+
data: Record<string, unknown>;
|
|
151
|
+
}
|
|
152
|
+
export type ModelItem = {
|
|
153
|
+
role: 'user' | 'assistant' | 'system';
|
|
154
|
+
content: string;
|
|
155
|
+
} | {
|
|
156
|
+
type: 'function_call';
|
|
157
|
+
callId: string;
|
|
158
|
+
name: string;
|
|
159
|
+
arguments: string;
|
|
160
|
+
} | {
|
|
161
|
+
type: 'function_call_output';
|
|
162
|
+
callId: string;
|
|
163
|
+
output: string;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Durable conversational state of one agent session, saved with optimistic
|
|
167
|
+
* concurrency (`revision`).
|
|
168
|
+
*/
|
|
169
|
+
export interface SessionRecord {
|
|
170
|
+
request?: import('../context/request.js').RequestSnapshot;
|
|
171
|
+
key: string;
|
|
172
|
+
tenantId: string;
|
|
173
|
+
agentId: string;
|
|
174
|
+
sessionId: string;
|
|
175
|
+
threadId?: string;
|
|
176
|
+
summary?: string;
|
|
177
|
+
history: ModelItem[];
|
|
178
|
+
/** Work ids whose turn input is already folded into `history`. */
|
|
179
|
+
appliedWorkIds: string[];
|
|
180
|
+
revision: number;
|
|
181
|
+
compactionEpoch: number;
|
|
182
|
+
/** Frozen system-prompt context; rebuilt when its source versions change. */
|
|
183
|
+
promptContext?: PromptContext;
|
|
184
|
+
}
|
|
185
|
+
/** Composite key shared by sessions, kernel affinity, and lease exclusivity. */
|
|
186
|
+
export declare function sessionKeyOf(work: Pick<WorkItem, 'tenantId' | 'agentId' | 'sessionId' | 'threadId'>): string;
|
|
187
|
+
/**
|
|
188
|
+
* The cache-stable prefix of the model conversation. Frozen into the session
|
|
189
|
+
* and only rebuilt when a source version changes, so provider prompt caches
|
|
190
|
+
* stay warm across turns.
|
|
191
|
+
*/
|
|
192
|
+
export interface PromptContext {
|
|
193
|
+
version: 2;
|
|
194
|
+
epoch: number;
|
|
195
|
+
assembledAt: string;
|
|
196
|
+
systemInstructions: string;
|
|
197
|
+
persona: {
|
|
198
|
+
name: string;
|
|
199
|
+
role: string;
|
|
200
|
+
instructions: string;
|
|
201
|
+
};
|
|
202
|
+
capabilities: string[];
|
|
203
|
+
/** Versions of everything folded into `systemInstructions`. */
|
|
204
|
+
sourceVersions: Record<string, string>;
|
|
205
|
+
}
|
|
206
|
+
export interface ContextMessage {
|
|
207
|
+
ref: string;
|
|
208
|
+
authorId: string;
|
|
209
|
+
authorName: string;
|
|
210
|
+
authorKind: 'human' | 'agent' | 'system';
|
|
211
|
+
body: string;
|
|
212
|
+
createdAt: string;
|
|
213
|
+
replyToRef?: string;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Everything the runtime needs to run one attempt. Split into a cache-stable
|
|
217
|
+
* candidate prompt context and per-turn dynamic context that is never frozen
|
|
218
|
+
* into the session.
|
|
219
|
+
*/
|
|
220
|
+
export interface TurnContext {
|
|
221
|
+
memory?: import('../memory/store.js').MemorySnapshot;
|
|
222
|
+
/** Prior attempt records only; files must be rechecked before current delivery. */
|
|
223
|
+
priorArtifacts?: KernelArtifact[];
|
|
224
|
+
evidence?: import('../context/evidence.js').EvidenceItem[];
|
|
225
|
+
work: WorkItem;
|
|
226
|
+
persona: {
|
|
227
|
+
name: string;
|
|
228
|
+
role: string;
|
|
229
|
+
instructions: string;
|
|
230
|
+
};
|
|
231
|
+
capabilities: string[];
|
|
232
|
+
messages: ContextMessage[];
|
|
233
|
+
promptContextCandidate?: PromptContext;
|
|
234
|
+
pendingApproval?: ApprovalResolution;
|
|
235
|
+
/**
|
|
236
|
+
* Deployment-defined per-turn context (retrieval results, live product
|
|
237
|
+
* state…). Rendered by the active RuntimePolicy; opaque to the core.
|
|
238
|
+
*/
|
|
239
|
+
dynamic?: Record<string, unknown>;
|
|
240
|
+
}
|
|
241
|
+
export interface SteerInput {
|
|
242
|
+
id: string;
|
|
243
|
+
text: string;
|
|
244
|
+
createdAt: string;
|
|
245
|
+
attachments?: import('../context/attachments.js').RequestAttachment[];
|
|
246
|
+
}
|
|
247
|
+
export interface HeartbeatResult {
|
|
248
|
+
ok: boolean;
|
|
249
|
+
cancelRequested?: boolean;
|
|
250
|
+
preemptRequested?: boolean;
|
|
251
|
+
steer?: SteerInput[];
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The final user-visible assistant message of a turn. The control plane
|
|
255
|
+
* verifies `body` byte-for-byte against the durably streamed deltas of the
|
|
256
|
+
* same attempt before delivering it.
|
|
257
|
+
*/
|
|
258
|
+
export interface AssistantMessage {
|
|
259
|
+
envelope: import('../outcome/envelope.js').ResponseEnvelope;
|
|
260
|
+
version: 2;
|
|
261
|
+
runId: string;
|
|
262
|
+
agentId: string;
|
|
263
|
+
sessionId: string;
|
|
264
|
+
threadId?: string;
|
|
265
|
+
body: string;
|
|
266
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core protocol types shared by the control plane, workers, kernels, and
|
|
3
|
+
* extensions. This module is intentionally logic-free: every layer depends on
|
|
4
|
+
* it and it depends on nothing.
|
|
5
|
+
*/
|
|
6
|
+
export const WORK_LANE_PRIORITY = Object.freeze({
|
|
7
|
+
interactive: 4,
|
|
8
|
+
approval: 3,
|
|
9
|
+
collaboration: 2,
|
|
10
|
+
background: 1,
|
|
11
|
+
});
|
|
12
|
+
export function actionKeyOf(action) {
|
|
13
|
+
return JSON.stringify([action.runId, action.cellId, action.callIndex]);
|
|
14
|
+
}
|
|
15
|
+
/** Composite key shared by sessions, kernel affinity, and lease exclusivity. */
|
|
16
|
+
export function sessionKeyOf(work) {
|
|
17
|
+
return JSON.stringify([work.tenantId, work.agentId, work.sessionId, work.threadId ?? null]);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/protocol/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,MAAM,CAAC,MAAM,kBAAkB,GAAuC,MAAM,CAAC,MAAM,CAAC;IAClF,WAAW,EAAE,CAAC;IACd,QAAQ,EAAE,CAAC;IACX,aAAa,EAAE,CAAC;IAChB,UAAU,EAAE,CAAC;CACd,CAAC,CAAA;AA0FF,MAAM,UAAU,WAAW,CAAC,MAA0D;IACpF,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;AACxE,CAAC;AAyGD,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,IAAuE;IAClG,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAA;AAC7F,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BlockList, isIP } from 'node:net';
|
|
2
|
+
const blocked = new BlockList();
|
|
3
|
+
for (const [address, prefix] of [
|
|
4
|
+
['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10], ['127.0.0.0', 8],
|
|
5
|
+
['169.254.0.0', 16], ['172.16.0.0', 12], ['192.0.0.0', 24], ['192.0.2.0', 24],
|
|
6
|
+
['192.168.0.0', 16], ['198.18.0.0', 15], ['198.51.100.0', 24], ['203.0.113.0', 24],
|
|
7
|
+
['224.0.0.0', 4], ['240.0.0.0', 4],
|
|
8
|
+
])
|
|
9
|
+
blocked.addSubnet(address, prefix, 'ipv4');
|
|
10
|
+
const globalV6 = new BlockList();
|
|
11
|
+
globalV6.addSubnet('2000::', 3, 'ipv6');
|
|
12
|
+
for (const [address, prefix] of [['2001::', 23], ['2001:db8::', 32], ['2002::', 16], ['3fff::', 20]]) {
|
|
13
|
+
blocked.addSubnet(address, prefix, 'ipv6');
|
|
14
|
+
}
|
|
15
|
+
export function isPublicAddress(address) {
|
|
16
|
+
const family = isIP(address);
|
|
17
|
+
if (family === 4)
|
|
18
|
+
return !blocked.check(address, 'ipv4');
|
|
19
|
+
return family === 6 && globalV6.check(address, 'ipv6') && !blocked.check(address, 'ipv6');
|
|
20
|
+
}
|
|
21
|
+
export function researchUrl(raw) {
|
|
22
|
+
if (raw.length > 2048)
|
|
23
|
+
throw new Error('research URL is too long');
|
|
24
|
+
const url = new URL(raw);
|
|
25
|
+
if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password)
|
|
26
|
+
throw new Error('research URL requires HTTP(S) without credentials');
|
|
27
|
+
const host = url.hostname.replace(/^\[|\]$/g, '').toLowerCase();
|
|
28
|
+
if (!host || host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local') || (isIP(host) && !isPublicAddress(host)))
|
|
29
|
+
throw new Error('research URL host is blocked');
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","sourceRoot":"","sources":["../../../src/research/address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,OAAO,GAAG,IAAI,SAAS,EAAE,CAAA;AAC/B,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI;IAC9B,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACrE,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC7E,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC;IAClF,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;CAC1B;IAAE,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AACtD,MAAM,QAAQ,GAAG,IAAI,SAAS,EAAE,CAAA;AAChC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;AACvC,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAU,EAAE,CAAC;IAC9G,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5B,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACxD,OAAO,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAC3F,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAClE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACrJ,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IAC/D,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACtL,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { lookup } from 'node:dns/promises';
|
|
2
|
+
import { request as httpRequest } from 'node:http';
|
|
3
|
+
import { request as httpsRequest } from 'node:https';
|
|
4
|
+
import { isIP } from 'node:net';
|
|
5
|
+
import { isPublicAddress, researchUrl } from './address.js';
|
|
6
|
+
const MAX_BYTES = 2 * 1024 * 1024;
|
|
7
|
+
export function pinnedRequestOptions(url, address) {
|
|
8
|
+
if (!isPublicAddress(address))
|
|
9
|
+
throw new Error('research address is blocked');
|
|
10
|
+
const host = url.hostname.replace(/^\[|\]$/g, '');
|
|
11
|
+
return { hostname: address, agent: false,
|
|
12
|
+
...(!isIP(host) ? { servername: host } : {}),
|
|
13
|
+
headers: { host: url.host, accept: 'text/html,application/json,text/plain', 'accept-encoding': 'identity', 'user-agent': 'LingxiOS-Research/1.0' },
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function fetchResearch(raw) {
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
let timeout;
|
|
19
|
+
const expired = new Promise((_resolve, reject) => {
|
|
20
|
+
timeout = setTimeout(() => { controller.abort(); reject(new Error('research request timed out')); }, 15_000);
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
return await Promise.race([expired, (async () => {
|
|
24
|
+
let url = researchUrl(raw);
|
|
25
|
+
for (let redirects = 0; redirects <= 5; redirects++) {
|
|
26
|
+
const host = url.hostname.replace(/^\[|\]$/g, '');
|
|
27
|
+
const addresses = isIP(host) ? [{ address: host }] : await lookup(host, { all: true, verbatim: true });
|
|
28
|
+
if (!addresses.length || addresses.some(item => !isPublicAddress(item.address)))
|
|
29
|
+
throw new Error('research DNS resolved to a blocked address');
|
|
30
|
+
controller.signal.throwIfAborted();
|
|
31
|
+
const result = await new Promise((resolve, reject) => {
|
|
32
|
+
const request = (url.protocol === 'https:' ? httpsRequest : httpRequest)(url, {
|
|
33
|
+
...pinnedRequestOptions(url, addresses[0].address), signal: controller.signal,
|
|
34
|
+
}, response => {
|
|
35
|
+
const status = response.statusCode ?? 0;
|
|
36
|
+
if (status >= 300 && status < 400) {
|
|
37
|
+
const location = response.headers.location;
|
|
38
|
+
response.destroy();
|
|
39
|
+
if (!location)
|
|
40
|
+
reject(new Error('research redirect has no location'));
|
|
41
|
+
else
|
|
42
|
+
resolve({ redirect: location });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (status < 200 || status >= 300 || Number(response.headers['content-length'] ?? 0) > MAX_BYTES) {
|
|
46
|
+
response.destroy();
|
|
47
|
+
reject(new Error(`research response rejected (HTTP ${status}, size limit ${MAX_BYTES})`));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (response.headers['content-encoding'] && response.headers['content-encoding'] !== 'identity') {
|
|
51
|
+
response.destroy();
|
|
52
|
+
reject(new Error('research source returned unsupported content encoding'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const chunks = [];
|
|
56
|
+
let size = 0;
|
|
57
|
+
response.on('data', (chunk) => {
|
|
58
|
+
size += chunk.length;
|
|
59
|
+
if (size > MAX_BYTES)
|
|
60
|
+
response.destroy(new Error('research source exceeds 2 MiB'));
|
|
61
|
+
else
|
|
62
|
+
chunks.push(chunk);
|
|
63
|
+
});
|
|
64
|
+
response.on('error', reject);
|
|
65
|
+
response.on('end', () => resolve({ url: url.href, contentType: String(response.headers['content-type'] ?? 'application/octet-stream').split(';')[0].toLowerCase(), body: Buffer.concat(chunks) }));
|
|
66
|
+
});
|
|
67
|
+
request.on('error', reject);
|
|
68
|
+
request.end();
|
|
69
|
+
});
|
|
70
|
+
if (!('redirect' in result))
|
|
71
|
+
return result;
|
|
72
|
+
if (redirects === 5)
|
|
73
|
+
throw new Error('research source redirected too many times');
|
|
74
|
+
url = researchUrl(new URL(result.redirect, url).href);
|
|
75
|
+
}
|
|
76
|
+
throw new Error('research redirect limit exceeded');
|
|
77
|
+
})()]);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
clearTimeout(timeout);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/research/fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ResearchSearchResult {
|
|
2
|
+
title: string;
|
|
3
|
+
url: string;
|
|
4
|
+
doi?: string;
|
|
5
|
+
publicationYear?: number;
|
|
6
|
+
authors: string[];
|
|
7
|
+
abstract?: string;
|
|
8
|
+
citedByCount?: number;
|
|
9
|
+
source: 'OpenAlex';
|
|
10
|
+
}
|
|
11
|
+
export declare function searchResearch(query: string, limit?: number): Promise<{
|
|
12
|
+
provider: 'OpenAlex';
|
|
13
|
+
query: string;
|
|
14
|
+
results: ResearchSearchResult[];
|
|
15
|
+
}>;
|
|
16
|
+
export declare function parseOpenAlex(value: unknown, count: number): ResearchSearchResult[];
|
|
17
|
+
export declare function decodeHtml(value: string): string;
|
|
18
|
+
export declare function readResearch(rawUrl: string): Promise<{
|
|
19
|
+
url: string;
|
|
20
|
+
finalUrl: string;
|
|
21
|
+
contentType: string;
|
|
22
|
+
text: string;
|
|
23
|
+
bytes: number;
|
|
24
|
+
sha256: string;
|
|
25
|
+
truncated: boolean;
|
|
26
|
+
}>;
|