@apo-ai/sdk 0.2.0 → 0.2.2
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.
|
@@ -61,13 +61,15 @@ type AgentTurnResult = {
|
|
|
61
61
|
};
|
|
62
62
|
/**
|
|
63
63
|
* The adapter-reported identity of the agent under test for one Task Run
|
|
64
|
-
|
|
64
|
+
* The adapter resolves its configuration (env vars, aliases,
|
|
65
65
|
* defaults), constructs the agent from that same resolved object, and reports
|
|
66
66
|
* the resolved values here.
|
|
67
67
|
*
|
|
68
68
|
* - `model` is the exact identifier the adapter passed to its runtime.
|
|
69
|
-
* - `effort` is the exact short value that
|
|
70
|
-
* or `"default"`).
|
|
69
|
+
* - `effort` is the exact short value that the selected model/provider applied
|
|
70
|
+
* (`low`/`medium`/... or `"default"`). Omit it when effort is unsupported,
|
|
71
|
+
* ignored, or cannot be verified. A configured default or accepted request
|
|
72
|
+
* parameter is not an applied effort by itself.
|
|
71
73
|
*
|
|
72
74
|
* The whole configuration is absent (`undefined`) when the adapter does not
|
|
73
75
|
* support reporting it. Values are descriptive — they never affect task
|
|
@@ -979,13 +979,13 @@ async function loadTaskDefinition(taskFilePath) {
|
|
|
979
979
|
const task2 = registeredTask ?? loaded.default;
|
|
980
980
|
if (!task2 || typeof task2 !== "object") {
|
|
981
981
|
throw new Error(
|
|
982
|
-
"No task definition found
|
|
982
|
+
"No task definition found. The .eval.ts file must call task(name, { adapter, deliverables, ... }) at module top level. If it does, the CLI and the .eval.ts may be loading different @apo-ai/sdk instances (check for a stale packages/sdk/dist build or a version mismatch between the CLI and node_modules)."
|
|
983
983
|
);
|
|
984
984
|
}
|
|
985
985
|
const adapter = getTaskAdapterDefinition(task2);
|
|
986
986
|
if (!adapter) {
|
|
987
987
|
throw new Error(
|
|
988
|
-
registeredTask ? "task() config must include an adapter" : "Task module must
|
|
988
|
+
registeredTask ? "task() config must include an adapter" : "Task module must call task(name, { adapter, ... }) \u2014 the config is missing an adapter."
|
|
989
989
|
);
|
|
990
990
|
}
|
|
991
991
|
return {
|
|
@@ -1109,15 +1109,15 @@ function fileArtifact(path, options = {}) {
|
|
|
1109
1109
|
try {
|
|
1110
1110
|
const lstat = lstatSync(path);
|
|
1111
1111
|
if (lstat.isSymbolicLink()) {
|
|
1112
|
-
throw new Error(
|
|
1112
|
+
throw new Error("fileArtifact: path is a symbolic link, not a regular file");
|
|
1113
1113
|
}
|
|
1114
1114
|
stat = statSync2(path);
|
|
1115
1115
|
} catch (error) {
|
|
1116
|
-
if (
|
|
1117
|
-
throw new Error(
|
|
1116
|
+
if (error instanceof Error && error.message.startsWith("fileArtifact:")) throw error;
|
|
1117
|
+
throw new Error("fileArtifact: path is not a regular file or is inaccessible");
|
|
1118
1118
|
}
|
|
1119
1119
|
if (!stat.isFile()) {
|
|
1120
|
-
throw new Error(
|
|
1120
|
+
throw new Error("fileArtifact: path is not a regular file");
|
|
1121
1121
|
}
|
|
1122
1122
|
const displayFilename = options.displayFilename ?? basename3(path);
|
|
1123
1123
|
if (!displayFilename) {
|
|
@@ -1133,21 +1133,19 @@ function fileArtifact(path, options = {}) {
|
|
|
1133
1133
|
function isFileArtifact(value) {
|
|
1134
1134
|
return typeof value === "object" && value !== null && value.kind === "apo.file-artifact" && typeof value.path === "string";
|
|
1135
1135
|
}
|
|
1136
|
-
function existsLike(error) {
|
|
1137
|
-
if (!(error instanceof Error)) return false;
|
|
1138
|
-
const code = error.code;
|
|
1139
|
-
return code === "ENOENT";
|
|
1140
|
-
}
|
|
1141
1136
|
|
|
1142
1137
|
// src/agent-task/deliverables/upload.ts
|
|
1143
1138
|
import { createHash } from "crypto";
|
|
1144
1139
|
import { createReadStream } from "fs";
|
|
1145
|
-
import { basename as basename4 } from "path";
|
|
1146
1140
|
import { Readable } from "stream";
|
|
1147
1141
|
var DEFAULT_FETCH = typeof fetch === "function" ? fetch : void 0;
|
|
1148
1142
|
async function persistFileArtifacts(deliverables, config) {
|
|
1149
1143
|
const jsonDeliverables = {};
|
|
1150
1144
|
const artifactUploads = [];
|
|
1145
|
+
const artifactNames = Object.entries(deliverables).filter(([, v]) => isFileArtifact(v)).map(([name]) => name);
|
|
1146
|
+
if (artifactNames.length > 0) {
|
|
1147
|
+
validateUploadConfig(config, artifactNames[0]);
|
|
1148
|
+
}
|
|
1151
1149
|
for (const [name, value] of Object.entries(deliverables)) {
|
|
1152
1150
|
if (isFileArtifact(value)) {
|
|
1153
1151
|
const summary = await uploadOne(name, value, config);
|
|
@@ -1158,13 +1156,37 @@ async function persistFileArtifacts(deliverables, config) {
|
|
|
1158
1156
|
}
|
|
1159
1157
|
return { jsonDeliverables, artifactUploads };
|
|
1160
1158
|
}
|
|
1159
|
+
function validateUploadConfig(config, firstName) {
|
|
1160
|
+
if (!config.taskRunId) {
|
|
1161
|
+
throw new Error(
|
|
1162
|
+
`Artifact '${firstName}' cannot be uploaded: missing task run ID`
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
if (!config.authToken) {
|
|
1166
|
+
throw new Error(
|
|
1167
|
+
`Artifact '${firstName}' cannot be uploaded: missing auth token`
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
if (!config.baseUrl) {
|
|
1171
|
+
throw new Error(
|
|
1172
|
+
`Artifact '${firstName}' cannot be uploaded: missing backend base URL`
|
|
1173
|
+
);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1161
1176
|
async function uploadOne(name, artifact, config) {
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1177
|
+
try {
|
|
1178
|
+
const { size, sha256 } = await hashFile(artifact.path);
|
|
1179
|
+
const intent = await createIntent(name, artifact, size, sha256, config);
|
|
1180
|
+
const body = Readable.toWeb(createReadStream(artifact.path));
|
|
1181
|
+
const summary = await putBytes(intent.upload_url, body, size, config);
|
|
1182
|
+
return summary;
|
|
1183
|
+
} catch (err) {
|
|
1184
|
+
if (err instanceof Error && err.code) {
|
|
1185
|
+
const code = err.code ?? "UNKNOWN";
|
|
1186
|
+
throw new Error(`Artifact '${name}' file read failed: ${code}`);
|
|
1187
|
+
}
|
|
1188
|
+
throw err;
|
|
1189
|
+
}
|
|
1168
1190
|
}
|
|
1169
1191
|
async function hashFile(path) {
|
|
1170
1192
|
return new Promise((resolve4, reject) => {
|