@sumeru/server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -0
- package/dist/.build-fingerprint +1 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +142 -0
- package/dist/config.js.map +1 -0
- package/dist/envelope.d.ts +28 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +43 -0
- package/dist/envelope.js.map +1 -0
- package/dist/export/bundle.d.ts +28 -0
- package/dist/export/bundle.d.ts.map +1 -0
- package/dist/export/bundle.js +78 -0
- package/dist/export/bundle.js.map +1 -0
- package/dist/export/handler.d.ts +24 -0
- package/dist/export/handler.d.ts.map +1 -0
- package/dist/export/handler.js +102 -0
- package/dist/export/handler.js.map +1 -0
- package/dist/export/index.d.ts +3 -0
- package/dist/export/index.d.ts.map +1 -0
- package/dist/export/index.js +3 -0
- package/dist/export/index.js.map +1 -0
- package/dist/handler.d.ts +24 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +622 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/ocas/index.d.ts +3 -0
- package/dist/ocas/index.d.ts.map +1 -0
- package/dist/ocas/index.js +3 -0
- package/dist/ocas/index.js.map +1 -0
- package/dist/ocas/schemas.d.ts +41 -0
- package/dist/ocas/schemas.d.ts.map +1 -0
- package/dist/ocas/schemas.js +108 -0
- package/dist/ocas/schemas.js.map +1 -0
- package/dist/ocas/store.d.ts +58 -0
- package/dist/ocas/store.d.ts.map +1 -0
- package/dist/ocas/store.js +139 -0
- package/dist/ocas/store.js.map +1 -0
- package/dist/search/handler.d.ts +54 -0
- package/dist/search/handler.d.ts.map +1 -0
- package/dist/search/handler.js +178 -0
- package/dist/search/handler.js.map +1 -0
- package/dist/search/index.d.ts +4 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +3 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/sqlite-index.d.ts +49 -0
- package/dist/search/sqlite-index.d.ts.map +1 -0
- package/dist/search/sqlite-index.js +508 -0
- package/dist/search/sqlite-index.js.map +1 -0
- package/dist/search/types.d.ts +143 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +10 -0
- package/dist/search/types.js.map +1 -0
- package/dist/session/cwd.d.ts +31 -0
- package/dist/session/cwd.d.ts.map +1 -0
- package/dist/session/cwd.js +54 -0
- package/dist/session/cwd.js.map +1 -0
- package/dist/session/id.d.ts +12 -0
- package/dist/session/id.d.ts.map +1 -0
- package/dist/session/id.js +76 -0
- package/dist/session/id.js.map +1 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +4 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/store.d.ts +89 -0
- package/dist/session/store.d.ts.map +1 -0
- package/dist/session/store.js +258 -0
- package/dist/session/store.js.map +1 -0
- package/dist/sse/buffer.d.ts +53 -0
- package/dist/sse/buffer.d.ts.map +1 -0
- package/dist/sse/buffer.js +119 -0
- package/dist/sse/buffer.js.map +1 -0
- package/dist/sse/index.d.ts +3 -0
- package/dist/sse/index.d.ts.map +1 -0
- package/dist/sse/index.js +3 -0
- package/dist/sse/index.js.map +1 -0
- package/dist/sse/messages.d.ts +30 -0
- package/dist/sse/messages.d.ts.map +1 -0
- package/dist/sse/messages.js +489 -0
- package/dist/sse/messages.js.map +1 -0
- package/dist/start.d.ts +22 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +86 -0
- package/dist/start.js.map +1 -0
- package/dist/types.d.ts +252 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +31 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { loadConfig } from "./config.js";
|
|
2
|
+
export { envelope, errorEnvelope, gatewayEnvelope, gatewayListEnvelope, instanceEnvelope, searchResultEnvelope, sessionEnvelope, sessionListEnvelope, } from "./envelope.js";
|
|
3
|
+
export { buildSessionExport } from "./export/index.js";
|
|
4
|
+
export { createHandler } from "./handler.js";
|
|
5
|
+
export { getRegisteredSchema, openSumeruOcas, recordPayload, SUMERU_SESSION_META_SCHEMA, SUMERU_SESSION_META_SCHEMA_HASH, SUMERU_TURN_SCHEMA, SUMERU_TURN_SCHEMA_HASH, type SumeruOcas, validatePayload, } from "./ocas/index.js";
|
|
6
|
+
export { createSearchIndex, quoteFtsPhrase, rebuildSearchIndex, type SearchHit, type SearchIndex, type SearchOptions, type SearchResult, searchSessions, } from "./search/index.js";
|
|
7
|
+
export type { SessionStore, TransitionResult } from "./session/index.js";
|
|
8
|
+
export { createSessionStore, generateSessionId, type ResolveCwdResult, resolveSessionCwd, } from "./session/index.js";
|
|
9
|
+
export { toWire } from "./session/store.js";
|
|
10
|
+
export { resolveOcasDir, startServer } from "./start.js";
|
|
11
|
+
export type { Envelope, ErrorValue, Gateway, GatewayCapabilities, GatewayConfig, Instance, InstanceConfig, MessageHistoryValue, OcasConfig, SearchResultHit, SearchResultValue, ServerConfig, Session, SessionListEntry, SessionStatus, SessionWire, StartConfig, StartedServer, TurnValue, UserSessionConfig, } from "./types.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,QAAQ,EACR,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,UAAU,EACf,eAAe,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,iBAAiB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EACX,QAAQ,EACR,UAAU,EACV,OAAO,EACP,mBAAmB,EACnB,aAAa,EACb,QAAQ,EACR,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { loadConfig } from "./config.js";
|
|
2
|
+
export { envelope, errorEnvelope, gatewayEnvelope, gatewayListEnvelope, instanceEnvelope, searchResultEnvelope, sessionEnvelope, sessionListEnvelope, } from "./envelope.js";
|
|
3
|
+
export { buildSessionExport } from "./export/index.js";
|
|
4
|
+
export { createHandler } from "./handler.js";
|
|
5
|
+
export { getRegisteredSchema, openSumeruOcas, recordPayload, SUMERU_SESSION_META_SCHEMA, SUMERU_SESSION_META_SCHEMA_HASH, SUMERU_TURN_SCHEMA, SUMERU_TURN_SCHEMA_HASH, validatePayload, } from "./ocas/index.js";
|
|
6
|
+
export { createSearchIndex, quoteFtsPhrase, rebuildSearchIndex, searchSessions, } from "./search/index.js";
|
|
7
|
+
export { createSessionStore, generateSessionId, resolveSessionCwd, } from "./session/index.js";
|
|
8
|
+
export { toWire } from "./session/store.js";
|
|
9
|
+
export { resolveOcasDir, startServer } from "./start.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,QAAQ,EACR,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,uBAAuB,EAEvB,eAAe,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAKlB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EAEjB,iBAAiB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { SUMERU_SESSION_META_SCHEMA, SUMERU_SESSION_META_SCHEMA_HASH, SUMERU_TURN_SCHEMA, SUMERU_TURN_SCHEMA_HASH, } from "./schemas.js";
|
|
2
|
+
export { getRegisteredSchema, openSumeruOcas, recordPayload, type SumeruOcas, validatePayload, } from "./store.js";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ocas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,KAAK,UAAU,EACf,eAAe,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ocas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,eAAe,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schemas registered against the ocas store at startup.
|
|
3
|
+
*
|
|
4
|
+
* The schema bodies are byte-stable contracts — the schema hash is a function
|
|
5
|
+
* of the schema body, so changing field order or adding properties changes
|
|
6
|
+
* the hash. Treat these definitions as immutable.
|
|
7
|
+
*/
|
|
8
|
+
import type { Hash, JSONSchema } from "@ocas/core";
|
|
9
|
+
/**
|
|
10
|
+
* `@sumeru/session-meta` — per-session metadata snapshot, written once at
|
|
11
|
+
* session create. `additionalProperties: false` forces opaque adapter config
|
|
12
|
+
* to live inside the `config` field rather than at the top level.
|
|
13
|
+
*
|
|
14
|
+
* `resolvedCwd` (issue #27) records the absolute path that Sumeru actually
|
|
15
|
+
* forwarded to the adapter under the well-known `config.cwd` key, AFTER
|
|
16
|
+
* `resolveSessionCwd` resolved it against the instance `workspaceRoot`. It is
|
|
17
|
+
* `null` when the client did not send `config.cwd` (no cwd hint), and a
|
|
18
|
+
* non-empty string otherwise. The original opaque `config` blob is preserved
|
|
19
|
+
* verbatim so `config.cwd` (if present) and `resolvedCwd` together describe
|
|
20
|
+
* the request → resolution mapping.
|
|
21
|
+
*/
|
|
22
|
+
export declare const SUMERU_SESSION_META_SCHEMA: JSONSchema;
|
|
23
|
+
/**
|
|
24
|
+
* Pre-computed hash of `SUMERU_SESSION_META_SCHEMA`. Hardcoded to avoid
|
|
25
|
+
* requiring WASM init (`initHasher()`) at import time. A test asserts this
|
|
26
|
+
* stays in sync with `computeSelfHashSync(SUMERU_SESSION_META_SCHEMA)`.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SUMERU_SESSION_META_SCHEMA_HASH: Hash;
|
|
29
|
+
/**
|
|
30
|
+
* `@sumeru/turn` — one turn in a session. Used for both user and assistant
|
|
31
|
+
* turns; the `role` enum excludes "system" because Sumeru does not record
|
|
32
|
+
* system turns through the message endpoint.
|
|
33
|
+
*/
|
|
34
|
+
export declare const SUMERU_TURN_SCHEMA: JSONSchema;
|
|
35
|
+
/**
|
|
36
|
+
* Pre-computed hash of `SUMERU_TURN_SCHEMA`. Hardcoded to avoid requiring
|
|
37
|
+
* WASM init (`initHasher()`) at import time. A test asserts this stays in
|
|
38
|
+
* sync with `computeSelfHashSync(SUMERU_TURN_SCHEMA)`.
|
|
39
|
+
*/
|
|
40
|
+
export declare const SUMERU_TURN_SCHEMA_HASH: Hash;
|
|
41
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/ocas/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,EAAE,UAgBxC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,EAAE,IAAsB,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAqDhC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,IAAsB,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schemas registered against the ocas store at startup.
|
|
3
|
+
*
|
|
4
|
+
* The schema bodies are byte-stable contracts — the schema hash is a function
|
|
5
|
+
* of the schema body, so changing field order or adding properties changes
|
|
6
|
+
* the hash. Treat these definitions as immutable.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* `@sumeru/session-meta` — per-session metadata snapshot, written once at
|
|
10
|
+
* session create. `additionalProperties: false` forces opaque adapter config
|
|
11
|
+
* to live inside the `config` field rather than at the top level.
|
|
12
|
+
*
|
|
13
|
+
* `resolvedCwd` (issue #27) records the absolute path that Sumeru actually
|
|
14
|
+
* forwarded to the adapter under the well-known `config.cwd` key, AFTER
|
|
15
|
+
* `resolveSessionCwd` resolved it against the instance `workspaceRoot`. It is
|
|
16
|
+
* `null` when the client did not send `config.cwd` (no cwd hint), and a
|
|
17
|
+
* non-empty string otherwise. The original opaque `config` blob is preserved
|
|
18
|
+
* verbatim so `config.cwd` (if present) and `resolvedCwd` together describe
|
|
19
|
+
* the request → resolution mapping.
|
|
20
|
+
*/
|
|
21
|
+
export const SUMERU_SESSION_META_SCHEMA = {
|
|
22
|
+
title: "@sumeru/session-meta",
|
|
23
|
+
description: "Per-session metadata snapshot. Written once at session create.",
|
|
24
|
+
type: "object",
|
|
25
|
+
additionalProperties: false,
|
|
26
|
+
required: ["id", "gateway", "adapter", "createdAt", "config", "resolvedCwd"],
|
|
27
|
+
properties: {
|
|
28
|
+
id: { type: "string", pattern: "^ses_[0-9A-HJKMNP-TV-Z]{26}$" },
|
|
29
|
+
gateway: { type: "string", minLength: 1 },
|
|
30
|
+
adapter: { type: "string", minLength: 1 },
|
|
31
|
+
createdAt: { type: "string", format: "date-time" },
|
|
32
|
+
config: { type: "object" },
|
|
33
|
+
resolvedCwd: {
|
|
34
|
+
anyOf: [{ type: "null" }, { type: "string", minLength: 1 }],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Pre-computed hash of `SUMERU_SESSION_META_SCHEMA`. Hardcoded to avoid
|
|
40
|
+
* requiring WASM init (`initHasher()`) at import time. A test asserts this
|
|
41
|
+
* stays in sync with `computeSelfHashSync(SUMERU_SESSION_META_SCHEMA)`.
|
|
42
|
+
*/
|
|
43
|
+
export const SUMERU_SESSION_META_SCHEMA_HASH = "5C30THA7BZ814";
|
|
44
|
+
/**
|
|
45
|
+
* `@sumeru/turn` — one turn in a session. Used for both user and assistant
|
|
46
|
+
* turns; the `role` enum excludes "system" because Sumeru does not record
|
|
47
|
+
* system turns through the message endpoint.
|
|
48
|
+
*/
|
|
49
|
+
export const SUMERU_TURN_SCHEMA = {
|
|
50
|
+
title: "@sumeru/turn",
|
|
51
|
+
description: "One turn in a session — a user message OR an assistant response.",
|
|
52
|
+
type: "object",
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
required: ["index", "role", "content", "timestamp", "toolCalls"],
|
|
55
|
+
properties: {
|
|
56
|
+
index: { type: "integer", minimum: 0 },
|
|
57
|
+
role: { type: "string", enum: ["user", "assistant"] },
|
|
58
|
+
content: { type: "string" },
|
|
59
|
+
timestamp: { type: "string", format: "date-time" },
|
|
60
|
+
toolCalls: {
|
|
61
|
+
anyOf: [
|
|
62
|
+
{ type: "null" },
|
|
63
|
+
{
|
|
64
|
+
type: "array",
|
|
65
|
+
items: {
|
|
66
|
+
type: "object",
|
|
67
|
+
additionalProperties: false,
|
|
68
|
+
required: ["tool", "input", "output", "durationMs", "exitCode"],
|
|
69
|
+
properties: {
|
|
70
|
+
tool: { type: "string", minLength: 1 },
|
|
71
|
+
input: { type: "object" },
|
|
72
|
+
output: {
|
|
73
|
+
anyOf: [{ type: "null" }, { type: "string" }],
|
|
74
|
+
},
|
|
75
|
+
durationMs: {
|
|
76
|
+
anyOf: [{ type: "null" }, { type: "integer", minimum: 0 }],
|
|
77
|
+
},
|
|
78
|
+
exitCode: {
|
|
79
|
+
anyOf: [{ type: "null" }, { type: "integer" }],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
tokens: {
|
|
87
|
+
anyOf: [
|
|
88
|
+
{ type: "null" },
|
|
89
|
+
{
|
|
90
|
+
type: "object",
|
|
91
|
+
additionalProperties: false,
|
|
92
|
+
required: ["input", "output"],
|
|
93
|
+
properties: {
|
|
94
|
+
input: { type: "integer", minimum: 0 },
|
|
95
|
+
output: { type: "integer", minimum: 0 },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Pre-computed hash of `SUMERU_TURN_SCHEMA`. Hardcoded to avoid requiring
|
|
104
|
+
* WASM init (`initHasher()`) at import time. A test asserts this stays in
|
|
105
|
+
* sync with `computeSelfHashSync(SUMERU_TURN_SCHEMA)`.
|
|
106
|
+
*/
|
|
107
|
+
export const SUMERU_TURN_SCHEMA_HASH = "718S3WF704TZ6";
|
|
108
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/ocas/schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sumeru ocas store wrapper — opens an `@ocas/fs` CAS-backed store, runs
|
|
3
|
+
* bootstrap so the schema-of-schemas exists, and registers the two Sumeru
|
|
4
|
+
* schemas. Exposes the resulting `Store` and the schema hashes.
|
|
5
|
+
*
|
|
6
|
+
* The wrapper validates payloads against their schema before writing.
|
|
7
|
+
* `@ocas/core.Store.cas.put` is intentionally non-validating; recording paths
|
|
8
|
+
* always go through {@link recordTurn} / {@link recordSessionMeta} so invalid
|
|
9
|
+
* payloads are rejected before they reach disk.
|
|
10
|
+
*/
|
|
11
|
+
import { type Hash, type JSONSchema, type Store } from "@ocas/core";
|
|
12
|
+
import { type SearchIndex } from "../search/index.js";
|
|
13
|
+
/** Hash alias for the schema-of-schemas (assigned at bootstrap). */
|
|
14
|
+
export type SumeruOcas = {
|
|
15
|
+
store: Store;
|
|
16
|
+
turnSchemaHash: Hash;
|
|
17
|
+
sessionMetaSchemaHash: Hash;
|
|
18
|
+
/** Schema-of-schemas hash from `@ocas/core` bootstrap. */
|
|
19
|
+
metaSchemaHash: Hash;
|
|
20
|
+
/** Map: schema hash → human alias for the `/ocas/:hash` endpoint. */
|
|
21
|
+
schemaAliases: Record<Hash, string>;
|
|
22
|
+
/** Phase 5: FTS5-backed session search index. */
|
|
23
|
+
searchIndex: SearchIndex;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Open or create the on-disk store at `dir`. Creates the directory if needed.
|
|
27
|
+
* Bootstraps `@ocas/core` schemas and registers `@sumeru/turn` +
|
|
28
|
+
* `@sumeru/session-meta`.
|
|
29
|
+
*
|
|
30
|
+
* Throws with a `failed to open ocas store at <dir>: <cause>` message when
|
|
31
|
+
* the directory cannot be created or accessed.
|
|
32
|
+
*/
|
|
33
|
+
export declare function openSumeruOcas(dir: string): SumeruOcas;
|
|
34
|
+
/**
|
|
35
|
+
* Validate `payload` against the schema identified by `schemaHash`. Throws
|
|
36
|
+
* `SchemaValidationError` if invalid.
|
|
37
|
+
*
|
|
38
|
+
* This is needed because `@ocas/core.Store.cas.put` does not validate — it
|
|
39
|
+
* just hashes and stores. We always validate before writing recording data
|
|
40
|
+
* so corrupted nodes never land in the store.
|
|
41
|
+
*
|
|
42
|
+
* The validator is our own ajv instance (not `@ocas/core`'s internal one)
|
|
43
|
+
* so we can recognise the `date-time` format without pulling in
|
|
44
|
+
* `ajv-formats`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function validatePayload(store: Store, schemaHash: Hash, payload: unknown): void;
|
|
47
|
+
/**
|
|
48
|
+
* Validate `payload` and put it in the store. Returns the resulting hash.
|
|
49
|
+
* Wraps `store.cas.put` with a pre-write validation step.
|
|
50
|
+
*/
|
|
51
|
+
export declare function recordPayload(store: Store, schemaHash: Hash, payload: unknown): Hash;
|
|
52
|
+
/**
|
|
53
|
+
* Look up a schema body. Returns `null` if `schemaHash` is not in the store.
|
|
54
|
+
* Convenience wrapper kept here so handlers don't need to import @ocas/core
|
|
55
|
+
* directly for trivial reads.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getRegisteredSchema(store: Store, schemaHash: Hash): JSONSchema | null;
|
|
58
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/ocas/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAEN,KAAK,IAAI,EACT,KAAK,UAAU,EAGf,KAAK,KAAK,EACV,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAyBzE,oEAAoE;AACpE,MAAM,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,IAAI,CAAC;IACrB,qBAAqB,EAAE,IAAI,CAAC;IAC5B,0DAA0D;IAC1D,cAAc,EAAE,IAAI,CAAC;IACrB,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,iDAAiD;IACjD,WAAW,EAAE,WAAW,CAAC;CACzB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAsDtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC9B,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,OAAO,GACd,IAAI,CAkBN;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,OAAO,GACd,IAAI,CAGN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,IAAI,GACd,UAAU,GAAG,IAAI,CAInB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sumeru ocas store wrapper — opens an `@ocas/fs` CAS-backed store, runs
|
|
3
|
+
* bootstrap so the schema-of-schemas exists, and registers the two Sumeru
|
|
4
|
+
* schemas. Exposes the resulting `Store` and the schema hashes.
|
|
5
|
+
*
|
|
6
|
+
* The wrapper validates payloads against their schema before writing.
|
|
7
|
+
* `@ocas/core.Store.cas.put` is intentionally non-validating; recording paths
|
|
8
|
+
* always go through {@link recordTurn} / {@link recordSessionMeta} so invalid
|
|
9
|
+
* payloads are rejected before they reach disk.
|
|
10
|
+
*/
|
|
11
|
+
import { mkdirSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { bootstrap, putSchema, SchemaValidationError, } from "@ocas/core";
|
|
14
|
+
import { createFsStore, createSqliteVarStore } from "@ocas/fs";
|
|
15
|
+
import * as AjvModule from "ajv";
|
|
16
|
+
import { createSearchIndex } from "../search/index.js";
|
|
17
|
+
import { SUMERU_SESSION_META_SCHEMA, SUMERU_TURN_SCHEMA } from "./schemas.js";
|
|
18
|
+
// ajv CJS interop: the constructor lives on `.default` at runtime, but the
|
|
19
|
+
// namespace shape is what tsc's verbatimModuleSyntax surfaces.
|
|
20
|
+
// biome-ignore lint/suspicious/noExplicitAny: CJS interop
|
|
21
|
+
const Ajv = (AjvModule.default ??
|
|
22
|
+
AjvModule);
|
|
23
|
+
/**
|
|
24
|
+
* Local ajv instance used for validating Sumeru recording payloads. We do not
|
|
25
|
+
* reuse `@ocas/core`'s internal ajv because we need the `date-time` format
|
|
26
|
+
* registered (without pulling in `ajv-formats`).
|
|
27
|
+
*
|
|
28
|
+
* `date-time` is registered with a permissive ISO-8601 regex matching what
|
|
29
|
+
* `Date.prototype.toISOString` emits — sufficient for validating timestamps
|
|
30
|
+
* the server itself produces.
|
|
31
|
+
*/
|
|
32
|
+
const ajv = new Ajv();
|
|
33
|
+
ajv.addFormat("ocas_ref", /^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
34
|
+
ajv.addFormat("date-time", /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})$/);
|
|
35
|
+
/**
|
|
36
|
+
* Open or create the on-disk store at `dir`. Creates the directory if needed.
|
|
37
|
+
* Bootstraps `@ocas/core` schemas and registers `@sumeru/turn` +
|
|
38
|
+
* `@sumeru/session-meta`.
|
|
39
|
+
*
|
|
40
|
+
* Throws with a `failed to open ocas store at <dir>: <cause>` message when
|
|
41
|
+
* the directory cannot be created or accessed.
|
|
42
|
+
*/
|
|
43
|
+
export function openSumeruOcas(dir) {
|
|
44
|
+
let store;
|
|
45
|
+
try {
|
|
46
|
+
// Ensure parent + dir exist before handing off to @ocas/fs.
|
|
47
|
+
mkdirSync(dir, { recursive: true });
|
|
48
|
+
const cas = createFsStore(dir);
|
|
49
|
+
const sqlite = createSqliteVarStore(dir, cas);
|
|
50
|
+
store = { cas, var: sqlite.var, tag: sqlite.tag };
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
54
|
+
throw new Error(`failed to open ocas store at ${dir}: ${cause}`);
|
|
55
|
+
}
|
|
56
|
+
let aliases;
|
|
57
|
+
try {
|
|
58
|
+
aliases = bootstrap(store);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
62
|
+
throw new Error(`failed to open ocas store at ${dir}: ${cause}`);
|
|
63
|
+
}
|
|
64
|
+
const turnSchemaHash = putSchema(store, SUMERU_TURN_SCHEMA);
|
|
65
|
+
const sessionMetaSchemaHash = putSchema(store, SUMERU_SESSION_META_SCHEMA);
|
|
66
|
+
const metaSchemaHash = aliases["@ocas/schema"];
|
|
67
|
+
if (metaSchemaHash === undefined) {
|
|
68
|
+
throw new Error(`failed to open ocas store at ${dir}: bootstrap did not register @ocas/schema`);
|
|
69
|
+
}
|
|
70
|
+
const schemaAliases = {
|
|
71
|
+
[metaSchemaHash]: "@ocas/schema",
|
|
72
|
+
[turnSchemaHash]: "@sumeru/turn",
|
|
73
|
+
[sessionMetaSchemaHash]: "@sumeru/session-meta",
|
|
74
|
+
};
|
|
75
|
+
let searchIndex;
|
|
76
|
+
try {
|
|
77
|
+
searchIndex = createSearchIndex(join(dir, "_store.db"));
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
81
|
+
throw new Error(`failed to open ocas store at ${dir}: ${cause}`);
|
|
82
|
+
}
|
|
83
|
+
const indexedTurns = searchIndex.turnCount();
|
|
84
|
+
console.log(`[sumeru] search index ready: ${indexedTurns} turns indexed`);
|
|
85
|
+
return {
|
|
86
|
+
store,
|
|
87
|
+
turnSchemaHash,
|
|
88
|
+
sessionMetaSchemaHash,
|
|
89
|
+
metaSchemaHash,
|
|
90
|
+
schemaAliases,
|
|
91
|
+
searchIndex,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate `payload` against the schema identified by `schemaHash`. Throws
|
|
96
|
+
* `SchemaValidationError` if invalid.
|
|
97
|
+
*
|
|
98
|
+
* This is needed because `@ocas/core.Store.cas.put` does not validate — it
|
|
99
|
+
* just hashes and stores. We always validate before writing recording data
|
|
100
|
+
* so corrupted nodes never land in the store.
|
|
101
|
+
*
|
|
102
|
+
* The validator is our own ajv instance (not `@ocas/core`'s internal one)
|
|
103
|
+
* so we can recognise the `date-time` format without pulling in
|
|
104
|
+
* `ajv-formats`.
|
|
105
|
+
*/
|
|
106
|
+
export function validatePayload(store, schemaHash, payload) {
|
|
107
|
+
const schemaNode = store.cas.get(schemaHash);
|
|
108
|
+
if (schemaNode === null) {
|
|
109
|
+
throw new SchemaValidationError(`Schema ${schemaHash} is not registered in the store`);
|
|
110
|
+
}
|
|
111
|
+
const schema = schemaNode.payload;
|
|
112
|
+
const valid = ajv.validate(schema, payload);
|
|
113
|
+
if (!valid) {
|
|
114
|
+
const detail = ajv.errors !== null && ajv.errors !== undefined && ajv.errors.length > 0
|
|
115
|
+
? ajv.errorsText(ajv.errors)
|
|
116
|
+
: "(no detail)";
|
|
117
|
+
throw new SchemaValidationError(`Payload does not validate against schema ${schemaHash}: ${detail}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validate `payload` and put it in the store. Returns the resulting hash.
|
|
122
|
+
* Wraps `store.cas.put` with a pre-write validation step.
|
|
123
|
+
*/
|
|
124
|
+
export function recordPayload(store, schemaHash, payload) {
|
|
125
|
+
validatePayload(store, schemaHash, payload);
|
|
126
|
+
return store.cas.put(schemaHash, payload);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Look up a schema body. Returns `null` if `schemaHash` is not in the store.
|
|
130
|
+
* Convenience wrapper kept here so handlers don't need to import @ocas/core
|
|
131
|
+
* directly for trivial reads.
|
|
132
|
+
*/
|
|
133
|
+
export function getRegisteredSchema(store, schemaHash) {
|
|
134
|
+
const node = store.cas.get(schemaHash);
|
|
135
|
+
if (node === null)
|
|
136
|
+
return null;
|
|
137
|
+
return node.payload;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/ocas/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 5 — search HTTP handlers.
|
|
3
|
+
*
|
|
4
|
+
* Wired into `createHandler` so:
|
|
5
|
+
* - `GET /sessions?q=...` runs cross-gateway search
|
|
6
|
+
* - `GET /gateways/:name/sessions?q=...` runs per-gateway search
|
|
7
|
+
*
|
|
8
|
+
* When `q` is missing or empty after trimming, the per-gateway route falls
|
|
9
|
+
* back to the existing `@sumeru/session-list` behavior; the top-level route
|
|
10
|
+
* 400s because there is no listing fallback.
|
|
11
|
+
*/
|
|
12
|
+
import type { ServerResponse } from "node:http";
|
|
13
|
+
import type { SearchIndex } from "../search/index.js";
|
|
14
|
+
/** Result of parsing the query string for a search request. */
|
|
15
|
+
export type ParsedSearchParams = {
|
|
16
|
+
ok: true;
|
|
17
|
+
value: ParsedSearchParamsOk;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
status: 400;
|
|
21
|
+
error: string;
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
|
24
|
+
export type ParsedSearchParamsOk = {
|
|
25
|
+
/** Trimmed query. Always non-empty when `ok === true`. */
|
|
26
|
+
query: string;
|
|
27
|
+
/** When `null`, the request is for the top-level (cross-gateway) route OR no filter applied. */
|
|
28
|
+
gateway: string | null;
|
|
29
|
+
limit: number;
|
|
30
|
+
offset: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Parse `q`, `limit`, `offset`, and (top-level only) `gateway` from a query
|
|
34
|
+
* string. Trimming `q` to empty is treated as "absent" — the caller decides
|
|
35
|
+
* whether that means fall through to listing or 400.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseSearchParams(queryString: string, allowGatewayFilter: boolean): ParsedSearchParams;
|
|
38
|
+
/**
|
|
39
|
+
* Run a cross-gateway search and write the response. Caller must have
|
|
40
|
+
* already validated method == GET / HEAD.
|
|
41
|
+
*/
|
|
42
|
+
export declare function handleSearchTopLevel(res: ServerResponse, queryString: string, searchIndex: SearchIndex): void;
|
|
43
|
+
/**
|
|
44
|
+
* Run a per-gateway search and write the response. The route's gateway is
|
|
45
|
+
* authoritative; any `?gateway=` param is ignored (per spec).
|
|
46
|
+
*/
|
|
47
|
+
export declare function handleSearchPerGateway(res: ServerResponse, queryString: string, searchIndex: SearchIndex, gateway: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Detect whether a query string carries a search request (`?q=` non-empty
|
|
50
|
+
* after trimming). Used by the per-gateway sessions route to decide between
|
|
51
|
+
* the Phase-2 listing and Phase-5 search.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSearchRequest(queryString: string): boolean;
|
|
54
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/search/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAUtD,+DAA+D;AAC/D,MAAM,MAAM,kBAAkB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG;IAClC,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,OAAO,GACzB,kBAAkB,CAsDpB;AAiCD;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,cAAc,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,WAAW,GACtB,IAAI,CAON;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,GAAG,EAAE,cAAc,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,MAAM,GACb,IAAI,CAQN;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAK5D"}
|