@sanity/ailf 3.4.0 → 3.5.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/config/airbyte/ai_literacy_framework.connector.yaml +114 -0
- package/config/bigquery/README.md +11 -4
- package/config/bigquery/views/official_area_scores.sql +20 -0
- package/config/bigquery/views/official_runs.sql +31 -0
- package/config/bigquery/views/reports.sql +19 -0
- package/config/bigquery/views/team_runs_template.sql +17 -0
- package/dist/_vendor/ailf-core/examples/index.d.ts +1 -1
- package/dist/_vendor/ailf-core/examples/index.js +1 -1
- package/dist/_vendor/ailf-core/ports/context.d.ts +25 -0
- package/dist/_vendor/ailf-core/schemas/pipeline-request.d.ts +23 -0
- package/dist/_vendor/ailf-core/schemas/pipeline-request.js +59 -1
- package/dist/_vendor/ailf-shared/index.d.ts +2 -0
- package/dist/_vendor/ailf-shared/index.js +2 -0
- package/dist/_vendor/ailf-shared/owner-teams.d.ts +26 -0
- package/dist/_vendor/ailf-shared/owner-teams.js +52 -0
- package/dist/_vendor/ailf-shared/run-classification.d.ts +100 -0
- package/dist/_vendor/ailf-shared/run-classification.js +28 -0
- package/dist/_vendor/ailf-shared/run-context.d.ts +23 -0
- package/dist/adapters/api-client/build-request.d.ts +31 -0
- package/dist/adapters/api-client/build-request.js +82 -1
- package/dist/adapters/api-client/index.d.ts +1 -1
- package/dist/adapters/api-client/index.js +1 -1
- package/dist/adapters/task-sources/repo-validation.js +4 -2
- package/dist/commands/explain-handler.js +5 -0
- package/dist/commands/init.js +5 -0
- package/dist/commands/pipeline-action.d.ts +6 -0
- package/dist/commands/pipeline-action.js +5 -0
- package/dist/commands/pipeline.d.ts +5 -0
- package/dist/commands/pipeline.js +15 -0
- package/dist/commands/remote-pipeline.js +7 -0
- package/dist/orchestration/steps/finalize-run-step.js +1 -0
- package/dist/orchestration/steps/publish-report-step.js +1 -0
- package/dist/pipeline/map-request-to-config.js +18 -0
- package/dist/pipeline/run-context.d.ts +63 -0
- package/dist/pipeline/run-context.js +166 -0
- package/package.json +1 -1
|
@@ -12,8 +12,13 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @see docs/decisions/D0032-run-anchored-artifact-store.md (§ Move 5 — Drift Prevention)
|
|
14
14
|
*/
|
|
15
|
+
import { execSync } from "node:child_process";
|
|
16
|
+
import { createRequire } from "node:module";
|
|
17
|
+
import * as os from "node:os";
|
|
18
|
+
import { isRunClassification, } from "../_vendor/ailf-shared/index.js";
|
|
15
19
|
import { ConsoleLogger } from "../adapters/loggers/index.js";
|
|
16
20
|
import { tryLoadConfigFile } from "./compiler/config-loader.js";
|
|
21
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
17
22
|
/**
|
|
18
23
|
* Derive `RunContext` from pipeline inputs. The only construction path.
|
|
19
24
|
*
|
|
@@ -35,6 +40,21 @@ export function buildRunContext(input) {
|
|
|
35
40
|
}
|
|
36
41
|
: detectGitMetadata();
|
|
37
42
|
const trigger = detectTrigger();
|
|
43
|
+
// D0037: caller envelope (from PipelineRequest) takes precedence over
|
|
44
|
+
// server-env detection — same pattern as `callerGit` for identity
|
|
45
|
+
// preservation across the --remote boundary.
|
|
46
|
+
const envelope = input.callerEnvelope;
|
|
47
|
+
const classification = envelope?.classification ?? detectClassification(log);
|
|
48
|
+
const owner = envelope?.owner ?? detectOwner();
|
|
49
|
+
const executor = envelope?.executor ?? detectExecutor();
|
|
50
|
+
// `tool` and `host` are server-environment facts — they always reflect
|
|
51
|
+
// where this pipeline is actually running, never what a caller claimed.
|
|
52
|
+
// Callers cannot override these via the envelope and the wire schema
|
|
53
|
+
// explicitly doesn't carry them (see pipeline-request.ts).
|
|
54
|
+
const tool = detectTool(log);
|
|
55
|
+
const host = detectHost();
|
|
56
|
+
const labels = envelope?.labels ?? detectLabels();
|
|
57
|
+
const purpose = envelope?.purpose ?? (process.env.AILF_PURPOSE?.trim() || undefined);
|
|
38
58
|
// Non-literacy modes (agent-harness, mcp-server, etc.) don't use the
|
|
39
59
|
// config/models.ts model matrix — listing those models would be
|
|
40
60
|
// misleading. Only include them for literacy mode where they're the
|
|
@@ -44,11 +64,18 @@ export function buildRunContext(input) {
|
|
|
44
64
|
: [];
|
|
45
65
|
return {
|
|
46
66
|
areas: input.areas,
|
|
67
|
+
classification,
|
|
47
68
|
evalFingerprint: input.evalFingerprint,
|
|
69
|
+
executor,
|
|
48
70
|
git,
|
|
49
71
|
graderModel: models.grader.id,
|
|
72
|
+
host,
|
|
73
|
+
labels,
|
|
74
|
+
lineage: input.lineage,
|
|
50
75
|
mode: input.mode,
|
|
51
76
|
models: evaluatedModels,
|
|
77
|
+
owner,
|
|
78
|
+
purpose,
|
|
52
79
|
source: {
|
|
53
80
|
baseUrl: input.source.baseUrl,
|
|
54
81
|
dataset: input.source.dataset,
|
|
@@ -57,6 +84,7 @@ export function buildRunContext(input) {
|
|
|
57
84
|
projectId: input.source.projectId,
|
|
58
85
|
},
|
|
59
86
|
taskIds: input.taskIds,
|
|
87
|
+
tool,
|
|
60
88
|
trigger,
|
|
61
89
|
};
|
|
62
90
|
}
|
|
@@ -137,6 +165,144 @@ function detectTrigger() {
|
|
|
137
165
|
return { type: "manual" };
|
|
138
166
|
}
|
|
139
167
|
// ---------------------------------------------------------------------------
|
|
168
|
+
// Classification, owner, executor, labels, tool, host detection (D0037)
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
/**
|
|
171
|
+
* Resolve `classification` from `AILF_CLASSIFICATION`, validated against
|
|
172
|
+
* the closed enum. Defaults to `"ad-hoc"` so unannotated runs never leak
|
|
173
|
+
* into the canonical `"official"` series.
|
|
174
|
+
*/
|
|
175
|
+
export function detectClassification(log) {
|
|
176
|
+
const raw = process.env.AILF_CLASSIFICATION?.trim();
|
|
177
|
+
if (!raw)
|
|
178
|
+
return "ad-hoc";
|
|
179
|
+
if (isRunClassification(raw))
|
|
180
|
+
return raw;
|
|
181
|
+
log.warn(`AILF_CLASSIFICATION="${raw}" is not a recognized value; defaulting to "ad-hoc"`);
|
|
182
|
+
return "ad-hoc";
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Resolve `owner` from `AILF_OWNER_TEAM` (+ optional
|
|
186
|
+
* `AILF_OWNER_INDIVIDUAL`). `team` is free-form; default is `"unknown"`.
|
|
187
|
+
*/
|
|
188
|
+
export function detectOwner() {
|
|
189
|
+
const team = process.env.AILF_OWNER_TEAM?.trim() || "unknown";
|
|
190
|
+
const individual = process.env.AILF_OWNER_INDIVIDUAL?.trim() || undefined;
|
|
191
|
+
return individual ? { individual, team } : { team };
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Detect who/what invoked the run.
|
|
195
|
+
*
|
|
196
|
+
* Priority:
|
|
197
|
+
* 1. GitHub Actions context → `{ type: "system", name: "github-actions", ... }`
|
|
198
|
+
* 2. CLI context → `{ type: "user", surface: "cli", ... }` with git-config
|
|
199
|
+
* or OS username fallback. Email capture gated by
|
|
200
|
+
* `AILF_CAPTURE_EMAIL` (default on; set `0` to opt out).
|
|
201
|
+
*
|
|
202
|
+
* Every identity field is optional — missing git, containers, or masked
|
|
203
|
+
* env vars must never block a run.
|
|
204
|
+
*/
|
|
205
|
+
export function detectExecutor() {
|
|
206
|
+
if (process.env.GITHUB_ACTIONS === "true") {
|
|
207
|
+
return {
|
|
208
|
+
name: "github-actions",
|
|
209
|
+
runId: process.env.GITHUB_RUN_ID?.trim() || undefined,
|
|
210
|
+
type: "system",
|
|
211
|
+
workflow: process.env.GITHUB_WORKFLOW?.trim() || undefined,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
const surface = resolveExecutorSurface();
|
|
215
|
+
const githubActor = process.env.GITHUB_ACTOR?.trim() || undefined;
|
|
216
|
+
const name = detectGitConfig("user.name") ?? githubActor ?? osUsername() ?? undefined;
|
|
217
|
+
const email = shouldCaptureEmail() ? detectGitConfig("user.email") : undefined;
|
|
218
|
+
const exec = { surface, type: "user" };
|
|
219
|
+
if (name)
|
|
220
|
+
exec.name = name;
|
|
221
|
+
if (email)
|
|
222
|
+
exec.email = email;
|
|
223
|
+
if (githubActor)
|
|
224
|
+
exec.githubActor = githubActor;
|
|
225
|
+
return exec;
|
|
226
|
+
}
|
|
227
|
+
function resolveExecutorSurface() {
|
|
228
|
+
const explicit = process.env.AILF_EXECUTOR_SURFACE?.trim();
|
|
229
|
+
if (explicit === "cli" || explicit === "studio" || explicit === "api") {
|
|
230
|
+
return explicit;
|
|
231
|
+
}
|
|
232
|
+
return "cli";
|
|
233
|
+
}
|
|
234
|
+
function shouldCaptureEmail() {
|
|
235
|
+
const raw = process.env.AILF_CAPTURE_EMAIL?.trim().toLowerCase();
|
|
236
|
+
if (raw === "0" || raw === "false" || raw === "no")
|
|
237
|
+
return false;
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
function detectGitConfig(key) {
|
|
241
|
+
try {
|
|
242
|
+
const value = execSync(`git config --get ${key}`, {
|
|
243
|
+
encoding: "utf8",
|
|
244
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
245
|
+
timeout: 500,
|
|
246
|
+
}).trim();
|
|
247
|
+
return value || undefined;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function osUsername() {
|
|
254
|
+
try {
|
|
255
|
+
return os.userInfo().username || undefined;
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Parse `AILF_LABELS` (comma-separated) into a trimmed unique list.
|
|
263
|
+
* Returns undefined when empty so absent labels stay absent.
|
|
264
|
+
*/
|
|
265
|
+
function detectLabels() {
|
|
266
|
+
const raw = process.env.AILF_LABELS;
|
|
267
|
+
if (!raw)
|
|
268
|
+
return undefined;
|
|
269
|
+
const labels = raw
|
|
270
|
+
.split(",")
|
|
271
|
+
.map((label) => label.trim())
|
|
272
|
+
.filter(Boolean);
|
|
273
|
+
if (labels.length === 0)
|
|
274
|
+
return undefined;
|
|
275
|
+
return Array.from(new Set(labels));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Resolve `tool` — which AILF/Node ran the eval. Captured on every new
|
|
279
|
+
* run so cross-version trend comparisons can isolate framework changes
|
|
280
|
+
* from doc changes.
|
|
281
|
+
*/
|
|
282
|
+
export function detectTool(log) {
|
|
283
|
+
const nodeVersion = process.version;
|
|
284
|
+
let ailfVersion;
|
|
285
|
+
try {
|
|
286
|
+
const pkg = requireFromHere("../../package.json");
|
|
287
|
+
ailfVersion = pkg.version;
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
log.warn(`Could not read @sanity/ailf package.json for tool.ailfVersion: ${err instanceof Error ? err.message : String(err)}`);
|
|
291
|
+
}
|
|
292
|
+
return { ailfVersion: ailfVersion ?? "unknown", nodeVersion };
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Resolve `host` — platform + arch + CI provider. Hostname is
|
|
296
|
+
* intentionally excluded (leaks identity without filtering benefit).
|
|
297
|
+
*/
|
|
298
|
+
export function detectHost() {
|
|
299
|
+
const ci = process.env.GITHUB_ACTIONS === "true" ? "github-actions" : undefined;
|
|
300
|
+
const host = { arch: os.arch(), platform: os.platform() };
|
|
301
|
+
if (ci)
|
|
302
|
+
host.ci = ci;
|
|
303
|
+
return host;
|
|
304
|
+
}
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
140
306
|
// Model config loading
|
|
141
307
|
// ---------------------------------------------------------------------------
|
|
142
308
|
/**
|