@corenel/harness 0.1.0 → 0.2.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/dist/conversation.d.ts +0 -11
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +1 -24
- package/dist/conversation.js.map +1 -1
- package/dist/core/budget.d.ts +40 -0
- package/dist/core/budget.d.ts.map +1 -0
- package/dist/core/budget.js +62 -0
- package/dist/core/budget.js.map +1 -0
- package/dist/core/loop.d.ts +9 -0
- package/dist/core/loop.d.ts.map +1 -1
- package/dist/core/loop.js +88 -20
- package/dist/core/loop.js.map +1 -1
- package/dist/core/pricing.d.ts +8 -0
- package/dist/core/pricing.d.ts.map +1 -0
- package/dist/core/pricing.js +12 -0
- package/dist/core/pricing.js.map +1 -0
- package/dist/core/recovery.d.ts +60 -0
- package/dist/core/recovery.d.ts.map +1 -0
- package/dist/core/recovery.js +128 -0
- package/dist/core/recovery.js.map +1 -0
- package/dist/guardrail/builtins.js +6 -6
- package/dist/guardrail/builtins.js.map +1 -1
- package/dist/guardrail/permission-service.js +1 -1
- package/dist/guardrail/permission-service.js.map +1 -1
- package/dist/guardrail/serialize.d.ts.map +1 -1
- package/dist/guardrail/serialize.js +6 -0
- package/dist/guardrail/serialize.js.map +1 -1
- package/dist/guardrail/validate.d.ts.map +1 -1
- package/dist/guardrail/validate.js +13 -0
- package/dist/guardrail/validate.js.map +1 -1
- package/dist/prompts/index.d.ts +6 -0
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +12 -6
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/library/defaults.generated.d.ts.map +1 -1
- package/dist/prompts/library/defaults.generated.js +22 -4
- package/dist/prompts/library/defaults.generated.js.map +1 -1
- package/dist/prompts/toolsMarker.d.ts +13 -0
- package/dist/prompts/toolsMarker.d.ts.map +1 -0
- package/dist/prompts/toolsMarker.js +21 -0
- package/dist/prompts/toolsMarker.js.map +1 -0
- package/dist/providers/gateway.d.ts +16 -1
- package/dist/providers/gateway.d.ts.map +1 -1
- package/dist/providers/gateway.js +30 -4
- package/dist/providers/gateway.js.map +1 -1
- package/dist/services.d.ts +13 -0
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +2 -0
- package/dist/services.js.map +1 -1
- package/dist/sessions/fileRecallStore.d.ts +33 -0
- package/dist/sessions/fileRecallStore.d.ts.map +1 -0
- package/dist/sessions/fileRecallStore.js +112 -0
- package/dist/sessions/fileRecallStore.js.map +1 -0
- package/dist/sessions/fileSessionStore.d.ts +20 -0
- package/dist/sessions/fileSessionStore.d.ts.map +1 -0
- package/dist/sessions/fileSessionStore.js +151 -0
- package/dist/sessions/fileSessionStore.js.map +1 -0
- package/dist/sessions/jsonl.d.ts +23 -0
- package/dist/sessions/jsonl.d.ts.map +1 -0
- package/dist/sessions/jsonl.js +52 -0
- package/dist/sessions/jsonl.js.map +1 -0
- package/dist/sessions/testFs.d.ts +5 -0
- package/dist/sessions/testFs.d.ts.map +1 -0
- package/dist/sessions/testFs.js +85 -0
- package/dist/sessions/testFs.js.map +1 -0
- package/dist/sidecar/host.d.ts +64 -2
- package/dist/sidecar/host.d.ts.map +1 -1
- package/dist/sidecar/host.js +135 -1
- package/dist/sidecar/host.js.map +1 -1
- package/dist/sidecar/server.d.ts +95 -2
- package/dist/sidecar/server.d.ts.map +1 -1
- package/dist/sidecar/server.js +229 -3
- package/dist/sidecar/server.js.map +1 -1
- package/dist/skills.d.ts +8 -3
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +71 -35
- package/dist/skills.js.map +1 -1
- package/dist/tools/builtins.d.ts +1 -0
- package/dist/tools/builtins.d.ts.map +1 -1
- package/dist/tools/builtins.js +89 -3
- package/dist/tools/builtins.js.map +1 -1
- package/dist/tools/files.d.ts.map +1 -1
- package/dist/tools/files.js +13 -0
- package/dist/tools/files.js.map +1 -1
- package/dist/tools/http.d.ts.map +1 -1
- package/dist/tools/http.js.map +1 -1
- package/package.json +22 -34
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolsMarker.js","sourceRoot":"","sources":["../../prompts/toolsMarker.ts"],"names":[],"mappings":"AAAA;;;;;;;+BAO+B;AAC/B,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE7C,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,KAAmD;IACjF,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1E,CAAC;AAED;mEACmE;AACnE,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,KAAmD;IACjG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,MAAM,CAAC;IAClD,OAAO,MAAM,CAAC,UAAU,CAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC;AAClH,CAAC"}
|
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
2
|
import type { ChatCompletionMessageParam, ChatCompletionTool } from 'openai/resources/chat/completions';
|
|
3
3
|
import type { IAuthTokenProvider, Usage } from '@corenel/protocol';
|
|
4
|
+
export type { Usage };
|
|
4
5
|
export declare function setGatewayBase(url: string): void;
|
|
5
6
|
export interface StreamCompletionParams {
|
|
6
7
|
model: string;
|
|
7
8
|
messages: ChatCompletionMessageParam[];
|
|
8
9
|
tools?: ChatCompletionTool[];
|
|
9
10
|
tool_choice?: 'auto' | 'none';
|
|
11
|
+
/** Optional output-token ceiling. For reasoning models this bounds reasoning +
|
|
12
|
+
* visible output COMBINED, so a low value can starve the answer — omit to leave
|
|
13
|
+
* output unbounded (the caller opts in). */
|
|
14
|
+
max_completion_tokens?: number;
|
|
10
15
|
}
|
|
11
16
|
export interface AccumulatedToolCall {
|
|
12
17
|
id: string;
|
|
13
18
|
name: string;
|
|
14
19
|
arguments: string;
|
|
15
20
|
}
|
|
21
|
+
/** Pure reducer: OpenAI stream chunk `usage` -> our Usage shape, discounting cached prompt tokens when reported. */
|
|
22
|
+
export declare function usageFromChunk(u: {
|
|
23
|
+
prompt_tokens?: number;
|
|
24
|
+
completion_tokens?: number;
|
|
25
|
+
prompt_tokens_details?: {
|
|
26
|
+
cached_tokens?: number;
|
|
27
|
+
};
|
|
28
|
+
}): Usage;
|
|
16
29
|
export interface StreamedCompletion {
|
|
17
30
|
content: string;
|
|
18
31
|
toolCalls: AccumulatedToolCall[];
|
|
@@ -25,7 +38,9 @@ export interface StreamedCompletion {
|
|
|
25
38
|
* into whole tool calls. Returns the finished message + usage.
|
|
26
39
|
*/
|
|
27
40
|
export declare function streamCompletion(client: OpenAI, params: StreamCompletionParams, signal: AbortSignal, onText?: (delta: string) => void): Promise<StreamedCompletion>;
|
|
28
|
-
export declare function createChatClient(auth: IAuthTokenProvider
|
|
41
|
+
export declare function createChatClient(auth: IAuthTokenProvider, opts?: {
|
|
42
|
+
origin?: string;
|
|
43
|
+
}): OpenAI;
|
|
29
44
|
/** Host-injected model→custom-provider lookup. The kernel transport knows how to
|
|
30
45
|
* build a custom client but NOT how the host decides which model belongs to one
|
|
31
46
|
* (that lookup reads app storage) — so the app registers it at boot. Default:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../providers/gateway.ts"],"names":[],"mappings":"AAIA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../providers/gateway.ts"],"names":[],"mappings":"AAIA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAKnE,YAAY,EAAE,KAAK,EAAE,CAAC;AAMtB,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEhD;AAUD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B;;gDAE4C;IAC5C,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAEpF,oHAAoH;AACpH,wBAAgB,cAAc,CAAC,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,qBAAqB,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,KAAK,CAKnJ;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,sBAAsB,EAC9B,MAAM,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAqE7B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CA6BjG;AAED;;;sEAGsE;AACtE,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAE/G,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,sBAAsB,GAAG,IAAI,CAE1E;AAED;;;;yDAIyD;AACzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;;+CAG+C;AAC/C,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;AAE3F,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAA0B;AAEvF;;;+CAG+C;AAC/C,wBAAgB,kBAAkB,CAAC,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAUjF"}
|
|
@@ -19,6 +19,14 @@ function gatewayBaseURL() {
|
|
|
19
19
|
return v1;
|
|
20
20
|
return `${globalThis.location.origin}${v1}`;
|
|
21
21
|
}
|
|
22
|
+
/** Pure reducer: OpenAI stream chunk `usage` -> our Usage shape, discounting cached prompt tokens when reported. */
|
|
23
|
+
export function usageFromChunk(u) {
|
|
24
|
+
const cached = u.prompt_tokens_details?.cached_tokens;
|
|
25
|
+
const out = { promptTokens: u.prompt_tokens || 0, completionTokens: u.completion_tokens || 0 };
|
|
26
|
+
if (typeof cached === 'number')
|
|
27
|
+
out.cachedTokens = cached;
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
22
30
|
/**
|
|
23
31
|
* Stream a completion and accumulate it: text deltas are surfaced via onText for
|
|
24
32
|
* live rendering; streamed tool-call deltas (indexed fragments) are reassembled
|
|
@@ -33,9 +41,18 @@ export async function streamCompletion(client, params, signal, onText) {
|
|
|
33
41
|
messages: params.messages,
|
|
34
42
|
tools: params.tools,
|
|
35
43
|
tool_choice: params.tool_choice,
|
|
44
|
+
// Undefined is dropped by the SDK's JSON serialization, so an unset cap
|
|
45
|
+
// leaves output unbounded (unchanged behavior).
|
|
46
|
+
max_completion_tokens: params.max_completion_tokens,
|
|
36
47
|
stream: true,
|
|
37
48
|
stream_options: { include_usage: true },
|
|
38
|
-
},
|
|
49
|
+
},
|
|
50
|
+
// The agent loop (loop.ts) is the SOLE retry authority — it owns the bounded
|
|
51
|
+
// backoff retry for transient failures. Disable the OpenAI SDK's own retries
|
|
52
|
+
// (default 2) so they don't MULTIPLY with the loop's: a gateway timeout was
|
|
53
|
+
// being retried SDK(1+2) x loop(1+3) = ~12 times, turning one 300s timeout
|
|
54
|
+
// into ~12 minutes of dead attempts.
|
|
55
|
+
{ signal, maxRetries: 0 });
|
|
39
56
|
}
|
|
40
57
|
catch (e) {
|
|
41
58
|
// Surface the real gateway failure. The OpenAI SDK throws an APIError carrying
|
|
@@ -76,15 +93,18 @@ export async function streamCompletion(client, params, signal, onText) {
|
|
|
76
93
|
if (choice?.finish_reason)
|
|
77
94
|
finishReason = choice.finish_reason;
|
|
78
95
|
if (chunk.usage) {
|
|
79
|
-
|
|
80
|
-
usage.
|
|
96
|
+
const u = usageFromChunk(chunk.usage);
|
|
97
|
+
usage.promptTokens = u.promptTokens;
|
|
98
|
+
usage.completionTokens = u.completionTokens;
|
|
99
|
+
if (u.cachedTokens != null)
|
|
100
|
+
usage.cachedTokens = u.cachedTokens;
|
|
81
101
|
}
|
|
82
102
|
}
|
|
83
103
|
const toolCalls = [...byIndex.entries()].sort((a, b) => a[0] - b[0]).map(([, v]) => v);
|
|
84
104
|
alog('stream:end', { chunks: chunkN, contentLen: content.length, toolCalls: toolCalls.length, finishReason, usage });
|
|
85
105
|
return { content, toolCalls, usage, finishReason };
|
|
86
106
|
}
|
|
87
|
-
export function createChatClient(auth) {
|
|
107
|
+
export function createChatClient(auth, opts = {}) {
|
|
88
108
|
return new OpenAI({
|
|
89
109
|
baseURL: gatewayBaseURL(),
|
|
90
110
|
// Real key lives server-side; this placeholder is replaced per-request by the
|
|
@@ -99,6 +119,12 @@ export function createChatClient(auth) {
|
|
|
99
119
|
headers.set('Authorization', `Bearer ${token}`);
|
|
100
120
|
else
|
|
101
121
|
headers.delete('Authorization');
|
|
122
|
+
// Static origin tag so the gateway can distinguish daemon-originated runs
|
|
123
|
+
// from interactive browser runs for entitlement metering. Enforcement is
|
|
124
|
+
// entirely server-side — this is only ever an informational tag, never a
|
|
125
|
+
// client-side gate.
|
|
126
|
+
if (opts.origin)
|
|
127
|
+
headers.set('X-Prompd-Origin', opts.origin);
|
|
102
128
|
alog('gateway:fetch', { url: String(url), hasToken: !!token });
|
|
103
129
|
try {
|
|
104
130
|
const res = await fetch(url, { ...init, headers });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../providers/gateway.ts"],"names":[],"mappings":"AAAA;;;6EAG6E;AAC7E,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../providers/gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/services.d.ts
CHANGED
|
@@ -10,6 +10,17 @@ export interface PingResult {
|
|
|
10
10
|
version?: string;
|
|
11
11
|
error?: string;
|
|
12
12
|
}
|
|
13
|
+
/** Product analytics PORT — a vendor-agnostic sink so corenel code (and the host's
|
|
14
|
+
* instrumentation) can record usage WITHOUT importing GA4/gtag or any analytics
|
|
15
|
+
* SDK. The host injects a concrete adapter (GA4, PostHog, Plausible, …) at boot;
|
|
16
|
+
* the default is a no-op, so dev/tests and unconfigured hosts emit nothing. Params
|
|
17
|
+
* are flat (GA4-friendly): no nested objects. */
|
|
18
|
+
export interface Analytics {
|
|
19
|
+
/** Record a named event with optional flat params (e.g. track('run_completed', { surface, model, cost })). */
|
|
20
|
+
track(name: string, params?: Record<string, string | number | boolean>): void;
|
|
21
|
+
/** Record a page/route view for an SPA path. */
|
|
22
|
+
pageView(path: string): void;
|
|
23
|
+
}
|
|
13
24
|
export interface HostServices {
|
|
14
25
|
/** Bearer token for the backend/gateway, or null when unauthenticated. */
|
|
15
26
|
getToken(): Promise<string | null>;
|
|
@@ -21,6 +32,8 @@ export interface HostServices {
|
|
|
21
32
|
}): Promise<BuildResult>;
|
|
22
33
|
/** Reachability + version check for the backend. */
|
|
23
34
|
ping(): Promise<PingResult>;
|
|
35
|
+
/** Product analytics sink (default: no-op until the host injects an adapter). */
|
|
36
|
+
analytics: Analytics;
|
|
24
37
|
}
|
|
25
38
|
/** Inject the host's backend access. Called once at boot (see the host's wiring). */
|
|
26
39
|
export declare function setHostServices(s: Partial<HostServices>): void;
|
package/dist/services.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../services.ts"],"names":[],"mappings":"AAQA;;iBAEiB;AACjB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnC,wEAAwE;IACxE,UAAU,IAAI,MAAM,CAAC;IACrB,mFAAmF;IACnF,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnH,oDAAoD;IACpD,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../services.ts"],"names":[],"mappings":"AAQA;;iBAEiB;AACjB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;iDAIiD;AACjD,MAAM,WAAW,SAAS;IACxB,8GAA8G;IAC9G,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9E,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAID,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnC,wEAAwE;IACxE,UAAU,IAAI,MAAM,CAAC;IACrB,mFAAmF;IACnF,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnH,oDAAoD;IACpD,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5B,iFAAiF;IACjF,SAAS,EAAE,SAAS,CAAC;CACtB;AAUD,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAE9D;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,YAAY,CAE3C"}
|
package/dist/services.js
CHANGED
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
* reads via hostServices(). The gateway has its own token/base injection
|
|
6
6
|
* (setGatewayBase + the per-client getToken); this covers the non-gateway uses
|
|
7
7
|
* (e.g. a runner attaching a bearer token to a direct fetch). */
|
|
8
|
+
const NOOP_ANALYTICS = { track: () => { }, pageView: () => { } };
|
|
8
9
|
let services = {
|
|
9
10
|
getToken: async () => null,
|
|
10
11
|
getApiBase: () => '/api',
|
|
11
12
|
build: async () => ({ output: '' }),
|
|
12
13
|
ping: async () => ({ ok: false, error: 'no backend configured' }),
|
|
14
|
+
analytics: NOOP_ANALYTICS,
|
|
13
15
|
};
|
|
14
16
|
/** Inject the host's backend access. Called once at boot (see the host's wiring). */
|
|
15
17
|
export function setHostServices(s) {
|
package/dist/services.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.js","sourceRoot":"","sources":["../services.ts"],"names":[],"mappings":"AAAA;;;;;;iEAMiE;
|
|
1
|
+
{"version":3,"file":"services.js","sourceRoot":"","sources":["../services.ts"],"names":[],"mappings":"AAAA;;;;;;iEAMiE;AA4BjE,MAAM,cAAc,GAAc,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAe1E,IAAI,QAAQ,GAAiB;IAC3B,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;IAC1B,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM;IACxB,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACnC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjE,SAAS,EAAE,cAAc;CAC1B,CAAC;AAEF,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,CAAwB;IACtD,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { FileService, IRecallStore, OffloadRef } from '@corenel/protocol';
|
|
2
|
+
/** Reserved pseudo-session for offloads produced outside any chat session
|
|
3
|
+
* (DAG node runs, the editor's prompt Run). */
|
|
4
|
+
export declare const UNATTACHED_SESSION = "_unattached";
|
|
5
|
+
export interface BlobRecord {
|
|
6
|
+
id: string;
|
|
7
|
+
toolName: string;
|
|
8
|
+
bytes: number;
|
|
9
|
+
content: string;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class FileRecallStore implements IRecallStore {
|
|
13
|
+
private getFiles;
|
|
14
|
+
private getSessionId;
|
|
15
|
+
private root;
|
|
16
|
+
private counter;
|
|
17
|
+
private readonly prefix;
|
|
18
|
+
constructor(getFiles: () => FileService | null | Promise<FileService | null>, getSessionId?: () => string, root?: () => string);
|
|
19
|
+
private files;
|
|
20
|
+
private blobPath;
|
|
21
|
+
record(toolName: string, content: unknown): Promise<OffloadRef>;
|
|
22
|
+
read(id: string): Promise<string | null>;
|
|
23
|
+
}
|
|
24
|
+
/** All blobs for a session, newest first (for the context drawer). */
|
|
25
|
+
export declare function listSessionBlobs(files: FileService, sessionId: string, root?: string): Promise<BlobRecord[]>;
|
|
26
|
+
/** Drop a session's offloaded blobs (housekeeping). */
|
|
27
|
+
export declare function clearSessionBlobs(files: FileService, sessionId: string, root?: string): Promise<void>;
|
|
28
|
+
/** Delete one offloaded blob (the drawer's Restore removes the record after
|
|
29
|
+
* re-injecting its content). The id is validated against SAFE_ID — it arrives
|
|
30
|
+
* from the UI, but the same no-traversal defense as read() applies. Invalid
|
|
31
|
+
* ids and missing files are silent no-ops. */
|
|
32
|
+
export declare function removeSessionBlob(files: FileService, sessionId: string, id: string, root?: string): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=fileRecallStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileRecallStore.d.ts","sourceRoot":"","sources":["../../sessions/fileRecallStore.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI/E;+CAC+C;AAC/C,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AASD,qBAAa,eAAgB,YAAW,YAAY;IAKhD,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,IAAI;IANd,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;gBAGvD,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,EAChE,YAAY,GAAE,MAAM,MAAiC,EACrD,IAAI,GAAE,MAAM,MAAqB;YAG7B,KAAK;IAMnB,OAAO,CAAC,QAAQ;IAIV,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAQ/D,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAM/C;AAED,sEAAsE;AACtE,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,SAAiB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAc1H;AAED,uDAAuD;AACvD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,SAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnH;AAED;;;8CAG8C;AAC9C,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,SAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/H"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { sessionsRoot, flattenFiles } from '@corenel/protocol';
|
|
2
|
+
import { PREVIEW_BYTES } from '../compression';
|
|
3
|
+
/** Reserved pseudo-session for offloads produced outside any chat session
|
|
4
|
+
* (DAG node runs, the editor's prompt Run). */
|
|
5
|
+
export const UNATTACHED_SESSION = '_unattached';
|
|
6
|
+
/** Blob ids are model-supplied on read — accept only our own shape. */
|
|
7
|
+
const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
8
|
+
function safeJson(v) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.stringify(v);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return String(v);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class FileRecallStore {
|
|
17
|
+
constructor(getFiles, getSessionId = () => UNATTACHED_SESSION, root = sessionsRoot) {
|
|
18
|
+
Object.defineProperty(this, "getFiles", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: getFiles
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "getSessionId", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: getSessionId
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "root", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: root
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "counter", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: 0
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "prefix", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: Math.random().toString(36).slice(2, 7)
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async files() {
|
|
50
|
+
const f = await this.getFiles();
|
|
51
|
+
if (!f)
|
|
52
|
+
throw new Error('No file workspace is connected — offload storage is unavailable.');
|
|
53
|
+
return f;
|
|
54
|
+
}
|
|
55
|
+
blobPath(id) {
|
|
56
|
+
return `${this.root()}/${this.getSessionId()}/blobs/${id}.json`;
|
|
57
|
+
}
|
|
58
|
+
async record(toolName, content) {
|
|
59
|
+
const text = typeof content === 'string' ? content : safeJson(content);
|
|
60
|
+
const id = `blob-${this.prefix}-${++this.counter}`;
|
|
61
|
+
const rec = { id, toolName, bytes: text.length, content: text, createdAt: Date.now() };
|
|
62
|
+
await (await this.files()).write(this.blobPath(id), JSON.stringify(rec));
|
|
63
|
+
return { id, toolName, bytes: text.length, preview: text.slice(0, PREVIEW_BYTES) };
|
|
64
|
+
}
|
|
65
|
+
async read(id) {
|
|
66
|
+
if (!SAFE_ID.test(id))
|
|
67
|
+
return null;
|
|
68
|
+
const text = await (await this.files()).read(this.blobPath(id)).catch(() => null);
|
|
69
|
+
if (text == null)
|
|
70
|
+
return null;
|
|
71
|
+
try {
|
|
72
|
+
return JSON.parse(text).content;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** All blobs for a session, newest first (for the context drawer). */
|
|
80
|
+
export async function listSessionBlobs(files, sessionId, root = sessionsRoot()) {
|
|
81
|
+
const blobsDir = `${root}/${sessionId}/blobs`;
|
|
82
|
+
// Same caveat as JsonlSessionStore.list: some backends return a workspace-
|
|
83
|
+
// rooted tree with the ancestor chain at the top level — flatten and match
|
|
84
|
+
// the blob files by path instead of trusting the top-level nodes.
|
|
85
|
+
const nodes = await files.list(blobsDir).catch(() => []);
|
|
86
|
+
const blobFiles = flattenFiles(nodes).filter((f) => f.path.startsWith(blobsDir + '/') && f.path.endsWith('.json'));
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const n of blobFiles) {
|
|
89
|
+
const text = await files.read(n.path).catch(() => null);
|
|
90
|
+
if (text == null)
|
|
91
|
+
continue;
|
|
92
|
+
try {
|
|
93
|
+
out.push(JSON.parse(text));
|
|
94
|
+
}
|
|
95
|
+
catch { /* skip corrupt */ }
|
|
96
|
+
}
|
|
97
|
+
return out.sort((a, b) => b.createdAt - a.createdAt);
|
|
98
|
+
}
|
|
99
|
+
/** Drop a session's offloaded blobs (housekeeping). */
|
|
100
|
+
export async function clearSessionBlobs(files, sessionId, root = sessionsRoot()) {
|
|
101
|
+
await files.remove(`${root}/${sessionId}/blobs`).catch(() => { });
|
|
102
|
+
}
|
|
103
|
+
/** Delete one offloaded blob (the drawer's Restore removes the record after
|
|
104
|
+
* re-injecting its content). The id is validated against SAFE_ID — it arrives
|
|
105
|
+
* from the UI, but the same no-traversal defense as read() applies. Invalid
|
|
106
|
+
* ids and missing files are silent no-ops. */
|
|
107
|
+
export async function removeSessionBlob(files, sessionId, id, root = sessionsRoot()) {
|
|
108
|
+
if (!SAFE_ID.test(id))
|
|
109
|
+
return;
|
|
110
|
+
await files.remove(`${root}/${sessionId}/blobs/${id}.json`).catch(() => { });
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=fileRecallStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileRecallStore.js","sourceRoot":"","sources":["../../sessions/fileRecallStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentSession, FileService, ISessionStore, SessionSurface } from '@corenel/protocol';
|
|
2
|
+
export declare class JsonlSessionStore implements ISessionStore {
|
|
3
|
+
private getFiles;
|
|
4
|
+
private root;
|
|
5
|
+
private cursors;
|
|
6
|
+
constructor(getFiles: () => FileService | null | Promise<FileService | null>, root?: () => string);
|
|
7
|
+
private files;
|
|
8
|
+
private path;
|
|
9
|
+
create(title: string, surface?: SessionSurface): Promise<AgentSession>;
|
|
10
|
+
get(id: string): Promise<AgentSession | null>;
|
|
11
|
+
list(surface?: SessionSurface): Promise<AgentSession[]>;
|
|
12
|
+
save(session: AgentSession): Promise<void>;
|
|
13
|
+
/** Cursor for a session this instance hasn't touched (e.g. saved after a
|
|
14
|
+
* reload): fold the existing file, or start a fresh log from the session's
|
|
15
|
+
* own meta. */
|
|
16
|
+
private seed;
|
|
17
|
+
rename(id: string, title: string): Promise<void>;
|
|
18
|
+
delete(id: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=fileSessionStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileSessionStore.d.ts","sourceRoot":"","sources":["../../sessions/fileSessionStore.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA4BlG,qBAAa,iBAAkB,YAAW,aAAa;IAInD,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,IAAI;IAJd,OAAO,CAAC,OAAO,CAA6B;gBAGlC,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,EAChE,IAAI,GAAE,MAAM,MAAqB;YAG7B,KAAK;IAMnB,OAAO,CAAC,IAAI;IAIN,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAUtE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAe7C,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAmBvD,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BhD;;mBAEe;YACD,IAAI;IAeZ,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAIxC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { sessionsRoot, flattenFiles } from '@corenel/protocol';
|
|
2
|
+
import { encodeLine, foldSession } from './jsonl';
|
|
3
|
+
function uid(prefix) {
|
|
4
|
+
return `${prefix}_${Date.now().toString(36)}${Math.floor(Math.random() * 1e6).toString(36)}`;
|
|
5
|
+
}
|
|
6
|
+
/** Strictly-increasing millisecond clock. Plain `Date.now()` ties under fast
|
|
7
|
+
* synchronous calls (e.g. back-to-back create()/save() in the same tick),
|
|
8
|
+
* which would make updatedAt-desc ordering ambiguous. Bumping by 1ms on a tie
|
|
9
|
+
* keeps createdAt/updatedAt monotonic without changing the stored shape. */
|
|
10
|
+
let lastTs = 0;
|
|
11
|
+
function now() {
|
|
12
|
+
const t = Date.now();
|
|
13
|
+
lastTs = t > lastTs ? t : lastTs + 1;
|
|
14
|
+
return lastTs;
|
|
15
|
+
}
|
|
16
|
+
export class JsonlSessionStore {
|
|
17
|
+
constructor(getFiles, root = sessionsRoot) {
|
|
18
|
+
Object.defineProperty(this, "getFiles", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: getFiles
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "root", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: root
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "cursors", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: new Map()
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async files() {
|
|
38
|
+
const f = await this.getFiles();
|
|
39
|
+
if (!f)
|
|
40
|
+
throw new Error('No file workspace is connected — sessions are unavailable.');
|
|
41
|
+
return f;
|
|
42
|
+
}
|
|
43
|
+
path(id) {
|
|
44
|
+
return `${this.root()}/${id}/SESSION.jsonl`;
|
|
45
|
+
}
|
|
46
|
+
async create(title, surface) {
|
|
47
|
+
const createdAt = now();
|
|
48
|
+
const id = uid('ses');
|
|
49
|
+
const meta = { k: 'meta', id, title, createdAt, ...(surface ? { surface } : {}) };
|
|
50
|
+
const text = encodeLine(meta);
|
|
51
|
+
await (await this.files()).write(this.path(id), text);
|
|
52
|
+
this.cursors.set(id, { text, turnJson: [], title });
|
|
53
|
+
return { id, title, createdAt, updatedAt: createdAt, messages: [], ...(surface ? { surface } : {}) };
|
|
54
|
+
}
|
|
55
|
+
async get(id) {
|
|
56
|
+
const text = await (await this.files()).read(this.path(id)).catch(() => null);
|
|
57
|
+
if (text == null)
|
|
58
|
+
return null;
|
|
59
|
+
const ses = foldSession(text);
|
|
60
|
+
if (ses) {
|
|
61
|
+
this.cursors.set(id, {
|
|
62
|
+
text,
|
|
63
|
+
turnJson: ses.messages.map((m) => JSON.stringify(m)),
|
|
64
|
+
title: ses.title,
|
|
65
|
+
titleLocked: ses.titleLocked,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return ses;
|
|
69
|
+
}
|
|
70
|
+
async list(surface) {
|
|
71
|
+
const files = await this.files();
|
|
72
|
+
const root = this.root();
|
|
73
|
+
// list(dir) shape differs per backend: MemoryFileService returns a tree
|
|
74
|
+
// rooted at the WORKSPACE root (the top level is the ancestor chain, e.g.
|
|
75
|
+
// ['.prompd']), while others return dir's children. Never trust the top
|
|
76
|
+
// level — flatten and match the SESSION.jsonl files by path.
|
|
77
|
+
const nodes = await files.list(root).catch(() => []);
|
|
78
|
+
const sessionFiles = flattenFiles(nodes).filter((f) => f.name === 'SESSION.jsonl' && f.path.startsWith(root + '/'));
|
|
79
|
+
const out = [];
|
|
80
|
+
for (const f of sessionFiles) {
|
|
81
|
+
const text = await files.read(f.path).catch(() => null);
|
|
82
|
+
const ses = text != null ? foldSession(text) : null;
|
|
83
|
+
if (ses)
|
|
84
|
+
out.push(ses);
|
|
85
|
+
}
|
|
86
|
+
const scoped = surface ? out.filter((s) => s.surface === surface || (surface === 'agent' && !s.surface)) : out;
|
|
87
|
+
return scoped.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
88
|
+
}
|
|
89
|
+
async save(session) {
|
|
90
|
+
// Compute the timestamp candidate up front but don't touch `session` until we
|
|
91
|
+
// know something actually changed — a no-op save must not mutate the caller's
|
|
92
|
+
// object (it should be indistinguishable from not having called save() at all).
|
|
93
|
+
const at = now();
|
|
94
|
+
const cur = this.cursors.get(session.id) ?? (await this.seed(session));
|
|
95
|
+
const turnJson = session.messages.map((m) => JSON.stringify(m));
|
|
96
|
+
const appended = [];
|
|
97
|
+
for (let i = 0; i < turnJson.length; i++) {
|
|
98
|
+
if (cur.turnJson[i] !== turnJson[i]) {
|
|
99
|
+
appended.push(encodeLine({ k: 'turn', i, at, m: session.messages[i] }));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (session.title !== cur.title || session.titleLocked !== cur.titleLocked) {
|
|
103
|
+
appended.push(encodeLine({
|
|
104
|
+
k: 'meta-update',
|
|
105
|
+
at,
|
|
106
|
+
title: session.title,
|
|
107
|
+
...(session.titleLocked !== undefined ? { titleLocked: session.titleLocked } : {}),
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
if (!appended.length)
|
|
111
|
+
return;
|
|
112
|
+
session.updatedAt = at;
|
|
113
|
+
const text = cur.text + appended.join('');
|
|
114
|
+
await (await this.files()).write(this.path(session.id), text);
|
|
115
|
+
this.cursors.set(session.id, { text, turnJson, title: session.title, titleLocked: session.titleLocked });
|
|
116
|
+
}
|
|
117
|
+
/** Cursor for a session this instance hasn't touched (e.g. saved after a
|
|
118
|
+
* reload): fold the existing file, or start a fresh log from the session's
|
|
119
|
+
* own meta. */
|
|
120
|
+
async seed(session) {
|
|
121
|
+
const text = await (await this.files()).read(this.path(session.id)).catch(() => null);
|
|
122
|
+
if (text != null) {
|
|
123
|
+
const ses = foldSession(text);
|
|
124
|
+
if (ses) {
|
|
125
|
+
return { text, turnJson: ses.messages.map((m) => JSON.stringify(m)), title: ses.title, titleLocked: ses.titleLocked };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const meta = encodeLine({
|
|
129
|
+
k: 'meta', id: session.id, title: session.title, createdAt: session.createdAt,
|
|
130
|
+
...(session.surface ? { surface: session.surface } : {}),
|
|
131
|
+
});
|
|
132
|
+
return { text: meta, turnJson: [], title: session.title, titleLocked: undefined };
|
|
133
|
+
}
|
|
134
|
+
async rename(id, title) {
|
|
135
|
+
const cur = this.cursors.get(id);
|
|
136
|
+
const text = cur?.text ?? (await (await this.files()).read(this.path(id)).catch(() => null));
|
|
137
|
+
if (text == null)
|
|
138
|
+
return; // no-op on missing, matching the old store
|
|
139
|
+
const next = text + encodeLine({ k: 'meta-update', at: now(), title, titleLocked: true });
|
|
140
|
+
await (await this.files()).write(this.path(id), next);
|
|
141
|
+
const folded = foldSession(next);
|
|
142
|
+
if (folded) {
|
|
143
|
+
this.cursors.set(id, { text: next, turnJson: folded.messages.map((m) => JSON.stringify(m)), title, titleLocked: true });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async delete(id) {
|
|
147
|
+
this.cursors.delete(id);
|
|
148
|
+
await (await this.files()).remove(`${this.root()}/${id}`).catch(() => { });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=fileSessionStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileSessionStore.js","sourceRoot":"","sources":["../../sessions/fileSessionStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AgentSession, SessionSurface } from '@corenel/protocol';
|
|
2
|
+
export type SessionLine = {
|
|
3
|
+
k: 'meta';
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
createdAt: number;
|
|
7
|
+
surface?: SessionSurface;
|
|
8
|
+
} | {
|
|
9
|
+
k: 'meta-update';
|
|
10
|
+
at: number;
|
|
11
|
+
title?: string;
|
|
12
|
+
titleLocked?: boolean;
|
|
13
|
+
} | {
|
|
14
|
+
k: 'turn';
|
|
15
|
+
i: number;
|
|
16
|
+
at: number;
|
|
17
|
+
m: unknown;
|
|
18
|
+
};
|
|
19
|
+
export declare function encodeLine(line: SessionLine): string;
|
|
20
|
+
/** Fold a SESSION.jsonl text into an AgentSession, or null when no valid meta
|
|
21
|
+
* line exists (empty/foreign file). */
|
|
22
|
+
export declare function foldSession(text: string): AgentSession | null;
|
|
23
|
+
//# sourceMappingURL=jsonl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../sessions/jsonl.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEtE,MAAM,MAAM,WAAW,GACnB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,cAAc,CAAA;CAAE,GACrF;IAAE,CAAC,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAErD,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEpD;AAED;uCACuC;AACvC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAkC7D"}
|