@axiom-lattice/core 3.1.0 → 3.1.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.
- package/dist/index.d.mts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +75 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +74 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -17030,6 +17030,51 @@ var FilesystemBackend = class {
|
|
|
17030
17030
|
throw new Error(`Path: ${resolvedPath} outside root directory: ${this.cwd}`);
|
|
17031
17031
|
}
|
|
17032
17032
|
}
|
|
17033
|
+
async assertVirtualOpenedFileContained(resolvedPath, openedStat) {
|
|
17034
|
+
if (!this.virtualMode) {
|
|
17035
|
+
return;
|
|
17036
|
+
}
|
|
17037
|
+
const [rootPath, realFilePath] = await Promise.all([
|
|
17038
|
+
fs2.realpath(this.cwd),
|
|
17039
|
+
fs2.realpath(resolvedPath)
|
|
17040
|
+
]);
|
|
17041
|
+
const relative4 = path4.relative(rootPath, realFilePath);
|
|
17042
|
+
if (relative4 === ".." || relative4.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative4)) {
|
|
17043
|
+
throw new Error(`Path: ${resolvedPath} outside root directory: ${this.cwd}`);
|
|
17044
|
+
}
|
|
17045
|
+
const realPathStat = await fs2.stat(realFilePath);
|
|
17046
|
+
if (realPathStat.dev !== openedStat.dev || realPathStat.ino !== openedStat.ino) {
|
|
17047
|
+
throw new Error(`File changed during secure read: ${resolvedPath}`);
|
|
17048
|
+
}
|
|
17049
|
+
}
|
|
17050
|
+
async readFileBuffer(filePath) {
|
|
17051
|
+
const resolvedPath = this.resolvePath(filePath);
|
|
17052
|
+
await this.assertVirtualParentContained(resolvedPath);
|
|
17053
|
+
if (!SUPPORTS_NOFOLLOW) {
|
|
17054
|
+
const initialStat = await fs2.lstat(resolvedPath);
|
|
17055
|
+
if (initialStat.isSymbolicLink()) {
|
|
17056
|
+
throw new Error(`Symlinks are not allowed: ${filePath}`);
|
|
17057
|
+
}
|
|
17058
|
+
}
|
|
17059
|
+
const flags = SUPPORTS_NOFOLLOW ? fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW : fsSync.constants.O_RDONLY;
|
|
17060
|
+
const fd = await fs2.open(resolvedPath, flags);
|
|
17061
|
+
try {
|
|
17062
|
+
const stat4 = await fd.stat();
|
|
17063
|
+
if (!stat4.isFile()) {
|
|
17064
|
+
throw new Error(`File '${filePath}' not found`);
|
|
17065
|
+
}
|
|
17066
|
+
await this.assertVirtualOpenedFileContained(resolvedPath, stat4);
|
|
17067
|
+
if (!SUPPORTS_NOFOLLOW) {
|
|
17068
|
+
const finalStat = await fs2.lstat(resolvedPath);
|
|
17069
|
+
if (finalStat.isSymbolicLink() || finalStat.dev !== stat4.dev || finalStat.ino !== stat4.ino) {
|
|
17070
|
+
throw new Error(`File changed during secure read: ${resolvedPath}`);
|
|
17071
|
+
}
|
|
17072
|
+
}
|
|
17073
|
+
return { content: await fd.readFile(), stat: stat4 };
|
|
17074
|
+
} finally {
|
|
17075
|
+
await fd.close();
|
|
17076
|
+
}
|
|
17077
|
+
}
|
|
17033
17078
|
validateDeleteTarget(filePath, stat4) {
|
|
17034
17079
|
if (stat4.isSymbolicLink()) {
|
|
17035
17080
|
return `Error: Cannot delete '${filePath}': symlinks are not allowed`;
|
|
@@ -17129,32 +17174,8 @@ var FilesystemBackend = class {
|
|
|
17129
17174
|
*/
|
|
17130
17175
|
async read(filePath, offset = 0, limit = 2e3) {
|
|
17131
17176
|
try {
|
|
17132
|
-
const
|
|
17133
|
-
|
|
17134
|
-
if (SUPPORTS_NOFOLLOW) {
|
|
17135
|
-
const stat4 = await fs2.stat(resolvedPath);
|
|
17136
|
-
if (!stat4.isFile()) {
|
|
17137
|
-
return `Error: File '${filePath}' not found`;
|
|
17138
|
-
}
|
|
17139
|
-
const fd = await fs2.open(
|
|
17140
|
-
resolvedPath,
|
|
17141
|
-
fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW
|
|
17142
|
-
);
|
|
17143
|
-
try {
|
|
17144
|
-
content = await fd.readFile({ encoding: "utf-8" });
|
|
17145
|
-
} finally {
|
|
17146
|
-
await fd.close();
|
|
17147
|
-
}
|
|
17148
|
-
} else {
|
|
17149
|
-
const stat4 = await fs2.lstat(resolvedPath);
|
|
17150
|
-
if (stat4.isSymbolicLink()) {
|
|
17151
|
-
return `Error: Symlinks are not allowed: ${filePath}`;
|
|
17152
|
-
}
|
|
17153
|
-
if (!stat4.isFile()) {
|
|
17154
|
-
return `Error: File '${filePath}' not found`;
|
|
17155
|
-
}
|
|
17156
|
-
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
17157
|
-
}
|
|
17177
|
+
const { content: buffer2 } = await this.readFileBuffer(filePath);
|
|
17178
|
+
const content = buffer2.toString("utf-8");
|
|
17158
17179
|
const emptyMsg = checkEmptyContent(content);
|
|
17159
17180
|
if (emptyMsg) {
|
|
17160
17181
|
return emptyMsg;
|
|
@@ -17178,35 +17199,19 @@ var FilesystemBackend = class {
|
|
|
17178
17199
|
* @returns Raw file content as FileData
|
|
17179
17200
|
*/
|
|
17180
17201
|
async readRaw(filePath) {
|
|
17181
|
-
const
|
|
17182
|
-
|
|
17183
|
-
let stat4;
|
|
17184
|
-
if (SUPPORTS_NOFOLLOW) {
|
|
17185
|
-
stat4 = await fs2.stat(resolvedPath);
|
|
17186
|
-
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
17187
|
-
const fd = await fs2.open(
|
|
17188
|
-
resolvedPath,
|
|
17189
|
-
fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW
|
|
17190
|
-
);
|
|
17191
|
-
try {
|
|
17192
|
-
content = await fd.readFile({ encoding: "utf-8" });
|
|
17193
|
-
} finally {
|
|
17194
|
-
await fd.close();
|
|
17195
|
-
}
|
|
17196
|
-
} else {
|
|
17197
|
-
stat4 = await fs2.lstat(resolvedPath);
|
|
17198
|
-
if (stat4.isSymbolicLink()) {
|
|
17199
|
-
throw new Error(`Symlinks are not allowed: ${filePath}`);
|
|
17200
|
-
}
|
|
17201
|
-
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
17202
|
-
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
17203
|
-
}
|
|
17202
|
+
const { content: buffer2, stat: stat4 } = await this.readFileBuffer(filePath);
|
|
17203
|
+
const content = buffer2.toString("utf-8");
|
|
17204
17204
|
return {
|
|
17205
17205
|
content: content.split("\n"),
|
|
17206
17206
|
created_at: stat4.ctime.toISOString(),
|
|
17207
17207
|
modified_at: stat4.mtime.toISOString()
|
|
17208
17208
|
};
|
|
17209
17209
|
}
|
|
17210
|
+
/** Read file content as raw bytes without following symbolic links. */
|
|
17211
|
+
async readBinary(filePath) {
|
|
17212
|
+
const { content } = await this.readFileBuffer(filePath);
|
|
17213
|
+
return content;
|
|
17214
|
+
}
|
|
17210
17215
|
/**
|
|
17211
17216
|
* Create a new file with content.
|
|
17212
17217
|
* Returns WriteResult. External storage sets filesUpdate=null.
|
|
@@ -21798,7 +21803,7 @@ registerToolLattice(
|
|
|
21798
21803
|
"update_agent",
|
|
21799
21804
|
{
|
|
21800
21805
|
name: "update_agent",
|
|
21801
|
-
description: "Update an existing agent's configuration. Provide the agent ID and the fields to change. Returns the updated agent's ID and name. NOTE: For user approval/confirmation scenarios, add middleware with type: 'ask_user_to_clarify'.",
|
|
21806
|
+
description: "Update an existing agent's configuration. Provide the agent ID and the fields to change. Returns the updated agent's ID and name. NOTE: For user approval/confirmation scenarios, add middleware with type: 'ask_user_to_clarify'. IMPORTANT: do NOT set 'modelKey' unless the user explicitly specified a model \u2014 leaving it unset makes the runtime use the 'default' model.",
|
|
21802
21807
|
schema: updateAgentSchema
|
|
21803
21808
|
},
|
|
21804
21809
|
async (input, exeConfig) => {
|
|
@@ -22036,6 +22041,8 @@ OVERRIDES the defaults above:
|
|
|
22036
22041
|
(parentId); NEVER create a new parent task for the round.
|
|
22037
22042
|
- The round is pre-approved \u2014 skip the DESIGN\u2192CONFIRM gates: show the
|
|
22038
22043
|
design in your reply, then build directly.
|
|
22044
|
+
- Do NOT set modelKey in update_agent unless the user explicitly named a
|
|
22045
|
+
model \u2014 leaving it unset makes the runtime use the 'default' model.
|
|
22039
22046
|
- Every update_agent call must be mirrored by a manage_task work item
|
|
22040
22047
|
whose summary names the changed keys (e.g. "update_agent: prompt,
|
|
22041
22048
|
modelKey") \u2014 the round feed highlights these so the user can see what
|
|
@@ -26625,14 +26632,22 @@ var DEFAULT_CALIBRATION_PROBES = [
|
|
|
26625
26632
|
expectedPass: false
|
|
26626
26633
|
}
|
|
26627
26634
|
];
|
|
26635
|
+
function resolveJudgeModelKey(explicitKey, manager) {
|
|
26636
|
+
if (explicitKey) return explicitKey;
|
|
26637
|
+
const models = manager.getAllLattices();
|
|
26638
|
+
const defaultModel = models.find((m) => m.key === "default");
|
|
26639
|
+
if (defaultModel) return defaultModel.key;
|
|
26640
|
+
const first = models[0];
|
|
26641
|
+
if (!first) {
|
|
26642
|
+
throw new Error("No model registered \u2014 register a model or provide a judgeModelKey");
|
|
26643
|
+
}
|
|
26644
|
+
return first.key;
|
|
26645
|
+
}
|
|
26628
26646
|
var LatticeEvalProject = class {
|
|
26629
26647
|
constructor(project, onCaseComplete) {
|
|
26630
26648
|
this.suites = /* @__PURE__ */ new Map();
|
|
26631
26649
|
this.project = project;
|
|
26632
|
-
const judgeModelKey = this.project.judge_agent_config.modelKey;
|
|
26633
|
-
if (!judgeModelKey) {
|
|
26634
|
-
throw new Error("judge_agent_config.modelKey is required \u2014 only pre-registered models are allowed");
|
|
26635
|
-
}
|
|
26650
|
+
const judgeModelKey = resolveJudgeModelKey(this.project.judge_agent_config.modelKey, modelLatticeManager);
|
|
26636
26651
|
if (!modelLatticeManager.hasLattice(judgeModelKey)) {
|
|
26637
26652
|
throw new Error(
|
|
26638
26653
|
`Judge model "${judgeModelKey}" not found. Register it first or provide a valid modelKey.`
|
|
@@ -29063,7 +29078,9 @@ function createManageEvalTool() {
|
|
|
29063
29078
|
data = await store.createProject(tid, uuidv48(), {
|
|
29064
29079
|
name: input.name,
|
|
29065
29080
|
description: input.description,
|
|
29066
|
-
|
|
29081
|
+
// No judge key given → default to the 'default' model key (the same
|
|
29082
|
+
// convention the UI model selector uses); never an empty modelKey.
|
|
29083
|
+
judgeModelConfig: { modelKey: input.judgeModelKey ?? "default" },
|
|
29067
29084
|
targetServerConfig: {
|
|
29068
29085
|
workspace_id: ctx.workspaceId,
|
|
29069
29086
|
project_id: ctx.projectId,
|
|
@@ -29138,7 +29155,7 @@ function createManageEvalTool() {
|
|
|
29138
29155
|
description: `Create, update, delete evaluation projects, suites, and test cases.
|
|
29139
29156
|
|
|
29140
29157
|
Project: create_project(name, description?, judgeModelKey?, concurrency?, targetAgentId?) | update_project | delete_project
|
|
29141
|
-
judgeModelKey defaults to
|
|
29158
|
+
judgeModelKey defaults to the "default" model. concurrency defaults to 3.
|
|
29142
29159
|
delete_project rejected if active runs exist.
|
|
29143
29160
|
**When creating a project from within a workspace, the workspace/project context is
|
|
29144
29161
|
automatically bound \u2014 eval runs will execute in the same workspace.**
|
|
@@ -31416,6 +31433,7 @@ export {
|
|
|
31416
31433
|
registerWorkflowRun,
|
|
31417
31434
|
removeCollectionVectorStore,
|
|
31418
31435
|
renderTemplate,
|
|
31436
|
+
resolveJudgeModelKey,
|
|
31419
31437
|
resolvePath,
|
|
31420
31438
|
sandboxLatticeManager,
|
|
31421
31439
|
sanitizeToolCallId,
|