@warmdrift/kgauto-compiler 2.0.0-alpha.53 → 2.0.0-alpha.55
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/brain-proxy.d.mts +100 -0
- package/dist/brain-proxy.d.ts +100 -0
- package/dist/brain-proxy.js +180 -0
- package/dist/brain-proxy.mjs +6 -0
- package/dist/chunk-WVICNOLA.mjs +156 -0
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +161 -1
- package/dist/index.mjs +10 -1
- package/package.json +7 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@warmdrift/kgauto-compiler/brain-proxy` — consumer brain-forward factory.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists (the 4-consumer silent-drop class, 2026-07-06 s62)
|
|
5
|
+
*
|
|
6
|
+
* The library's `record()` / `recordOutcome()` / `recordShadowProbe()` /
|
|
7
|
+
* advisory paths all POST to a consumer-hosted proxy that forwards the row to
|
|
8
|
+
* the shared Supabase brain (the consumer holds the service-role key; kgauto's
|
|
9
|
+
* library never sees it). Every consumer hand-rolled that proxy layer — and a
|
|
10
|
+
* 4-consumer audit found every one silently broken in a *different* shape:
|
|
11
|
+
*
|
|
12
|
+
* - tt-intelligence: middleware blocked 2 of 3 routes — server-to-server
|
|
13
|
+
* POSTs 307-redirected to /login (missing public-path allowlist entry).
|
|
14
|
+
* - inspire-central: the `/outcomes` proxy carried a column whitelist frozen
|
|
15
|
+
* at alpha.7 that stripped `fell_over_from` / `fallback_reason`
|
|
16
|
+
* (migration 018 columns) — Glass-Box fallback telemetry silently NULL.
|
|
17
|
+
* - playbacksam: the `/probe_outcomes` whitelist would strip alpha.53's
|
|
18
|
+
* `error_class` — every future migration column drops on the floor.
|
|
19
|
+
* - global-expansion: mounted 1 of 4 routes — advisory POSTs 404 silently.
|
|
20
|
+
*
|
|
21
|
+
* Same L-142 / L-117 silent-drop family, four independent shapes, all in the
|
|
22
|
+
* layer consumers hand-roll. This factory kills the *class*: kgauto owns the
|
|
23
|
+
* forward handler, the consumer mounts ONE catch-all route. No column
|
|
24
|
+
* whitelist — the body is forwarded verbatim (`{ ...body }`), so any future
|
|
25
|
+
* migration column passes through untouched. One middleware/public-path entry
|
|
26
|
+
* (`/api/kgauto/v2/`) covers all four segments, which structurally prevents
|
|
27
|
+
* the tt-intel middleware-drift failure.
|
|
28
|
+
*
|
|
29
|
+
* ## Mounting recipes
|
|
30
|
+
*
|
|
31
|
+
* ### (a) Next.js app-router catch-all — ONE file, ONE middleware entry
|
|
32
|
+
*
|
|
33
|
+
* // app/api/kgauto/v2/[segment]/route.ts
|
|
34
|
+
* import { createBrainForwardRoutes } from '@warmdrift/kgauto-compiler/brain-proxy';
|
|
35
|
+
* const routes = createBrainForwardRoutes({
|
|
36
|
+
* ingestSecret: process.env.KGAUTO_INGEST_SECRET!,
|
|
37
|
+
* brainUrl: process.env.KGAUTO_BRAIN_URL!, // https://xxxx.supabase.co
|
|
38
|
+
* serviceKey: process.env.KGAUTO_BRAIN_SERVICE_KEY!,
|
|
39
|
+
* });
|
|
40
|
+
* export const POST = (req: Request, { params }: { params: { segment: string } }) =>
|
|
41
|
+
* routes.handle(req, params.segment);
|
|
42
|
+
*
|
|
43
|
+
* // middleware.ts — ONE public-path entry covers ALL four segments.
|
|
44
|
+
* // This is the structural fix for the tt-intel drift: you cannot mount
|
|
45
|
+
* // 3-of-4 routes and forget the 4th, because the catch-all is one file
|
|
46
|
+
* // and the allowlist is one prefix.
|
|
47
|
+
* const PUBLIC_PATHS = [ ... '/api/kgauto/v2/' ];
|
|
48
|
+
*
|
|
49
|
+
* ### (b) Plain Vercel edge function, per segment
|
|
50
|
+
*
|
|
51
|
+
* // api/kgauto/probe_outcomes.ts
|
|
52
|
+
* export const config = { runtime: 'edge' };
|
|
53
|
+
* const routes = createBrainForwardRoutes({ ... });
|
|
54
|
+
* export default (req: Request) => routes.handle(req, 'probe_outcomes');
|
|
55
|
+
*
|
|
56
|
+
* The library appends the segment path to the consumer's `endpoint`, so the
|
|
57
|
+
* consumer's `KGAUTO_V2_BRAIN_URL` (the value passed to `configureBrain`)
|
|
58
|
+
* must be the base that resolves to `.../api/kgauto/v2` — i.e. the last path
|
|
59
|
+
* segment of each library POST (`outcomes`, `probe_outcomes`, …) is what
|
|
60
|
+
* `handle()` receives as `segment`.
|
|
61
|
+
*
|
|
62
|
+
* ## Quality-segment handle resolution (alpha.55)
|
|
63
|
+
*
|
|
64
|
+
* `recordOutcome()` sends `outcome_id` as `CompileResult.handle` (a string),
|
|
65
|
+
* but `compile_outcome_quality.outcome_id` is a BIGINT FK →
|
|
66
|
+
* `compile_outcomes(id)`. A verbatim forward would 400 every handle-shaped
|
|
67
|
+
* verdict (tt-intel + IC convergent finding, 2026-07-06). On the
|
|
68
|
+
* `compile_outcome_quality` segment the factory resolves non-numeric
|
|
69
|
+
* `outcome_id` values to their BIGINT row ids via
|
|
70
|
+
* `compile_outcomes?handle=eq.<v>` (latest row wins) before forwarding.
|
|
71
|
+
* Numeric ids pass through untouched; an unresolvable handle returns
|
|
72
|
+
* `404 handle_not_found` so the library's route-404 observability names the
|
|
73
|
+
* failure instead of the brain's opaque FK error.
|
|
74
|
+
*/
|
|
75
|
+
interface BrainForwardConfig {
|
|
76
|
+
/** Bearer token consumers' callers must present (usually KGAUTO_INGEST_SECRET). */
|
|
77
|
+
ingestSecret: string;
|
|
78
|
+
/** Brain Supabase project URL (e.g. https://xxxx.supabase.co). */
|
|
79
|
+
brainUrl: string;
|
|
80
|
+
/** Brain service-role key (server-side only). */
|
|
81
|
+
serviceKey: string;
|
|
82
|
+
/** Optional fetch impl for tests. */
|
|
83
|
+
fetchImpl?: typeof fetch;
|
|
84
|
+
}
|
|
85
|
+
interface BrainForwardRoutes {
|
|
86
|
+
/**
|
|
87
|
+
* Web-standard handler. `segment` is the last path segment of the library's
|
|
88
|
+
* POST URL (e.g. 'outcomes', 'probe_outcomes'). In a Next.js catch-all this
|
|
89
|
+
* is `params.segment`. Never throws — every error path returns a `Response`.
|
|
90
|
+
*/
|
|
91
|
+
handle(req: Request, segment: string): Promise<Response>;
|
|
92
|
+
/**
|
|
93
|
+
* The path segments this factory serves. Consumers can use it for route
|
|
94
|
+
* generation, allowlist construction, or tests.
|
|
95
|
+
*/
|
|
96
|
+
segments: readonly string[];
|
|
97
|
+
}
|
|
98
|
+
declare function createBrainForwardRoutes(config: BrainForwardConfig): BrainForwardRoutes;
|
|
99
|
+
|
|
100
|
+
export { type BrainForwardConfig, type BrainForwardRoutes, createBrainForwardRoutes };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@warmdrift/kgauto-compiler/brain-proxy` — consumer brain-forward factory.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists (the 4-consumer silent-drop class, 2026-07-06 s62)
|
|
5
|
+
*
|
|
6
|
+
* The library's `record()` / `recordOutcome()` / `recordShadowProbe()` /
|
|
7
|
+
* advisory paths all POST to a consumer-hosted proxy that forwards the row to
|
|
8
|
+
* the shared Supabase brain (the consumer holds the service-role key; kgauto's
|
|
9
|
+
* library never sees it). Every consumer hand-rolled that proxy layer — and a
|
|
10
|
+
* 4-consumer audit found every one silently broken in a *different* shape:
|
|
11
|
+
*
|
|
12
|
+
* - tt-intelligence: middleware blocked 2 of 3 routes — server-to-server
|
|
13
|
+
* POSTs 307-redirected to /login (missing public-path allowlist entry).
|
|
14
|
+
* - inspire-central: the `/outcomes` proxy carried a column whitelist frozen
|
|
15
|
+
* at alpha.7 that stripped `fell_over_from` / `fallback_reason`
|
|
16
|
+
* (migration 018 columns) — Glass-Box fallback telemetry silently NULL.
|
|
17
|
+
* - playbacksam: the `/probe_outcomes` whitelist would strip alpha.53's
|
|
18
|
+
* `error_class` — every future migration column drops on the floor.
|
|
19
|
+
* - global-expansion: mounted 1 of 4 routes — advisory POSTs 404 silently.
|
|
20
|
+
*
|
|
21
|
+
* Same L-142 / L-117 silent-drop family, four independent shapes, all in the
|
|
22
|
+
* layer consumers hand-roll. This factory kills the *class*: kgauto owns the
|
|
23
|
+
* forward handler, the consumer mounts ONE catch-all route. No column
|
|
24
|
+
* whitelist — the body is forwarded verbatim (`{ ...body }`), so any future
|
|
25
|
+
* migration column passes through untouched. One middleware/public-path entry
|
|
26
|
+
* (`/api/kgauto/v2/`) covers all four segments, which structurally prevents
|
|
27
|
+
* the tt-intel middleware-drift failure.
|
|
28
|
+
*
|
|
29
|
+
* ## Mounting recipes
|
|
30
|
+
*
|
|
31
|
+
* ### (a) Next.js app-router catch-all — ONE file, ONE middleware entry
|
|
32
|
+
*
|
|
33
|
+
* // app/api/kgauto/v2/[segment]/route.ts
|
|
34
|
+
* import { createBrainForwardRoutes } from '@warmdrift/kgauto-compiler/brain-proxy';
|
|
35
|
+
* const routes = createBrainForwardRoutes({
|
|
36
|
+
* ingestSecret: process.env.KGAUTO_INGEST_SECRET!,
|
|
37
|
+
* brainUrl: process.env.KGAUTO_BRAIN_URL!, // https://xxxx.supabase.co
|
|
38
|
+
* serviceKey: process.env.KGAUTO_BRAIN_SERVICE_KEY!,
|
|
39
|
+
* });
|
|
40
|
+
* export const POST = (req: Request, { params }: { params: { segment: string } }) =>
|
|
41
|
+
* routes.handle(req, params.segment);
|
|
42
|
+
*
|
|
43
|
+
* // middleware.ts — ONE public-path entry covers ALL four segments.
|
|
44
|
+
* // This is the structural fix for the tt-intel drift: you cannot mount
|
|
45
|
+
* // 3-of-4 routes and forget the 4th, because the catch-all is one file
|
|
46
|
+
* // and the allowlist is one prefix.
|
|
47
|
+
* const PUBLIC_PATHS = [ ... '/api/kgauto/v2/' ];
|
|
48
|
+
*
|
|
49
|
+
* ### (b) Plain Vercel edge function, per segment
|
|
50
|
+
*
|
|
51
|
+
* // api/kgauto/probe_outcomes.ts
|
|
52
|
+
* export const config = { runtime: 'edge' };
|
|
53
|
+
* const routes = createBrainForwardRoutes({ ... });
|
|
54
|
+
* export default (req: Request) => routes.handle(req, 'probe_outcomes');
|
|
55
|
+
*
|
|
56
|
+
* The library appends the segment path to the consumer's `endpoint`, so the
|
|
57
|
+
* consumer's `KGAUTO_V2_BRAIN_URL` (the value passed to `configureBrain`)
|
|
58
|
+
* must be the base that resolves to `.../api/kgauto/v2` — i.e. the last path
|
|
59
|
+
* segment of each library POST (`outcomes`, `probe_outcomes`, …) is what
|
|
60
|
+
* `handle()` receives as `segment`.
|
|
61
|
+
*
|
|
62
|
+
* ## Quality-segment handle resolution (alpha.55)
|
|
63
|
+
*
|
|
64
|
+
* `recordOutcome()` sends `outcome_id` as `CompileResult.handle` (a string),
|
|
65
|
+
* but `compile_outcome_quality.outcome_id` is a BIGINT FK →
|
|
66
|
+
* `compile_outcomes(id)`. A verbatim forward would 400 every handle-shaped
|
|
67
|
+
* verdict (tt-intel + IC convergent finding, 2026-07-06). On the
|
|
68
|
+
* `compile_outcome_quality` segment the factory resolves non-numeric
|
|
69
|
+
* `outcome_id` values to their BIGINT row ids via
|
|
70
|
+
* `compile_outcomes?handle=eq.<v>` (latest row wins) before forwarding.
|
|
71
|
+
* Numeric ids pass through untouched; an unresolvable handle returns
|
|
72
|
+
* `404 handle_not_found` so the library's route-404 observability names the
|
|
73
|
+
* failure instead of the brain's opaque FK error.
|
|
74
|
+
*/
|
|
75
|
+
interface BrainForwardConfig {
|
|
76
|
+
/** Bearer token consumers' callers must present (usually KGAUTO_INGEST_SECRET). */
|
|
77
|
+
ingestSecret: string;
|
|
78
|
+
/** Brain Supabase project URL (e.g. https://xxxx.supabase.co). */
|
|
79
|
+
brainUrl: string;
|
|
80
|
+
/** Brain service-role key (server-side only). */
|
|
81
|
+
serviceKey: string;
|
|
82
|
+
/** Optional fetch impl for tests. */
|
|
83
|
+
fetchImpl?: typeof fetch;
|
|
84
|
+
}
|
|
85
|
+
interface BrainForwardRoutes {
|
|
86
|
+
/**
|
|
87
|
+
* Web-standard handler. `segment` is the last path segment of the library's
|
|
88
|
+
* POST URL (e.g. 'outcomes', 'probe_outcomes'). In a Next.js catch-all this
|
|
89
|
+
* is `params.segment`. Never throws — every error path returns a `Response`.
|
|
90
|
+
*/
|
|
91
|
+
handle(req: Request, segment: string): Promise<Response>;
|
|
92
|
+
/**
|
|
93
|
+
* The path segments this factory serves. Consumers can use it for route
|
|
94
|
+
* generation, allowlist construction, or tests.
|
|
95
|
+
*/
|
|
96
|
+
segments: readonly string[];
|
|
97
|
+
}
|
|
98
|
+
declare function createBrainForwardRoutes(config: BrainForwardConfig): BrainForwardRoutes;
|
|
99
|
+
|
|
100
|
+
export { type BrainForwardConfig, type BrainForwardRoutes, createBrainForwardRoutes };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/brain-proxy.ts
|
|
21
|
+
var brain_proxy_exports = {};
|
|
22
|
+
__export(brain_proxy_exports, {
|
|
23
|
+
createBrainForwardRoutes: () => createBrainForwardRoutes
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(brain_proxy_exports);
|
|
26
|
+
var SEGMENT_TO_TABLE = {
|
|
27
|
+
outcomes: "compile_outcomes",
|
|
28
|
+
compile_outcome_advisories: "compile_outcome_advisories",
|
|
29
|
+
compile_outcome_quality: "compile_outcome_quality",
|
|
30
|
+
probe_outcomes: "probe_outcomes"
|
|
31
|
+
};
|
|
32
|
+
var KNOWN_SEGMENTS = Object.keys(SEGMENT_TO_TABLE);
|
|
33
|
+
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
34
|
+
function jsonResponse(status, body) {
|
|
35
|
+
return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });
|
|
36
|
+
}
|
|
37
|
+
function bearerOf(req) {
|
|
38
|
+
const header = req.headers.get("Authorization") ?? "";
|
|
39
|
+
const match = /^Bearer\s+(.+)$/i.exec(header);
|
|
40
|
+
return match?.[1]?.trim() ?? "";
|
|
41
|
+
}
|
|
42
|
+
function requireString(name, value) {
|
|
43
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
44
|
+
throw new Error(`createBrainForwardRoutes: ${name} is required`);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function isNumericOutcomeId(value) {
|
|
49
|
+
return typeof value === "number" || typeof value === "string" && /^\d+$/.test(value);
|
|
50
|
+
}
|
|
51
|
+
function createBrainForwardRoutes(config) {
|
|
52
|
+
const ingestSecret = requireString("ingestSecret", config.ingestSecret);
|
|
53
|
+
const brainUrl = requireString("brainUrl", config.brainUrl).replace(/\/+$/, "");
|
|
54
|
+
const serviceKey = requireString("serviceKey", config.serviceKey);
|
|
55
|
+
const fetchFn = config.fetchImpl ?? fetch;
|
|
56
|
+
async function resolveQualityOutcomeIds(body) {
|
|
57
|
+
const rows = Array.isArray(body) ? body : [body];
|
|
58
|
+
const handles = [
|
|
59
|
+
...new Set(
|
|
60
|
+
rows.map((r) => r?.outcome_id).filter(
|
|
61
|
+
(v) => typeof v === "string" && !isNumericOutcomeId(v)
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
];
|
|
65
|
+
if (handles.length === 0) return body;
|
|
66
|
+
const list = handles.map((h) => `"${h.replace(/"/g, "")}"`).join(",");
|
|
67
|
+
const url = `${brainUrl}/rest/v1/compile_outcomes?select=id,handle&handle=in.(${encodeURIComponent(list)})&order=id.desc`;
|
|
68
|
+
let idByHandle;
|
|
69
|
+
try {
|
|
70
|
+
const res = await fetchFn(url, {
|
|
71
|
+
headers: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
const text = await res.text().catch(() => "<no body>");
|
|
75
|
+
return jsonResponse(502, {
|
|
76
|
+
error: "handle-resolution-failed",
|
|
77
|
+
table: "compile_outcome_quality",
|
|
78
|
+
status: res.status,
|
|
79
|
+
detail: text
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const found = await res.json();
|
|
83
|
+
idByHandle = /* @__PURE__ */ new Map();
|
|
84
|
+
for (const r of found) {
|
|
85
|
+
if (!idByHandle.has(r.handle)) idByHandle.set(r.handle, r.id);
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
return jsonResponse(502, {
|
|
89
|
+
error: "handle-resolution-failed",
|
|
90
|
+
table: "compile_outcome_quality",
|
|
91
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const unresolved = handles.filter((h) => !idByHandle.has(h));
|
|
95
|
+
if (unresolved.length > 0) {
|
|
96
|
+
return jsonResponse(404, {
|
|
97
|
+
error: "handle_not_found",
|
|
98
|
+
table: "compile_outcome_quality",
|
|
99
|
+
unresolved
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const rewritten = rows.map(
|
|
103
|
+
(r) => typeof r?.outcome_id === "string" && idByHandle.has(r.outcome_id) ? { ...r, outcome_id: idByHandle.get(r.outcome_id) } : r
|
|
104
|
+
);
|
|
105
|
+
return Array.isArray(body) ? rewritten : rewritten[0];
|
|
106
|
+
}
|
|
107
|
+
async function handle(req, segment) {
|
|
108
|
+
try {
|
|
109
|
+
if (req.method !== "POST") {
|
|
110
|
+
return jsonResponse(405, {
|
|
111
|
+
error: "method-not-allowed",
|
|
112
|
+
method: req.method,
|
|
113
|
+
allowed: ["POST"]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const table = SEGMENT_TO_TABLE[segment];
|
|
117
|
+
if (!table) {
|
|
118
|
+
return jsonResponse(404, {
|
|
119
|
+
error: "unknown-brain-forward-segment",
|
|
120
|
+
segment,
|
|
121
|
+
known: KNOWN_SEGMENTS
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (bearerOf(req) !== ingestSecret) {
|
|
125
|
+
return jsonResponse(401, { error: "unauthorized" });
|
|
126
|
+
}
|
|
127
|
+
let body;
|
|
128
|
+
try {
|
|
129
|
+
body = await req.json();
|
|
130
|
+
} catch {
|
|
131
|
+
return jsonResponse(400, { error: "invalid-json" });
|
|
132
|
+
}
|
|
133
|
+
let row = Array.isArray(body) ? body : { ...body };
|
|
134
|
+
if (table === "compile_outcome_quality") {
|
|
135
|
+
const outcome = await resolveQualityOutcomeIds(row);
|
|
136
|
+
if (outcome instanceof Response) return outcome;
|
|
137
|
+
row = outcome;
|
|
138
|
+
}
|
|
139
|
+
let brainRes;
|
|
140
|
+
try {
|
|
141
|
+
brainRes = await fetchFn(`${brainUrl}/rest/v1/${table}`, {
|
|
142
|
+
method: "POST",
|
|
143
|
+
headers: {
|
|
144
|
+
apikey: serviceKey,
|
|
145
|
+
Authorization: `Bearer ${serviceKey}`,
|
|
146
|
+
"Content-Type": "application/json",
|
|
147
|
+
Prefer: "return=minimal"
|
|
148
|
+
},
|
|
149
|
+
body: JSON.stringify(row)
|
|
150
|
+
});
|
|
151
|
+
} catch (err) {
|
|
152
|
+
return jsonResponse(502, {
|
|
153
|
+
error: "brain-unreachable",
|
|
154
|
+
table,
|
|
155
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (brainRes.ok) {
|
|
159
|
+
return jsonResponse(201, { ok: true });
|
|
160
|
+
}
|
|
161
|
+
const text = await brainRes.text().catch(() => "<no body>");
|
|
162
|
+
return jsonResponse(brainRes.status, {
|
|
163
|
+
error: "brain-write-failed",
|
|
164
|
+
table,
|
|
165
|
+
status: brainRes.status,
|
|
166
|
+
detail: text
|
|
167
|
+
});
|
|
168
|
+
} catch (err) {
|
|
169
|
+
return jsonResponse(500, {
|
|
170
|
+
error: "brain-forward-internal-error",
|
|
171
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { handle, segments: KNOWN_SEGMENTS };
|
|
176
|
+
}
|
|
177
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
178
|
+
0 && (module.exports = {
|
|
179
|
+
createBrainForwardRoutes
|
|
180
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// src/brain-proxy.ts
|
|
2
|
+
var SEGMENT_TO_TABLE = {
|
|
3
|
+
outcomes: "compile_outcomes",
|
|
4
|
+
compile_outcome_advisories: "compile_outcome_advisories",
|
|
5
|
+
compile_outcome_quality: "compile_outcome_quality",
|
|
6
|
+
probe_outcomes: "probe_outcomes"
|
|
7
|
+
};
|
|
8
|
+
var KNOWN_SEGMENTS = Object.keys(SEGMENT_TO_TABLE);
|
|
9
|
+
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
10
|
+
function jsonResponse(status, body) {
|
|
11
|
+
return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });
|
|
12
|
+
}
|
|
13
|
+
function bearerOf(req) {
|
|
14
|
+
const header = req.headers.get("Authorization") ?? "";
|
|
15
|
+
const match = /^Bearer\s+(.+)$/i.exec(header);
|
|
16
|
+
return match?.[1]?.trim() ?? "";
|
|
17
|
+
}
|
|
18
|
+
function requireString(name, value) {
|
|
19
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
20
|
+
throw new Error(`createBrainForwardRoutes: ${name} is required`);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
function isNumericOutcomeId(value) {
|
|
25
|
+
return typeof value === "number" || typeof value === "string" && /^\d+$/.test(value);
|
|
26
|
+
}
|
|
27
|
+
function createBrainForwardRoutes(config) {
|
|
28
|
+
const ingestSecret = requireString("ingestSecret", config.ingestSecret);
|
|
29
|
+
const brainUrl = requireString("brainUrl", config.brainUrl).replace(/\/+$/, "");
|
|
30
|
+
const serviceKey = requireString("serviceKey", config.serviceKey);
|
|
31
|
+
const fetchFn = config.fetchImpl ?? fetch;
|
|
32
|
+
async function resolveQualityOutcomeIds(body) {
|
|
33
|
+
const rows = Array.isArray(body) ? body : [body];
|
|
34
|
+
const handles = [
|
|
35
|
+
...new Set(
|
|
36
|
+
rows.map((r) => r?.outcome_id).filter(
|
|
37
|
+
(v) => typeof v === "string" && !isNumericOutcomeId(v)
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
];
|
|
41
|
+
if (handles.length === 0) return body;
|
|
42
|
+
const list = handles.map((h) => `"${h.replace(/"/g, "")}"`).join(",");
|
|
43
|
+
const url = `${brainUrl}/rest/v1/compile_outcomes?select=id,handle&handle=in.(${encodeURIComponent(list)})&order=id.desc`;
|
|
44
|
+
let idByHandle;
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetchFn(url, {
|
|
47
|
+
headers: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const text = await res.text().catch(() => "<no body>");
|
|
51
|
+
return jsonResponse(502, {
|
|
52
|
+
error: "handle-resolution-failed",
|
|
53
|
+
table: "compile_outcome_quality",
|
|
54
|
+
status: res.status,
|
|
55
|
+
detail: text
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const found = await res.json();
|
|
59
|
+
idByHandle = /* @__PURE__ */ new Map();
|
|
60
|
+
for (const r of found) {
|
|
61
|
+
if (!idByHandle.has(r.handle)) idByHandle.set(r.handle, r.id);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
return jsonResponse(502, {
|
|
65
|
+
error: "handle-resolution-failed",
|
|
66
|
+
table: "compile_outcome_quality",
|
|
67
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const unresolved = handles.filter((h) => !idByHandle.has(h));
|
|
71
|
+
if (unresolved.length > 0) {
|
|
72
|
+
return jsonResponse(404, {
|
|
73
|
+
error: "handle_not_found",
|
|
74
|
+
table: "compile_outcome_quality",
|
|
75
|
+
unresolved
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const rewritten = rows.map(
|
|
79
|
+
(r) => typeof r?.outcome_id === "string" && idByHandle.has(r.outcome_id) ? { ...r, outcome_id: idByHandle.get(r.outcome_id) } : r
|
|
80
|
+
);
|
|
81
|
+
return Array.isArray(body) ? rewritten : rewritten[0];
|
|
82
|
+
}
|
|
83
|
+
async function handle(req, segment) {
|
|
84
|
+
try {
|
|
85
|
+
if (req.method !== "POST") {
|
|
86
|
+
return jsonResponse(405, {
|
|
87
|
+
error: "method-not-allowed",
|
|
88
|
+
method: req.method,
|
|
89
|
+
allowed: ["POST"]
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const table = SEGMENT_TO_TABLE[segment];
|
|
93
|
+
if (!table) {
|
|
94
|
+
return jsonResponse(404, {
|
|
95
|
+
error: "unknown-brain-forward-segment",
|
|
96
|
+
segment,
|
|
97
|
+
known: KNOWN_SEGMENTS
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (bearerOf(req) !== ingestSecret) {
|
|
101
|
+
return jsonResponse(401, { error: "unauthorized" });
|
|
102
|
+
}
|
|
103
|
+
let body;
|
|
104
|
+
try {
|
|
105
|
+
body = await req.json();
|
|
106
|
+
} catch {
|
|
107
|
+
return jsonResponse(400, { error: "invalid-json" });
|
|
108
|
+
}
|
|
109
|
+
let row = Array.isArray(body) ? body : { ...body };
|
|
110
|
+
if (table === "compile_outcome_quality") {
|
|
111
|
+
const outcome = await resolveQualityOutcomeIds(row);
|
|
112
|
+
if (outcome instanceof Response) return outcome;
|
|
113
|
+
row = outcome;
|
|
114
|
+
}
|
|
115
|
+
let brainRes;
|
|
116
|
+
try {
|
|
117
|
+
brainRes = await fetchFn(`${brainUrl}/rest/v1/${table}`, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers: {
|
|
120
|
+
apikey: serviceKey,
|
|
121
|
+
Authorization: `Bearer ${serviceKey}`,
|
|
122
|
+
"Content-Type": "application/json",
|
|
123
|
+
Prefer: "return=minimal"
|
|
124
|
+
},
|
|
125
|
+
body: JSON.stringify(row)
|
|
126
|
+
});
|
|
127
|
+
} catch (err) {
|
|
128
|
+
return jsonResponse(502, {
|
|
129
|
+
error: "brain-unreachable",
|
|
130
|
+
table,
|
|
131
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (brainRes.ok) {
|
|
135
|
+
return jsonResponse(201, { ok: true });
|
|
136
|
+
}
|
|
137
|
+
const text = await brainRes.text().catch(() => "<no body>");
|
|
138
|
+
return jsonResponse(brainRes.status, {
|
|
139
|
+
error: "brain-write-failed",
|
|
140
|
+
table,
|
|
141
|
+
status: brainRes.status,
|
|
142
|
+
detail: text
|
|
143
|
+
});
|
|
144
|
+
} catch (err) {
|
|
145
|
+
return jsonResponse(500, {
|
|
146
|
+
error: "brain-forward-internal-error",
|
|
147
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { handle, segments: KNOWN_SEGMENTS };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
createBrainForwardRoutes
|
|
156
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,7 @@ import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as Provide
|
|
|
2
2
|
export { m as CallAttempt, n as CallError, o as ChainModelEntry, p as ChainWithGrounding, q as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, r as MutationApplied, s as NormalizedTokens, t as OutcomeKind, u as PerAxisMetricsByModel, v as PromptSection, w as SectionKind, x as ShadowProbeConfig, T as ToolCall, y as ToolDefinition } from './ir-CAlLBu5d.mjs';
|
|
3
3
|
import { ModelProfile, ArchetypeConvention } from './profiles.mjs';
|
|
4
4
|
export { ALIASES, CacheStrategy, CliffRule, LATENCY_TIER_MS, LatencyTier, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, latencyTierOf, profilesByProvider, tryGetProfile } from './profiles.mjs';
|
|
5
|
+
export { BrainForwardConfig, BrainForwardRoutes, createBrainForwardRoutes } from './brain-proxy.mjs';
|
|
5
6
|
import { IntentArchetypeName } from './dialect.mjs';
|
|
6
7
|
export { ALL_ARCHETYPES, ContextBucket, DIALECT_VERSION, HistoryDepth, INTENT_ARCHETYPES, OutputMode, ShapeSignature, ToolCountBucket, bucketContext, bucketHistory, bucketToolCount, hashShape, isArchetype, learningKey } from './dialect.mjs';
|
|
7
8
|
|
|
@@ -316,7 +317,10 @@ interface CompileForAISDKv6Result {
|
|
|
316
317
|
/**
|
|
317
318
|
* Index (into post-strip history) for the Anthropic history cache marker
|
|
318
319
|
* (alpha.33). Mirror of `result.diagnostics.historyCacheMarkIndex` — no
|
|
319
|
-
* consumer re-derivation needed. Undefined when no marker fires
|
|
320
|
+
* consumer re-derivation needed. Undefined when no marker fires, and (since
|
|
321
|
+
* alpha.55) always undefined for non-Anthropic targets: the marker is an
|
|
322
|
+
* Anthropic wire concept, other providers cache prefixes implicitly. The
|
|
323
|
+
* ungated value remains on `diagnostics.historyCacheMarkIndex`.
|
|
320
324
|
*/
|
|
321
325
|
historyCacheMarkIndex?: number;
|
|
322
326
|
/** Compile handle — pass to `record()` after the call. */
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as Provide
|
|
|
2
2
|
export { m as CallAttempt, n as CallError, o as ChainModelEntry, p as ChainWithGrounding, q as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, r as MutationApplied, s as NormalizedTokens, t as OutcomeKind, u as PerAxisMetricsByModel, v as PromptSection, w as SectionKind, x as ShadowProbeConfig, T as ToolCall, y as ToolDefinition } from './ir-BiXAMyji.js';
|
|
3
3
|
import { ModelProfile, ArchetypeConvention } from './profiles.js';
|
|
4
4
|
export { ALIASES, CacheStrategy, CliffRule, LATENCY_TIER_MS, LatencyTier, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, latencyTierOf, profilesByProvider, tryGetProfile } from './profiles.js';
|
|
5
|
+
export { BrainForwardConfig, BrainForwardRoutes, createBrainForwardRoutes } from './brain-proxy.js';
|
|
5
6
|
import { IntentArchetypeName } from './dialect.js';
|
|
6
7
|
export { ALL_ARCHETYPES, ContextBucket, DIALECT_VERSION, HistoryDepth, INTENT_ARCHETYPES, OutputMode, ShapeSignature, ToolCountBucket, bucketContext, bucketHistory, bucketToolCount, hashShape, isArchetype, learningKey } from './dialect.js';
|
|
7
8
|
|
|
@@ -316,7 +317,10 @@ interface CompileForAISDKv6Result {
|
|
|
316
317
|
/**
|
|
317
318
|
* Index (into post-strip history) for the Anthropic history cache marker
|
|
318
319
|
* (alpha.33). Mirror of `result.diagnostics.historyCacheMarkIndex` — no
|
|
319
|
-
* consumer re-derivation needed. Undefined when no marker fires
|
|
320
|
+
* consumer re-derivation needed. Undefined when no marker fires, and (since
|
|
321
|
+
* alpha.55) always undefined for non-Anthropic targets: the marker is an
|
|
322
|
+
* Anthropic wire concept, other providers cache prefixes implicitly. The
|
|
323
|
+
* ungated value remains on `diagnostics.historyCacheMarkIndex`.
|
|
320
324
|
*/
|
|
321
325
|
historyCacheMarkIndex?: number;
|
|
322
326
|
/** Compile handle — pass to `record()` after the call. */
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
compileForAISDKv6: () => compileForAISDKv6,
|
|
52
52
|
configureBrain: () => configureBrain,
|
|
53
53
|
countTokens: () => countTokens,
|
|
54
|
+
createBrainForwardRoutes: () => createBrainForwardRoutes,
|
|
54
55
|
deriveFamilyFromModelId: () => deriveFamilyFromModelId,
|
|
55
56
|
deriveOwnership: () => deriveOwnership,
|
|
56
57
|
execute: () => execute,
|
|
@@ -6733,7 +6734,12 @@ function compileForAISDKv6(ir, opts) {
|
|
|
6733
6734
|
},
|
|
6734
6735
|
keptToolNames,
|
|
6735
6736
|
...providerOptions ? { providerOptions } : {},
|
|
6736
|
-
|
|
6737
|
+
// Provider-gated (alpha.55, IC finding): the marker is an Anthropic
|
|
6738
|
+
// concept — Gemini/OpenAI/DeepSeek cache prefixes implicitly, and a
|
|
6739
|
+
// consumer attaching Anthropic providerOptions at this index on a
|
|
6740
|
+
// non-Anthropic call would ship a no-op-at-best marker. The ungated value
|
|
6741
|
+
// stays on diagnostics.historyCacheMarkIndex for observability.
|
|
6742
|
+
...result.provider === "anthropic" && result.diagnostics.historyCacheMarkIndex !== void 0 ? { historyCacheMarkIndex: result.diagnostics.historyCacheMarkIndex } : {},
|
|
6737
6743
|
mutationsApplied: result.mutationsApplied.map((m) => m.id),
|
|
6738
6744
|
advisories: result.advisories ?? [],
|
|
6739
6745
|
diagnostics,
|
|
@@ -6761,6 +6767,159 @@ function extractKeptToolNames(result) {
|
|
|
6761
6767
|
return names;
|
|
6762
6768
|
}
|
|
6763
6769
|
|
|
6770
|
+
// src/brain-proxy.ts
|
|
6771
|
+
var SEGMENT_TO_TABLE = {
|
|
6772
|
+
outcomes: "compile_outcomes",
|
|
6773
|
+
compile_outcome_advisories: "compile_outcome_advisories",
|
|
6774
|
+
compile_outcome_quality: "compile_outcome_quality",
|
|
6775
|
+
probe_outcomes: "probe_outcomes"
|
|
6776
|
+
};
|
|
6777
|
+
var KNOWN_SEGMENTS = Object.keys(SEGMENT_TO_TABLE);
|
|
6778
|
+
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
6779
|
+
function jsonResponse(status, body) {
|
|
6780
|
+
return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });
|
|
6781
|
+
}
|
|
6782
|
+
function bearerOf(req) {
|
|
6783
|
+
const header = req.headers.get("Authorization") ?? "";
|
|
6784
|
+
const match = /^Bearer\s+(.+)$/i.exec(header);
|
|
6785
|
+
return match?.[1]?.trim() ?? "";
|
|
6786
|
+
}
|
|
6787
|
+
function requireString(name, value) {
|
|
6788
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
6789
|
+
throw new Error(`createBrainForwardRoutes: ${name} is required`);
|
|
6790
|
+
}
|
|
6791
|
+
return value;
|
|
6792
|
+
}
|
|
6793
|
+
function isNumericOutcomeId(value) {
|
|
6794
|
+
return typeof value === "number" || typeof value === "string" && /^\d+$/.test(value);
|
|
6795
|
+
}
|
|
6796
|
+
function createBrainForwardRoutes(config) {
|
|
6797
|
+
const ingestSecret = requireString("ingestSecret", config.ingestSecret);
|
|
6798
|
+
const brainUrl = requireString("brainUrl", config.brainUrl).replace(/\/+$/, "");
|
|
6799
|
+
const serviceKey = requireString("serviceKey", config.serviceKey);
|
|
6800
|
+
const fetchFn = config.fetchImpl ?? fetch;
|
|
6801
|
+
async function resolveQualityOutcomeIds(body) {
|
|
6802
|
+
const rows = Array.isArray(body) ? body : [body];
|
|
6803
|
+
const handles = [
|
|
6804
|
+
...new Set(
|
|
6805
|
+
rows.map((r) => r?.outcome_id).filter(
|
|
6806
|
+
(v) => typeof v === "string" && !isNumericOutcomeId(v)
|
|
6807
|
+
)
|
|
6808
|
+
)
|
|
6809
|
+
];
|
|
6810
|
+
if (handles.length === 0) return body;
|
|
6811
|
+
const list = handles.map((h) => `"${h.replace(/"/g, "")}"`).join(",");
|
|
6812
|
+
const url = `${brainUrl}/rest/v1/compile_outcomes?select=id,handle&handle=in.(${encodeURIComponent(list)})&order=id.desc`;
|
|
6813
|
+
let idByHandle;
|
|
6814
|
+
try {
|
|
6815
|
+
const res = await fetchFn(url, {
|
|
6816
|
+
headers: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` }
|
|
6817
|
+
});
|
|
6818
|
+
if (!res.ok) {
|
|
6819
|
+
const text = await res.text().catch(() => "<no body>");
|
|
6820
|
+
return jsonResponse(502, {
|
|
6821
|
+
error: "handle-resolution-failed",
|
|
6822
|
+
table: "compile_outcome_quality",
|
|
6823
|
+
status: res.status,
|
|
6824
|
+
detail: text
|
|
6825
|
+
});
|
|
6826
|
+
}
|
|
6827
|
+
const found = await res.json();
|
|
6828
|
+
idByHandle = /* @__PURE__ */ new Map();
|
|
6829
|
+
for (const r of found) {
|
|
6830
|
+
if (!idByHandle.has(r.handle)) idByHandle.set(r.handle, r.id);
|
|
6831
|
+
}
|
|
6832
|
+
} catch (err) {
|
|
6833
|
+
return jsonResponse(502, {
|
|
6834
|
+
error: "handle-resolution-failed",
|
|
6835
|
+
table: "compile_outcome_quality",
|
|
6836
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
6837
|
+
});
|
|
6838
|
+
}
|
|
6839
|
+
const unresolved = handles.filter((h) => !idByHandle.has(h));
|
|
6840
|
+
if (unresolved.length > 0) {
|
|
6841
|
+
return jsonResponse(404, {
|
|
6842
|
+
error: "handle_not_found",
|
|
6843
|
+
table: "compile_outcome_quality",
|
|
6844
|
+
unresolved
|
|
6845
|
+
});
|
|
6846
|
+
}
|
|
6847
|
+
const rewritten = rows.map(
|
|
6848
|
+
(r) => typeof r?.outcome_id === "string" && idByHandle.has(r.outcome_id) ? { ...r, outcome_id: idByHandle.get(r.outcome_id) } : r
|
|
6849
|
+
);
|
|
6850
|
+
return Array.isArray(body) ? rewritten : rewritten[0];
|
|
6851
|
+
}
|
|
6852
|
+
async function handle(req, segment) {
|
|
6853
|
+
try {
|
|
6854
|
+
if (req.method !== "POST") {
|
|
6855
|
+
return jsonResponse(405, {
|
|
6856
|
+
error: "method-not-allowed",
|
|
6857
|
+
method: req.method,
|
|
6858
|
+
allowed: ["POST"]
|
|
6859
|
+
});
|
|
6860
|
+
}
|
|
6861
|
+
const table = SEGMENT_TO_TABLE[segment];
|
|
6862
|
+
if (!table) {
|
|
6863
|
+
return jsonResponse(404, {
|
|
6864
|
+
error: "unknown-brain-forward-segment",
|
|
6865
|
+
segment,
|
|
6866
|
+
known: KNOWN_SEGMENTS
|
|
6867
|
+
});
|
|
6868
|
+
}
|
|
6869
|
+
if (bearerOf(req) !== ingestSecret) {
|
|
6870
|
+
return jsonResponse(401, { error: "unauthorized" });
|
|
6871
|
+
}
|
|
6872
|
+
let body;
|
|
6873
|
+
try {
|
|
6874
|
+
body = await req.json();
|
|
6875
|
+
} catch {
|
|
6876
|
+
return jsonResponse(400, { error: "invalid-json" });
|
|
6877
|
+
}
|
|
6878
|
+
let row = Array.isArray(body) ? body : { ...body };
|
|
6879
|
+
if (table === "compile_outcome_quality") {
|
|
6880
|
+
const outcome = await resolveQualityOutcomeIds(row);
|
|
6881
|
+
if (outcome instanceof Response) return outcome;
|
|
6882
|
+
row = outcome;
|
|
6883
|
+
}
|
|
6884
|
+
let brainRes;
|
|
6885
|
+
try {
|
|
6886
|
+
brainRes = await fetchFn(`${brainUrl}/rest/v1/${table}`, {
|
|
6887
|
+
method: "POST",
|
|
6888
|
+
headers: {
|
|
6889
|
+
apikey: serviceKey,
|
|
6890
|
+
Authorization: `Bearer ${serviceKey}`,
|
|
6891
|
+
"Content-Type": "application/json",
|
|
6892
|
+
Prefer: "return=minimal"
|
|
6893
|
+
},
|
|
6894
|
+
body: JSON.stringify(row)
|
|
6895
|
+
});
|
|
6896
|
+
} catch (err) {
|
|
6897
|
+
return jsonResponse(502, {
|
|
6898
|
+
error: "brain-unreachable",
|
|
6899
|
+
table,
|
|
6900
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
6901
|
+
});
|
|
6902
|
+
}
|
|
6903
|
+
if (brainRes.ok) {
|
|
6904
|
+
return jsonResponse(201, { ok: true });
|
|
6905
|
+
}
|
|
6906
|
+
const text = await brainRes.text().catch(() => "<no body>");
|
|
6907
|
+
return jsonResponse(brainRes.status, {
|
|
6908
|
+
error: "brain-write-failed",
|
|
6909
|
+
table,
|
|
6910
|
+
status: brainRes.status,
|
|
6911
|
+
detail: text
|
|
6912
|
+
});
|
|
6913
|
+
} catch (err) {
|
|
6914
|
+
return jsonResponse(500, {
|
|
6915
|
+
error: "brain-forward-internal-error",
|
|
6916
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
6917
|
+
});
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6920
|
+
return { handle, segments: KNOWN_SEGMENTS };
|
|
6921
|
+
}
|
|
6922
|
+
|
|
6764
6923
|
// src/oracle.ts
|
|
6765
6924
|
var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
|
|
6766
6925
|
var judgeCallTimes = [];
|
|
@@ -7220,6 +7379,7 @@ function compile2(ir, opts) {
|
|
|
7220
7379
|
compileForAISDKv6,
|
|
7221
7380
|
configureBrain,
|
|
7222
7381
|
countTokens,
|
|
7382
|
+
createBrainForwardRoutes,
|
|
7223
7383
|
deriveFamilyFromModelId,
|
|
7224
7384
|
deriveOwnership,
|
|
7225
7385
|
execute,
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createBrainForwardRoutes
|
|
3
|
+
} from "./chunk-WVICNOLA.mjs";
|
|
1
4
|
import {
|
|
2
5
|
ALL_ARCHETYPES,
|
|
3
6
|
DIALECT_VERSION,
|
|
@@ -4172,7 +4175,12 @@ function compileForAISDKv6(ir, opts) {
|
|
|
4172
4175
|
},
|
|
4173
4176
|
keptToolNames,
|
|
4174
4177
|
...providerOptions ? { providerOptions } : {},
|
|
4175
|
-
|
|
4178
|
+
// Provider-gated (alpha.55, IC finding): the marker is an Anthropic
|
|
4179
|
+
// concept — Gemini/OpenAI/DeepSeek cache prefixes implicitly, and a
|
|
4180
|
+
// consumer attaching Anthropic providerOptions at this index on a
|
|
4181
|
+
// non-Anthropic call would ship a no-op-at-best marker. The ungated value
|
|
4182
|
+
// stays on diagnostics.historyCacheMarkIndex for observability.
|
|
4183
|
+
...result.provider === "anthropic" && result.diagnostics.historyCacheMarkIndex !== void 0 ? { historyCacheMarkIndex: result.diagnostics.historyCacheMarkIndex } : {},
|
|
4176
4184
|
mutationsApplied: result.mutationsApplied.map((m) => m.id),
|
|
4177
4185
|
advisories: result.advisories ?? [],
|
|
4178
4186
|
diagnostics,
|
|
@@ -4658,6 +4666,7 @@ export {
|
|
|
4658
4666
|
compileForAISDKv6,
|
|
4659
4667
|
configureBrain,
|
|
4660
4668
|
countTokens,
|
|
4669
|
+
createBrainForwardRoutes,
|
|
4661
4670
|
deriveFamilyFromModelId,
|
|
4662
4671
|
deriveOwnership,
|
|
4663
4672
|
execute,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warmdrift/kgauto-compiler",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.55",
|
|
4
4
|
"description": "Prompt compiler + central learning brain for multi-model AI apps. Swap models without rewriting prompts.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"import": "./dist/profiles.mjs",
|
|
22
22
|
"require": "./dist/profiles.js"
|
|
23
23
|
},
|
|
24
|
+
"./brain-proxy": {
|
|
25
|
+
"types": "./dist/brain-proxy.d.ts",
|
|
26
|
+
"import": "./dist/brain-proxy.mjs",
|
|
27
|
+
"require": "./dist/brain-proxy.js"
|
|
28
|
+
},
|
|
24
29
|
"./glassbox": {
|
|
25
30
|
"types": "./dist/glassbox/index.d.ts",
|
|
26
31
|
"import": "./dist/glassbox/index.mjs",
|
|
@@ -47,7 +52,7 @@
|
|
|
47
52
|
"README.md"
|
|
48
53
|
],
|
|
49
54
|
"scripts": {
|
|
50
|
-
"build": "tsup src/index.ts src/dialect.ts src/profiles.ts src/glassbox/index.ts src/glassbox-routes/index.ts src/glassbox-routes/format.ts src/glassbox-routes/react/index.ts --format cjs,esm --dts --clean --external react --external react-dom",
|
|
55
|
+
"build": "tsup src/index.ts src/dialect.ts src/profiles.ts src/brain-proxy.ts src/glassbox/index.ts src/glassbox-routes/index.ts src/glassbox-routes/format.ts src/glassbox-routes/react/index.ts --format cjs,esm --dts --clean --external react --external react-dom",
|
|
51
56
|
"test": "vitest run",
|
|
52
57
|
"test:watch": "vitest",
|
|
53
58
|
"typecheck": "tsc --noEmit",
|