anpord 0.1.18 → 0.1.20
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/api-context.cjs +1 -1
- package/dist/api-context.d.cts +1 -1
- package/dist/api-context.d.mts +1 -1
- package/dist/api-context.mjs +1 -1
- package/dist/{api-mocks-CuVw86Qw.cjs → api-mocks-BjnewAya.cjs} +1 -1
- package/dist/{api-mocks-wNUnpzJf.mjs → api-mocks-C3SsliJZ.mjs} +1 -1
- package/dist/{api-mocks-CAQFqUgY.d.cts → api-mocks-xXKzUFc9.d.cts} +2 -2
- package/dist/{api-mocks-CAQFqUgY.d.mts → api-mocks-xXKzUFc9.d.mts} +2 -2
- package/dist/api-runtime.cjs +1 -1
- package/dist/api-runtime.d.cts +1 -1
- package/dist/api-runtime.d.mts +1 -1
- package/dist/api-runtime.mjs +1 -1
- package/dist/api.cjs +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.mts +1 -1
- package/dist/api.mjs +1 -1
- package/dist/bin.cjs +138 -20
- package/dist/bin.mjs +139 -21
- package/dist/{client-dRUs93gl.d.cts → client-BD2VyKja.d.cts} +1101 -505
- package/dist/{client-DDYWBAma.d.mts → client-ClWUDcPC.d.mts} +1101 -505
- package/dist/{client-DziJjMFh.cjs → client-D4SBJEsG.cjs} +24 -2
- package/dist/{client-DE3YNtWc.mjs → client-DCSRP55Q.mjs} +24 -2
- package/dist/{compiler-WpuZwsp9.mjs → compiler-BKchnKps.mjs} +3 -2
- package/dist/{compiler-XtLHSR2J.cjs → compiler-DSN62KNe.cjs} +3 -2
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -1
- package/dist/{eval-judges--be3T7fJ.d.mts → eval-turns-CTCoSuB6.d.cts} +30 -1
- package/dist/{eval-judges--be3T7fJ.d.cts → eval-turns-CTCoSuB6.d.mts} +30 -1
- package/dist/eval-turns-DZTHit19.mjs +22 -0
- package/dist/eval-turns-weR_7JIp.cjs +39 -0
- package/dist/{eval-validations-BvX9dkYh.mjs → eval-validations-CUG2PvR_.mjs} +1 -1
- package/dist/{eval-validations-BdlPhudg.cjs → eval-validations-D0Cz6xSg.cjs} +1 -1
- package/dist/eval.cjs +1 -1
- package/dist/eval.d.cts +1 -1
- package/dist/eval.d.mts +1 -1
- package/dist/eval.mjs +1 -1
- package/dist/{evals-B2UuSop0.d.cts → evals-WMHOpPxd.d.cts} +52 -55
- package/dist/{evals-B2UuSop0.d.mts → evals-WMHOpPxd.d.mts} +52 -55
- package/dist/{evals-api-CsdU741J.mjs → evals-api-B0lnr_R8.mjs} +90 -70
- package/dist/{evals-api-CqhPZCr5.cjs → evals-api-DuDr8UdV.cjs} +113 -69
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +38 -6
- package/dist/index.d.mts +38 -6
- package/dist/index.mjs +2 -2
- package/dist/{runtime-CXcsGvwP.cjs → runtime-B5it0Siy.cjs} +2 -2
- package/dist/{runtime-DDUrsAI-.mjs → runtime-ChWJywJY.mjs} +2 -2
- package/dist/source.d.cts +1 -1
- package/dist/source.d.mts +1 -1
- package/dist/{types-2vK8mBga.d.cts → types-CUVZ1A_F.d.cts} +32 -14
- package/dist/{types-C6yDL7ZQ.d.mts → types-Cw5k37Uk.d.mts} +32 -14
- package/dist/validator-runtime.cjs +9 -1
- package/dist/validator-runtime.d.cts +1 -1
- package/dist/validator-runtime.d.mts +1 -1
- package/dist/validator-runtime.mjs +9 -1
- package/dist/validators.cjs +50 -0
- package/dist/validators.d.cts +41 -2
- package/dist/validators.d.mts +41 -2
- package/dist/validators.mjs +48 -1
- package/package.json +1 -1
package/dist/api-context.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_api_mocks = require("./api-mocks-
|
|
2
|
+
const require_api_mocks = require("./api-mocks-BjnewAya.cjs");
|
|
3
3
|
let effect = require("effect");
|
|
4
4
|
let node_fs_promises = require("node:fs/promises");
|
|
5
5
|
//#region src/mock-api/context.ts
|
package/dist/api-context.d.cts
CHANGED
package/dist/api-context.d.mts
CHANGED
package/dist/api-context.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ApiCall, n as API_MANIFEST, o as ApiManifest, t as API_JOURNAL } from "./api-mocks-
|
|
1
|
+
import { a as ApiCall, n as API_MANIFEST, o as ApiManifest, t as API_JOURNAL } from "./api-mocks-C3SsliJZ.mjs";
|
|
2
2
|
import { Schema } from "effect";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
//#region src/mock-api/context.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_eval_validations = require("./eval-validations-
|
|
1
|
+
const require_eval_validations = require("./eval-validations-D0Cz6xSg.cjs");
|
|
2
2
|
let effect = require("effect");
|
|
3
3
|
//#region ../schema/src/domain/api-mocks.ts
|
|
4
4
|
const API_PROGRAM = "workspace/.anpord/api/program.json";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as ValidationValue } from "./eval-validations-
|
|
1
|
+
import { r as ValidationValue } from "./eval-validations-CUG2PvR_.mjs";
|
|
2
2
|
import { Schema } from "effect";
|
|
3
3
|
//#region ../schema/src/domain/api-mocks.ts
|
|
4
4
|
const API_PROGRAM = "workspace/.anpord/api/program.json";
|
|
@@ -58,10 +58,10 @@ declare const ApiCall_base: Schema.Class<ApiCall, {
|
|
|
58
58
|
}>>>;
|
|
59
59
|
}>, never, {
|
|
60
60
|
readonly api: string;
|
|
61
|
-
} & {
|
|
62
|
-
readonly startedAt: number;
|
|
63
61
|
} & {
|
|
64
62
|
readonly status: number;
|
|
63
|
+
} & {
|
|
64
|
+
readonly startedAt: number;
|
|
65
65
|
} & {
|
|
66
66
|
readonly path: string;
|
|
67
67
|
} & {
|
|
@@ -58,10 +58,10 @@ declare const ApiCall_base: Schema.Class<ApiCall, {
|
|
|
58
58
|
}>>>;
|
|
59
59
|
}>, never, {
|
|
60
60
|
readonly api: string;
|
|
61
|
-
} & {
|
|
62
|
-
readonly startedAt: number;
|
|
63
61
|
} & {
|
|
64
62
|
readonly status: number;
|
|
63
|
+
} & {
|
|
64
|
+
readonly startedAt: number;
|
|
65
65
|
} & {
|
|
66
66
|
readonly path: string;
|
|
67
67
|
} & {
|
package/dist/api-runtime.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_runtime = require("./runtime-
|
|
2
|
+
const require_runtime = require("./runtime-B5it0Siy.cjs");
|
|
3
3
|
exports.runApiServers = require_runtime.runApiServers;
|
|
4
4
|
exports.withApi = require_runtime.withApi;
|
package/dist/api-runtime.d.cts
CHANGED
package/dist/api-runtime.d.mts
CHANGED
package/dist/api-runtime.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as withApi, t as runApiServers } from "./runtime-
|
|
1
|
+
import { n as withApi, t as runApiServers } from "./runtime-ChWJywJY.mjs";
|
|
2
2
|
export { runApiServers, withApi };
|
package/dist/api.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_runtime = require("./runtime-
|
|
2
|
+
const require_runtime = require("./runtime-B5it0Siy.cjs");
|
|
3
3
|
exports.api = require_runtime.api;
|
|
4
4
|
exports.endpoint = require_runtime.endpoint;
|
|
5
5
|
exports.withApi = require_runtime.withApi;
|
package/dist/api.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ApiCall } from "./api-mocks-
|
|
1
|
+
import { t as ApiCall } from "./api-mocks-xXKzUFc9.cjs";
|
|
2
2
|
import { a as endpoint, i as api, n as ApiHandlerContext, r as EndpointDefinition, t as ApiDefinition } from "./define-NZvmQuIv.cjs";
|
|
3
3
|
import { withApi } from "./api-runtime.cjs";
|
|
4
4
|
export { type ApiCall, type ApiDefinition, type ApiHandlerContext, type EndpointDefinition, api, endpoint, withApi };
|
package/dist/api.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ApiCall } from "./api-mocks-
|
|
1
|
+
import { t as ApiCall } from "./api-mocks-xXKzUFc9.mjs";
|
|
2
2
|
import { a as endpoint, i as api, n as ApiHandlerContext, r as EndpointDefinition, t as ApiDefinition } from "./define-NZvmQuIv.mjs";
|
|
3
3
|
import { withApi } from "./api-runtime.mjs";
|
|
4
4
|
export { type ApiCall, type ApiDefinition, type ApiHandlerContext, type EndpointDefinition, api, endpoint, withApi };
|
package/dist/api.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as endpoint, n as withApi, r as api } from "./runtime-
|
|
1
|
+
import { i as endpoint, n as withApi, r as api } from "./runtime-ChWJywJY.mjs";
|
|
2
2
|
export { api, endpoint, withApi };
|
package/dist/bin.cjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_client = require("./client-
|
|
3
|
-
const require_evals_api = require("./evals-api-
|
|
2
|
+
const require_client = require("./client-D4SBJEsG.cjs");
|
|
3
|
+
const require_evals_api = require("./evals-api-DuDr8UdV.cjs");
|
|
4
4
|
const require_errors = require("./errors-BX1wry8K.cjs");
|
|
5
5
|
const require_config = require("./config.cjs");
|
|
6
|
-
const require_compiler = require("./compiler-
|
|
6
|
+
const require_compiler = require("./compiler-DSN62KNe.cjs");
|
|
7
7
|
let effect = require("effect");
|
|
8
8
|
let _effect_platform = require("@effect/platform");
|
|
9
9
|
let _effect_cli = require("@effect/cli");
|
|
10
10
|
let _effect_platform_node = require("@effect/platform-node");
|
|
11
11
|
let yaml = require("yaml");
|
|
12
12
|
//#region package.json
|
|
13
|
-
var version$1 = "0.1.
|
|
13
|
+
var version$1 = "0.1.20";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region ../template/src/extract.ts
|
|
16
16
|
/** Reads escapes too, so text the renderer leaves literal is never reported as
|
|
@@ -21,6 +21,84 @@ function extractVariables(template) {
|
|
|
21
21
|
return [...new Set(names)];
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
|
+
//#region src/cli/render.ts
|
|
25
|
+
const json = (value) => effect.Console.log(JSON.stringify(value, null, 2));
|
|
26
|
+
const promptContent = (prompt) => effect.Effect.sync(() => {
|
|
27
|
+
process.stdout.write(prompt.content);
|
|
28
|
+
if (!prompt.content.endsWith("\n")) process.stdout.write("\n");
|
|
29
|
+
});
|
|
30
|
+
const row = (line) => effect.Effect.sync(() => {
|
|
31
|
+
process.stdout.write(`${line}\n`);
|
|
32
|
+
});
|
|
33
|
+
const note = (message) => effect.Effect.sync(() => {
|
|
34
|
+
process.stderr.write(`${message}\n`);
|
|
35
|
+
});
|
|
36
|
+
const attended = effect.Effect.sync(() => globalThis.process?.stdout?.isTTY === true);
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/cli/connector-command.ts
|
|
39
|
+
const asJson$2 = _effect_cli.Options.boolean("json").pipe(_effect_cli.Options.withDescription("Print the result as JSON"));
|
|
40
|
+
const integrationId = _effect_cli.Args.text({ name: "integration" }).pipe(_effect_cli.Args.withDescription("The integration to connect, such as openai"));
|
|
41
|
+
const connectorId = _effect_cli.Args.text({ name: "id" }).pipe(_effect_cli.Args.withDescription("The connector's id"));
|
|
42
|
+
const name = _effect_cli.Options.text("name").pipe(_effect_cli.Options.withDescription("What to call this connector"), _effect_cli.Options.optional);
|
|
43
|
+
const authMethod = _effect_cli.Options.text("auth").pipe(_effect_cli.Options.withDescription("Which auth method to use, when more than one exists"), _effect_cli.Options.optional);
|
|
44
|
+
const isDefault = _effect_cli.Options.boolean("default").pipe(_effect_cli.Options.withDescription("Make this the connector the runs use"));
|
|
45
|
+
const readSecret = (label) => effect.Effect.gen(function* () {
|
|
46
|
+
if (yield* attended) return effect.Redacted.value(yield* _effect_cli.Prompt.password({ message: label }));
|
|
47
|
+
return yield* effect.Effect.promise(async () => {
|
|
48
|
+
const chunks = [];
|
|
49
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
50
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const integrations = _effect_cli.Command.make("integrations", { asJson: asJson$2 }, ({ asJson: wantsJson }) => effect.Effect.gen(function* () {
|
|
54
|
+
const found = yield* (yield* require_client.AnpordApi).connectors.integrations({ payload: {} });
|
|
55
|
+
if (wantsJson) return yield* json(found);
|
|
56
|
+
return yield* effect.Effect.forEach(found, (integration) => row(`${integration.id}\t${integration.category}\t${integration.authMethods.map((method) => method.id).join(", ")}`));
|
|
57
|
+
})).pipe(_effect_cli.Command.withDescription("List the integrations that can be connected"));
|
|
58
|
+
const list$1 = _effect_cli.Command.make("list", { asJson: asJson$2 }, ({ asJson: wantsJson }) => effect.Effect.gen(function* () {
|
|
59
|
+
const found = yield* (yield* require_client.AnpordApi).connectors.list({ payload: {} });
|
|
60
|
+
if (wantsJson) return yield* json(found);
|
|
61
|
+
if (found.length === 0) return yield* note("No connectors yet. Add one with `anpord connectors add`.");
|
|
62
|
+
return yield* effect.Effect.forEach(found, (connector) => row(`${connector.id}\t${connector.integrationId}\t${connector.name}${connector.isDefault ? " (default)" : ""}`));
|
|
63
|
+
})).pipe(_effect_cli.Command.withDescription("List the connectors this organization has"));
|
|
64
|
+
const add = _effect_cli.Command.make("add", {
|
|
65
|
+
authMethod,
|
|
66
|
+
integrationId,
|
|
67
|
+
isDefault,
|
|
68
|
+
name
|
|
69
|
+
}, ({ authMethod: wantedMethod, integrationId: integration, isDefault: wantsDefault, name: wantedName }) => effect.Effect.gen(function* () {
|
|
70
|
+
const api = yield* require_client.AnpordApi;
|
|
71
|
+
const found = (yield* api.connectors.integrations({ payload: {} })).find((entry) => entry.id === integration);
|
|
72
|
+
if (found === void 0) return yield* note(`No integration called ${integration}. Run \`anpord connectors integrations\` to see them.`);
|
|
73
|
+
const method = effect.Option.match(wantedMethod, {
|
|
74
|
+
onNone: () => found.authMethods[0],
|
|
75
|
+
onSome: (wanted) => found.authMethods.find((entry) => entry.id === wanted)
|
|
76
|
+
});
|
|
77
|
+
if (method === void 0) return yield* note(`${integration} has no auth method called ${effect.Option.getOrElse(wantedMethod, () => "")}.`);
|
|
78
|
+
if (method.kind === "device") return yield* note(`${integration} signs in through a browser. Connect it at https://www.anpord.com/settings/connections.`);
|
|
79
|
+
const values = {};
|
|
80
|
+
for (const field of method.fields) values[field.name] = yield* readSecret(field.label);
|
|
81
|
+
const created = yield* api.connectors.add({ payload: {
|
|
82
|
+
authMethodId: method.id,
|
|
83
|
+
integrationId: integration,
|
|
84
|
+
isDefault: wantsDefault,
|
|
85
|
+
name: effect.Option.getOrElse(wantedName, () => found.label),
|
|
86
|
+
scope: "organization",
|
|
87
|
+
values
|
|
88
|
+
} });
|
|
89
|
+
return yield* note(`Connected ${created.integrationId} as ${created.id}`);
|
|
90
|
+
})).pipe(_effect_cli.Command.withDescription("Connect an integration. The secret is prompted for, or read from stdin"));
|
|
91
|
+
const remove = _effect_cli.Command.make("remove", { connectorId }, ({ connectorId: id }) => effect.Effect.gen(function* () {
|
|
92
|
+
yield* (yield* require_client.AnpordApi).connectors.remove({ payload: { id } });
|
|
93
|
+
return yield* note(`Removed ${id}`);
|
|
94
|
+
})).pipe(_effect_cli.Command.withDescription("Remove a connector"));
|
|
95
|
+
const connectors = _effect_cli.Command.make("connectors").pipe(_effect_cli.Command.withDescription("Connect the credentials an eval run needs"), _effect_cli.Command.withSubcommands([
|
|
96
|
+
add,
|
|
97
|
+
integrations,
|
|
98
|
+
list$1,
|
|
99
|
+
remove
|
|
100
|
+
]));
|
|
101
|
+
//#endregion
|
|
24
102
|
//#region src/cli/declarations.ts
|
|
25
103
|
const PREAMBLE = [
|
|
26
104
|
"// Generated by `anpord generate`. Do not edit.",
|
|
@@ -58,6 +136,32 @@ const evalFilesIn = (directory) => effect.Effect.gen(function* () {
|
|
|
58
136
|
return (yield* (yield* _effect_platform.FileSystem.FileSystem).readDirectory(directory, { recursive: true })).filter(wanted).sort();
|
|
59
137
|
}).pipe(effect.Effect.withSpan("Cli.evalFilesIn"));
|
|
60
138
|
//#endregion
|
|
139
|
+
//#region src/cli/eval-verdict.ts
|
|
140
|
+
const MARKS = {
|
|
141
|
+
error: "!",
|
|
142
|
+
failed: "✗",
|
|
143
|
+
passed: "✓",
|
|
144
|
+
queued: "·",
|
|
145
|
+
running: "·",
|
|
146
|
+
skipped: "–"
|
|
147
|
+
};
|
|
148
|
+
const WIDTH = 72;
|
|
149
|
+
const clip$1 = (text) => {
|
|
150
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
151
|
+
return flat.length > WIDTH ? `${flat.slice(0, 71)}…` : flat;
|
|
152
|
+
};
|
|
153
|
+
const decided = (validation) => validation.status === "passed" || validation.status === "failed";
|
|
154
|
+
const verdictLines = (trial) => {
|
|
155
|
+
const validations = trial.validations ?? [];
|
|
156
|
+
if (validations.length === 0) return [];
|
|
157
|
+
return validations.map((validation) => {
|
|
158
|
+
const mark = MARKS[validation.status];
|
|
159
|
+
const detail = validation.message === "" ? "" : ` ${clip$1(validation.message)}`;
|
|
160
|
+
return ` ${mark} ${validation.name}${detail}`;
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
const undecidedIn = (trial) => (trial.validations ?? []).filter((validation) => !decided(validation));
|
|
164
|
+
//#endregion
|
|
61
165
|
//#region src/cli/eval-gate.ts
|
|
62
166
|
const EvalGate = effect.Schema.Literal("strict", "never", "regressed", "unscored");
|
|
63
167
|
const regressions = (run) => run.cells.filter((cell) => cell.comparison?.verdict === "regressed");
|
|
@@ -83,7 +187,12 @@ const problemsWith = (run, failOn, expected) => {
|
|
|
83
187
|
return run.cells.flatMap((cell) => {
|
|
84
188
|
if (cell.status !== "finished" || cell.trials.length === 0) return [`${cell.caseName} has no complete trial results.`];
|
|
85
189
|
if (expected && cell.trials.length !== expected.trials) return [`${cell.caseName}: expected ${expected.trials} trials, received ${cell.trials.length}.`];
|
|
86
|
-
return cell.trials.flatMap((trial) =>
|
|
190
|
+
return cell.trials.flatMap((trial) => {
|
|
191
|
+
if (trial.status === "passed" && trial.passed) return [];
|
|
192
|
+
const undecided = undecidedIn(trial);
|
|
193
|
+
const why = undecided.length === 0 ? "" : ` (${undecided.length} validator${undecided.length === 1 ? "" : "s"} never decided)`;
|
|
194
|
+
return [`${cell.caseName}, trial ${trial.ordinal}: ${trial.status}.${why}`, ...verdictLines(trial)];
|
|
195
|
+
});
|
|
87
196
|
});
|
|
88
197
|
}
|
|
89
198
|
if (failOn === "never") return [];
|
|
@@ -102,20 +211,6 @@ var NoEvalFiles = class extends effect.Data.TaggedError("NoEvalFiles") {
|
|
|
102
211
|
}
|
|
103
212
|
};
|
|
104
213
|
//#endregion
|
|
105
|
-
//#region src/cli/render.ts
|
|
106
|
-
const json = (value) => effect.Console.log(JSON.stringify(value, null, 2));
|
|
107
|
-
const promptContent = (prompt) => effect.Effect.sync(() => {
|
|
108
|
-
process.stdout.write(prompt.content);
|
|
109
|
-
if (!prompt.content.endsWith("\n")) process.stdout.write("\n");
|
|
110
|
-
});
|
|
111
|
-
const row = (line) => effect.Effect.sync(() => {
|
|
112
|
-
process.stdout.write(`${line}\n`);
|
|
113
|
-
});
|
|
114
|
-
const note = (message) => effect.Effect.sync(() => {
|
|
115
|
-
process.stderr.write(`${message}\n`);
|
|
116
|
-
});
|
|
117
|
-
const attended = effect.Effect.sync(() => globalThis.process?.stdout?.isTTY === true);
|
|
118
|
-
//#endregion
|
|
119
214
|
//#region src/cli/eval-grid.ts
|
|
120
215
|
const DIM = "\x1B[2m";
|
|
121
216
|
const BOLD = "\x1B[1m";
|
|
@@ -150,6 +245,25 @@ const formatPassRate = (cell) => {
|
|
|
150
245
|
const shown = `${Math.round(rate * PERCENT)}%`;
|
|
151
246
|
return paint(rate === 1 ? GREEN : RED, shown);
|
|
152
247
|
};
|
|
248
|
+
const TAIL = 56;
|
|
249
|
+
const clip = (text) => {
|
|
250
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
251
|
+
return flat.length > TAIL ? `${flat.slice(0, 55)}…` : flat;
|
|
252
|
+
};
|
|
253
|
+
const latestOf = (cell) => {
|
|
254
|
+
const entry = cell.trials.find((trial) => trial.status === "running")?.trajectory.at(-1);
|
|
255
|
+
if (entry === void 0) return;
|
|
256
|
+
if (entry._tag === "command") return clip(entry.command);
|
|
257
|
+
if (entry._tag === "toolCall") return clip(entry.name);
|
|
258
|
+
return entry._tag === "fileChange" ? clip(entry.paths.join(" ")) : clip(entry.text);
|
|
259
|
+
};
|
|
260
|
+
const formatActivity = (cell) => {
|
|
261
|
+
const running = cell.trials.find((trial) => trial.status === "running");
|
|
262
|
+
if (running === void 0) return [];
|
|
263
|
+
const latest = latestOf(cell);
|
|
264
|
+
const counts = [`${running.commands} cmd`, ...running.filesChanged.length === 0 ? [] : [`${running.filesChanged.length} files`]].join(", ");
|
|
265
|
+
return [paint(DIM, ` ${counts}${latest === void 0 ? "" : ` ${latest}`}`)];
|
|
266
|
+
};
|
|
153
267
|
const formatVariant = (run, cell) => {
|
|
154
268
|
const task = run.tasks[cell.taskIndex];
|
|
155
269
|
return task === void 0 ? "?" : `${task.harness}/${task.model}`;
|
|
@@ -160,7 +274,10 @@ const formatGrid = (run, trials, elapsedMs) => {
|
|
|
160
274
|
const lines = [];
|
|
161
275
|
for (const caseName of run.cases) {
|
|
162
276
|
lines.push(` ${BOLD}${caseName}${RESET}`);
|
|
163
|
-
for (const cell of run.cells.filter((one) => one.caseName === caseName))
|
|
277
|
+
for (const cell of run.cells.filter((one) => one.caseName === caseName)) {
|
|
278
|
+
lines.push(` ${formatStatus(cell)} ${formatVariant(run, cell).padEnd(width)} ${formatTrialProgress(cell, trials)} ${formatPassRate(cell)}`);
|
|
279
|
+
lines.push(...formatActivity(cell));
|
|
280
|
+
}
|
|
164
281
|
lines.push("");
|
|
165
282
|
}
|
|
166
283
|
lines.push(paint(DIM, ` ${formatElapsed(elapsedMs)} elapsed`));
|
|
@@ -891,6 +1008,7 @@ const gen = _effect_cli.Command.make("gen", { out }, writeDeclarations).pipe(_ef
|
|
|
891
1008
|
const withClient = (command) => _effect_cli.Command.provide(command, require_config.ClientLayer);
|
|
892
1009
|
const commands = [
|
|
893
1010
|
runEval,
|
|
1011
|
+
withClient(connectors),
|
|
894
1012
|
withClient(gen),
|
|
895
1013
|
withClient(generate),
|
|
896
1014
|
withClient(get),
|
package/dist/bin.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as ChannelName, o as PromptId, s as VersionNumber, t as AnpordApi } from "./client-
|
|
3
|
-
import {
|
|
2
|
+
import { a as ChannelName, o as PromptId, s as VersionNumber, t as AnpordApi } from "./client-DCSRP55Q.mjs";
|
|
3
|
+
import { d as EvalTrigger, r as EvalRun } from "./evals-api-B0lnr_R8.mjs";
|
|
4
4
|
import { i as tokenMatcher, r as asAnpordError } from "./errors-B0YknR5V.mjs";
|
|
5
5
|
import { ClientLayer, webUrlConfig } from "./config.mjs";
|
|
6
|
-
import { r as compileEvalEffect } from "./compiler-
|
|
6
|
+
import { r as compileEvalEffect } from "./compiler-BKchnKps.mjs";
|
|
7
7
|
import { Cause, Clock, Config, Console, Data, Duration, Effect, Layer, Option, ParseResult, Redacted, Ref, Schema } from "effect";
|
|
8
8
|
import { FetchHttpClient, FileSystem, HttpClient, HttpClientError, HttpClientRequest } from "@effect/platform";
|
|
9
|
-
import { Args, Command, Options } from "@effect/cli";
|
|
9
|
+
import { Args, Command, Options, Prompt } from "@effect/cli";
|
|
10
10
|
import { NodeContext, NodeRuntime } from "@effect/platform-node";
|
|
11
11
|
import { parseDocument } from "yaml";
|
|
12
12
|
//#region package.json
|
|
13
|
-
var version$1 = "0.1.
|
|
13
|
+
var version$1 = "0.1.20";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region ../template/src/extract.ts
|
|
16
16
|
/** Reads escapes too, so text the renderer leaves literal is never reported as
|
|
@@ -21,6 +21,84 @@ function extractVariables(template) {
|
|
|
21
21
|
return [...new Set(names)];
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
|
+
//#region src/cli/render.ts
|
|
25
|
+
const json = (value) => Console.log(JSON.stringify(value, null, 2));
|
|
26
|
+
const promptContent = (prompt) => Effect.sync(() => {
|
|
27
|
+
process.stdout.write(prompt.content);
|
|
28
|
+
if (!prompt.content.endsWith("\n")) process.stdout.write("\n");
|
|
29
|
+
});
|
|
30
|
+
const row = (line) => Effect.sync(() => {
|
|
31
|
+
process.stdout.write(`${line}\n`);
|
|
32
|
+
});
|
|
33
|
+
const note = (message) => Effect.sync(() => {
|
|
34
|
+
process.stderr.write(`${message}\n`);
|
|
35
|
+
});
|
|
36
|
+
const attended = Effect.sync(() => globalThis.process?.stdout?.isTTY === true);
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/cli/connector-command.ts
|
|
39
|
+
const asJson$2 = Options.boolean("json").pipe(Options.withDescription("Print the result as JSON"));
|
|
40
|
+
const integrationId = Args.text({ name: "integration" }).pipe(Args.withDescription("The integration to connect, such as openai"));
|
|
41
|
+
const connectorId = Args.text({ name: "id" }).pipe(Args.withDescription("The connector's id"));
|
|
42
|
+
const name = Options.text("name").pipe(Options.withDescription("What to call this connector"), Options.optional);
|
|
43
|
+
const authMethod = Options.text("auth").pipe(Options.withDescription("Which auth method to use, when more than one exists"), Options.optional);
|
|
44
|
+
const isDefault = Options.boolean("default").pipe(Options.withDescription("Make this the connector the runs use"));
|
|
45
|
+
const readSecret = (label) => Effect.gen(function* () {
|
|
46
|
+
if (yield* attended) return Redacted.value(yield* Prompt.password({ message: label }));
|
|
47
|
+
return yield* Effect.promise(async () => {
|
|
48
|
+
const chunks = [];
|
|
49
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
50
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const integrations = Command.make("integrations", { asJson: asJson$2 }, ({ asJson: wantsJson }) => Effect.gen(function* () {
|
|
54
|
+
const found = yield* (yield* AnpordApi).connectors.integrations({ payload: {} });
|
|
55
|
+
if (wantsJson) return yield* json(found);
|
|
56
|
+
return yield* Effect.forEach(found, (integration) => row(`${integration.id}\t${integration.category}\t${integration.authMethods.map((method) => method.id).join(", ")}`));
|
|
57
|
+
})).pipe(Command.withDescription("List the integrations that can be connected"));
|
|
58
|
+
const list$1 = Command.make("list", { asJson: asJson$2 }, ({ asJson: wantsJson }) => Effect.gen(function* () {
|
|
59
|
+
const found = yield* (yield* AnpordApi).connectors.list({ payload: {} });
|
|
60
|
+
if (wantsJson) return yield* json(found);
|
|
61
|
+
if (found.length === 0) return yield* note("No connectors yet. Add one with `anpord connectors add`.");
|
|
62
|
+
return yield* Effect.forEach(found, (connector) => row(`${connector.id}\t${connector.integrationId}\t${connector.name}${connector.isDefault ? " (default)" : ""}`));
|
|
63
|
+
})).pipe(Command.withDescription("List the connectors this organization has"));
|
|
64
|
+
const add = Command.make("add", {
|
|
65
|
+
authMethod,
|
|
66
|
+
integrationId,
|
|
67
|
+
isDefault,
|
|
68
|
+
name
|
|
69
|
+
}, ({ authMethod: wantedMethod, integrationId: integration, isDefault: wantsDefault, name: wantedName }) => Effect.gen(function* () {
|
|
70
|
+
const api = yield* AnpordApi;
|
|
71
|
+
const found = (yield* api.connectors.integrations({ payload: {} })).find((entry) => entry.id === integration);
|
|
72
|
+
if (found === void 0) return yield* note(`No integration called ${integration}. Run \`anpord connectors integrations\` to see them.`);
|
|
73
|
+
const method = Option.match(wantedMethod, {
|
|
74
|
+
onNone: () => found.authMethods[0],
|
|
75
|
+
onSome: (wanted) => found.authMethods.find((entry) => entry.id === wanted)
|
|
76
|
+
});
|
|
77
|
+
if (method === void 0) return yield* note(`${integration} has no auth method called ${Option.getOrElse(wantedMethod, () => "")}.`);
|
|
78
|
+
if (method.kind === "device") return yield* note(`${integration} signs in through a browser. Connect it at https://www.anpord.com/settings/connections.`);
|
|
79
|
+
const values = {};
|
|
80
|
+
for (const field of method.fields) values[field.name] = yield* readSecret(field.label);
|
|
81
|
+
const created = yield* api.connectors.add({ payload: {
|
|
82
|
+
authMethodId: method.id,
|
|
83
|
+
integrationId: integration,
|
|
84
|
+
isDefault: wantsDefault,
|
|
85
|
+
name: Option.getOrElse(wantedName, () => found.label),
|
|
86
|
+
scope: "organization",
|
|
87
|
+
values
|
|
88
|
+
} });
|
|
89
|
+
return yield* note(`Connected ${created.integrationId} as ${created.id}`);
|
|
90
|
+
})).pipe(Command.withDescription("Connect an integration. The secret is prompted for, or read from stdin"));
|
|
91
|
+
const remove = Command.make("remove", { connectorId }, ({ connectorId: id }) => Effect.gen(function* () {
|
|
92
|
+
yield* (yield* AnpordApi).connectors.remove({ payload: { id } });
|
|
93
|
+
return yield* note(`Removed ${id}`);
|
|
94
|
+
})).pipe(Command.withDescription("Remove a connector"));
|
|
95
|
+
const connectors = Command.make("connectors").pipe(Command.withDescription("Connect the credentials an eval run needs"), Command.withSubcommands([
|
|
96
|
+
add,
|
|
97
|
+
integrations,
|
|
98
|
+
list$1,
|
|
99
|
+
remove
|
|
100
|
+
]));
|
|
101
|
+
//#endregion
|
|
24
102
|
//#region src/cli/declarations.ts
|
|
25
103
|
const PREAMBLE = [
|
|
26
104
|
"// Generated by `anpord generate`. Do not edit.",
|
|
@@ -58,6 +136,32 @@ const evalFilesIn = (directory) => Effect.gen(function* () {
|
|
|
58
136
|
return (yield* (yield* FileSystem.FileSystem).readDirectory(directory, { recursive: true })).filter(wanted).sort();
|
|
59
137
|
}).pipe(Effect.withSpan("Cli.evalFilesIn"));
|
|
60
138
|
//#endregion
|
|
139
|
+
//#region src/cli/eval-verdict.ts
|
|
140
|
+
const MARKS = {
|
|
141
|
+
error: "!",
|
|
142
|
+
failed: "✗",
|
|
143
|
+
passed: "✓",
|
|
144
|
+
queued: "·",
|
|
145
|
+
running: "·",
|
|
146
|
+
skipped: "–"
|
|
147
|
+
};
|
|
148
|
+
const WIDTH = 72;
|
|
149
|
+
const clip$1 = (text) => {
|
|
150
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
151
|
+
return flat.length > WIDTH ? `${flat.slice(0, 71)}…` : flat;
|
|
152
|
+
};
|
|
153
|
+
const decided = (validation) => validation.status === "passed" || validation.status === "failed";
|
|
154
|
+
const verdictLines = (trial) => {
|
|
155
|
+
const validations = trial.validations ?? [];
|
|
156
|
+
if (validations.length === 0) return [];
|
|
157
|
+
return validations.map((validation) => {
|
|
158
|
+
const mark = MARKS[validation.status];
|
|
159
|
+
const detail = validation.message === "" ? "" : ` ${clip$1(validation.message)}`;
|
|
160
|
+
return ` ${mark} ${validation.name}${detail}`;
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
const undecidedIn = (trial) => (trial.validations ?? []).filter((validation) => !decided(validation));
|
|
164
|
+
//#endregion
|
|
61
165
|
//#region src/cli/eval-gate.ts
|
|
62
166
|
const EvalGate = Schema.Literal("strict", "never", "regressed", "unscored");
|
|
63
167
|
const regressions = (run) => run.cells.filter((cell) => cell.comparison?.verdict === "regressed");
|
|
@@ -83,7 +187,12 @@ const problemsWith = (run, failOn, expected) => {
|
|
|
83
187
|
return run.cells.flatMap((cell) => {
|
|
84
188
|
if (cell.status !== "finished" || cell.trials.length === 0) return [`${cell.caseName} has no complete trial results.`];
|
|
85
189
|
if (expected && cell.trials.length !== expected.trials) return [`${cell.caseName}: expected ${expected.trials} trials, received ${cell.trials.length}.`];
|
|
86
|
-
return cell.trials.flatMap((trial) =>
|
|
190
|
+
return cell.trials.flatMap((trial) => {
|
|
191
|
+
if (trial.status === "passed" && trial.passed) return [];
|
|
192
|
+
const undecided = undecidedIn(trial);
|
|
193
|
+
const why = undecided.length === 0 ? "" : ` (${undecided.length} validator${undecided.length === 1 ? "" : "s"} never decided)`;
|
|
194
|
+
return [`${cell.caseName}, trial ${trial.ordinal}: ${trial.status}.${why}`, ...verdictLines(trial)];
|
|
195
|
+
});
|
|
87
196
|
});
|
|
88
197
|
}
|
|
89
198
|
if (failOn === "never") return [];
|
|
@@ -102,20 +211,6 @@ var NoEvalFiles = class extends Data.TaggedError("NoEvalFiles") {
|
|
|
102
211
|
}
|
|
103
212
|
};
|
|
104
213
|
//#endregion
|
|
105
|
-
//#region src/cli/render.ts
|
|
106
|
-
const json = (value) => Console.log(JSON.stringify(value, null, 2));
|
|
107
|
-
const promptContent = (prompt) => Effect.sync(() => {
|
|
108
|
-
process.stdout.write(prompt.content);
|
|
109
|
-
if (!prompt.content.endsWith("\n")) process.stdout.write("\n");
|
|
110
|
-
});
|
|
111
|
-
const row = (line) => Effect.sync(() => {
|
|
112
|
-
process.stdout.write(`${line}\n`);
|
|
113
|
-
});
|
|
114
|
-
const note = (message) => Effect.sync(() => {
|
|
115
|
-
process.stderr.write(`${message}\n`);
|
|
116
|
-
});
|
|
117
|
-
const attended = Effect.sync(() => globalThis.process?.stdout?.isTTY === true);
|
|
118
|
-
//#endregion
|
|
119
214
|
//#region src/cli/eval-grid.ts
|
|
120
215
|
const DIM = "\x1B[2m";
|
|
121
216
|
const BOLD = "\x1B[1m";
|
|
@@ -150,6 +245,25 @@ const formatPassRate = (cell) => {
|
|
|
150
245
|
const shown = `${Math.round(rate * PERCENT)}%`;
|
|
151
246
|
return paint(rate === 1 ? GREEN : RED, shown);
|
|
152
247
|
};
|
|
248
|
+
const TAIL = 56;
|
|
249
|
+
const clip = (text) => {
|
|
250
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
251
|
+
return flat.length > TAIL ? `${flat.slice(0, 55)}…` : flat;
|
|
252
|
+
};
|
|
253
|
+
const latestOf = (cell) => {
|
|
254
|
+
const entry = cell.trials.find((trial) => trial.status === "running")?.trajectory.at(-1);
|
|
255
|
+
if (entry === void 0) return;
|
|
256
|
+
if (entry._tag === "command") return clip(entry.command);
|
|
257
|
+
if (entry._tag === "toolCall") return clip(entry.name);
|
|
258
|
+
return entry._tag === "fileChange" ? clip(entry.paths.join(" ")) : clip(entry.text);
|
|
259
|
+
};
|
|
260
|
+
const formatActivity = (cell) => {
|
|
261
|
+
const running = cell.trials.find((trial) => trial.status === "running");
|
|
262
|
+
if (running === void 0) return [];
|
|
263
|
+
const latest = latestOf(cell);
|
|
264
|
+
const counts = [`${running.commands} cmd`, ...running.filesChanged.length === 0 ? [] : [`${running.filesChanged.length} files`]].join(", ");
|
|
265
|
+
return [paint(DIM, ` ${counts}${latest === void 0 ? "" : ` ${latest}`}`)];
|
|
266
|
+
};
|
|
153
267
|
const formatVariant = (run, cell) => {
|
|
154
268
|
const task = run.tasks[cell.taskIndex];
|
|
155
269
|
return task === void 0 ? "?" : `${task.harness}/${task.model}`;
|
|
@@ -160,7 +274,10 @@ const formatGrid = (run, trials, elapsedMs) => {
|
|
|
160
274
|
const lines = [];
|
|
161
275
|
for (const caseName of run.cases) {
|
|
162
276
|
lines.push(` ${BOLD}${caseName}${RESET}`);
|
|
163
|
-
for (const cell of run.cells.filter((one) => one.caseName === caseName))
|
|
277
|
+
for (const cell of run.cells.filter((one) => one.caseName === caseName)) {
|
|
278
|
+
lines.push(` ${formatStatus(cell)} ${formatVariant(run, cell).padEnd(width)} ${formatTrialProgress(cell, trials)} ${formatPassRate(cell)}`);
|
|
279
|
+
lines.push(...formatActivity(cell));
|
|
280
|
+
}
|
|
164
281
|
lines.push("");
|
|
165
282
|
}
|
|
166
283
|
lines.push(paint(DIM, ` ${formatElapsed(elapsedMs)} elapsed`));
|
|
@@ -891,6 +1008,7 @@ const gen = Command.make("gen", { out }, writeDeclarations).pipe(Command.withDes
|
|
|
891
1008
|
const withClient = (command) => Command.provide(command, ClientLayer);
|
|
892
1009
|
const commands = [
|
|
893
1010
|
runEval,
|
|
1011
|
+
withClient(connectors),
|
|
894
1012
|
withClient(gen),
|
|
895
1013
|
withClient(generate),
|
|
896
1014
|
withClient(get),
|