@standardagents/builder 0.10.1-next.bbd142a → 0.11.0-next.ab7e1ea

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.js CHANGED
@@ -1,6 +1,4 @@
1
- import { probe, sip } from '@standardagents/sip';
2
- import { decode as decode$1, encode } from '@jsquash/png';
3
- import { decode } from '@jsquash/avif';
1
+ import { sip } from '@standardagents/sip';
4
2
  import fs2 from 'fs';
5
3
  import path3 from 'path';
6
4
  import { fileURLToPath } from 'url';
@@ -879,15 +877,18 @@ var TestProvider;
879
877
  var init_TestProvider = __esm({
880
878
  "src/agents/providers/TestProvider.ts"() {
881
879
  init_BaseProvider();
880
+ init_TestScript();
882
881
  TestProvider = class extends BaseProvider {
883
882
  script;
884
883
  responseIndex = 0;
885
884
  validateInputs;
886
885
  debugLog;
887
886
  requestLog = [];
887
+ useDefaultResponse;
888
888
  constructor(config) {
889
889
  super(config);
890
- this.script = config.script;
890
+ this.useDefaultResponse = !config.script;
891
+ this.script = config.script ?? TestScript.create().addTextResponse("Test response received.");
891
892
  this.validateInputs = config.validateInputs ?? false;
892
893
  this.debugLog = config.debugLog ?? false;
893
894
  }
@@ -915,14 +916,20 @@ var init_TestProvider = __esm({
915
916
  throw new Error("Request aborted");
916
917
  }
917
918
  const responses = this.script.getResponses();
919
+ let scripted;
918
920
  if (this.responseIndex >= responses.length) {
919
- const lastMessage = context.messages.slice(-1)[0];
920
- const lastContent = contentToString(lastMessage?.content);
921
- throw new Error(
922
- `TestProvider: Script exhausted after ${this.responseIndex} responses. Expected ${responses.length} total requests. Received request with ${context.messages.length} messages. Last message role: "${lastMessage?.role}", content: "${lastContent.substring(0, 100)}..."`
923
- );
921
+ if (this.useDefaultResponse) {
922
+ scripted = responses[0];
923
+ } else {
924
+ const lastMessage = context.messages.slice(-1)[0];
925
+ const lastContent = contentToString(lastMessage?.content);
926
+ throw new Error(
927
+ `TestProvider: Script exhausted after ${this.responseIndex} responses. Expected ${responses.length} total requests. Received request with ${context.messages.length} messages. Last message role: "${lastMessage?.role}", content: "${lastContent.substring(0, 100)}..."`
928
+ );
929
+ }
930
+ } else {
931
+ scripted = responses[this.responseIndex];
924
932
  }
925
- const scripted = responses[this.responseIndex];
926
933
  this.responseIndex++;
927
934
  if (this.validateInputs && scripted.expectInput) {
928
935
  this.validateInput(context, scripted.expectInput);
@@ -4603,7 +4610,9 @@ function rowToFileRecord(row) {
4603
4610
  size: row.size,
4604
4611
  metadata: row.metadata ? JSON.parse(row.metadata) : null,
4605
4612
  isDirectory: row.is_directory === 1,
4606
- createdAt: row.created_at
4613
+ createdAt: row.created_at,
4614
+ width: row.width ?? null,
4615
+ height: row.height ?? null
4607
4616
  };
4608
4617
  }
4609
4618
  function inferMimeType(filename) {
@@ -4674,8 +4683,8 @@ var init_files = __esm({
4674
4683
  }
4675
4684
  const metadataJson = options?.metadata ? JSON.stringify(options.metadata) : null;
4676
4685
  await this.sql.exec(
4677
- `INSERT OR REPLACE INTO files (path, name, mime_type, storage, location, data, content, size, metadata, thumbnail, is_directory, created_at)
4678
- VALUES (?, ?, ?, 'local', NULL, ?, ?, ?, ?, ?, 0, ?)`,
4686
+ `INSERT OR REPLACE INTO files (path, name, mime_type, storage, location, data, content, size, metadata, thumbnail, is_directory, created_at, width, height)
4687
+ VALUES (?, ?, ?, 'local', NULL, ?, ?, ?, ?, ?, 0, ?, ?, ?)`,
4679
4688
  normalizedPath,
4680
4689
  name,
4681
4690
  mimeType,
@@ -4684,7 +4693,9 @@ var init_files = __esm({
4684
4693
  size,
4685
4694
  metadataJson,
4686
4695
  options?.thumbnail || null,
4687
- now
4696
+ now,
4697
+ options?.width ?? null,
4698
+ options?.height ?? null
4688
4699
  );
4689
4700
  await this.updateStats();
4690
4701
  return {
@@ -4696,7 +4707,9 @@ var init_files = __esm({
4696
4707
  size,
4697
4708
  metadata: options?.metadata || null,
4698
4709
  isDirectory: false,
4699
- createdAt: now
4710
+ createdAt: now,
4711
+ width: options?.width ?? null,
4712
+ height: options?.height ?? null
4700
4713
  };
4701
4714
  }
4702
4715
  /**
@@ -4749,7 +4762,8 @@ var init_files = __esm({
4749
4762
  const row = rows[0];
4750
4763
  if (row.storage !== "local") return null;
4751
4764
  if (row.content !== null) {
4752
- return new TextEncoder().encode(row.content);
4765
+ const encoded = new TextEncoder().encode(row.content);
4766
+ return encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
4753
4767
  }
4754
4768
  return row.data;
4755
4769
  }
@@ -4970,144 +4984,19 @@ async function processImage(input, inputMimeType) {
4970
4984
  if (input.byteLength > MAX_INPUT_SIZE) {
4971
4985
  throw new Error(`Image too large: ${input.byteLength} bytes exceeds ${MAX_INPUT_SIZE} byte limit`);
4972
4986
  }
4973
- const probeResult = probe(input);
4974
- const format = probeResult.format !== "unknown" ? probeResult.format : detectFormat(input, inputMimeType);
4975
- const hasAlpha = probeResult.hasAlpha;
4976
- if (hasAlpha && (format === "png" || format === "avif" || format === "webp")) {
4977
- return await processPngWithAlpha(input, format);
4978
- }
4979
- try {
4980
- const result = await sip.process(input, {
4981
- maxWidth: MAX_DIMENSION,
4982
- maxHeight: MAX_DIMENSION,
4983
- maxBytes: MAX_SIZE,
4984
- quality: 85
4985
- });
4986
- return {
4987
- data: result.data,
4988
- mimeType: "image/jpeg",
4989
- width: result.width,
4990
- height: result.height
4991
- };
4992
- } catch (err) {
4993
- console.error("[sip] Processing failed, falling back:", err);
4994
- throw err;
4995
- }
4996
- }
4997
- async function processPngWithAlpha(input, format) {
4998
- let imageData;
4999
- if (format === "avif") {
5000
- imageData = await decode(input);
5001
- } else {
5002
- imageData = await decode$1(input);
5003
- }
5004
- const originalWidth = imageData.width;
5005
- const originalHeight = imageData.height;
5006
- let encoded = await encode(imageData);
5007
- if (encoded.byteLength <= MAX_SIZE) {
5008
- return {
5009
- data: encoded,
5010
- mimeType: "image/png",
5011
- width: originalWidth,
5012
- height: originalHeight
5013
- };
5014
- }
5015
- let scale = 0.9;
5016
- while (encoded.byteLength > MAX_SIZE && scale > 0.15) {
5017
- const newWidth = Math.floor(originalWidth * scale);
5018
- const newHeight = Math.floor(originalHeight * scale);
5019
- if (newWidth < 100 || newHeight < 100) {
5020
- scale *= 0.9;
5021
- continue;
5022
- }
5023
- const resized = resizeRgba(
5024
- new Uint8ClampedArray(imageData.data),
5025
- originalWidth,
5026
- originalHeight,
5027
- newWidth,
5028
- newHeight
5029
- );
5030
- const resizedImageData = { data: resized, width: newWidth, height: newHeight };
5031
- encoded = await encode(resizedImageData);
5032
- if (encoded.byteLength <= MAX_SIZE) {
5033
- return {
5034
- data: encoded,
5035
- mimeType: "image/png",
5036
- width: newWidth,
5037
- height: newHeight
5038
- };
5039
- }
5040
- scale *= 0.9;
5041
- }
5042
- const finalWidth = Math.floor(originalWidth * 0.15);
5043
- const finalHeight = Math.floor(originalHeight * 0.15);
5044
- const finalResized = resizeRgba(
5045
- new Uint8ClampedArray(imageData.data),
5046
- originalWidth,
5047
- originalHeight,
5048
- finalWidth,
5049
- finalHeight
5050
- );
5051
- encoded = await encode({ data: finalResized, width: finalWidth, height: finalHeight });
4987
+ const result = await sip.process(input, {
4988
+ maxWidth: MAX_DIMENSION,
4989
+ maxHeight: MAX_DIMENSION,
4990
+ maxBytes: MAX_SIZE,
4991
+ quality: 85
4992
+ });
5052
4993
  return {
5053
- data: encoded,
5054
- mimeType: "image/png",
5055
- width: finalWidth,
5056
- height: finalHeight
4994
+ data: result.data,
4995
+ mimeType: "image/jpeg",
4996
+ width: result.width,
4997
+ height: result.height
5057
4998
  };
5058
4999
  }
5059
- function resizeRgba(src, srcWidth, srcHeight, dstWidth, dstHeight) {
5060
- const dst = new Uint8ClampedArray(dstWidth * dstHeight * 4);
5061
- const xScale = srcWidth / dstWidth;
5062
- const yScale = srcHeight / dstHeight;
5063
- for (let dstY = 0; dstY < dstHeight; dstY++) {
5064
- for (let dstX = 0; dstX < dstWidth; dstX++) {
5065
- const srcXFloat = dstX * xScale;
5066
- const srcYFloat = dstY * yScale;
5067
- const srcX0 = Math.floor(srcXFloat);
5068
- const srcY0 = Math.floor(srcYFloat);
5069
- const srcX1 = Math.min(srcX0 + 1, srcWidth - 1);
5070
- const srcY1 = Math.min(srcY0 + 1, srcHeight - 1);
5071
- const tx = srcXFloat - srcX0;
5072
- const ty = srcYFloat - srcY0;
5073
- const idx00 = (srcY0 * srcWidth + srcX0) * 4;
5074
- const idx10 = (srcY0 * srcWidth + srcX1) * 4;
5075
- const idx01 = (srcY1 * srcWidth + srcX0) * 4;
5076
- const idx11 = (srcY1 * srcWidth + srcX1) * 4;
5077
- const dstIdx = (dstY * dstWidth + dstX) * 4;
5078
- for (let c = 0; c < 4; c++) {
5079
- const v00 = src[idx00 + c];
5080
- const v10 = src[idx10 + c];
5081
- const v01 = src[idx01 + c];
5082
- const v11 = src[idx11 + c];
5083
- const top = v00 * (1 - tx) + v10 * tx;
5084
- const bottom = v01 * (1 - tx) + v11 * tx;
5085
- dst[dstIdx + c] = Math.round(top * (1 - ty) + bottom * ty);
5086
- }
5087
- }
5088
- }
5089
- return dst;
5090
- }
5091
- function detectFormat(data, mimeType) {
5092
- const bytes = new Uint8Array(data.slice(0, 12));
5093
- if (bytes[4] === 102 && bytes[5] === 116 && bytes[6] === 121 && bytes[7] === 112) {
5094
- const brand = String.fromCharCode(...bytes.slice(8, 12));
5095
- if (brand === "avif" || brand === "avis") return "avif";
5096
- }
5097
- if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
5098
- return "png";
5099
- }
5100
- if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
5101
- return "jpeg";
5102
- }
5103
- if (bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) {
5104
- return "webp";
5105
- }
5106
- if (mimeType.includes("png")) return "png";
5107
- if (mimeType.includes("webp")) return "webp";
5108
- if (mimeType.includes("avif")) return "avif";
5109
- return "jpeg";
5110
- }
5111
5000
  function needsProcessing(data, mimeType) {
5112
5001
  const binaryLength = Math.ceil(data.length * 3 / 4);
5113
5002
  return binaryLength > MAX_SIZE || mimeType.includes("avif") || mimeType.includes("webp");
@@ -6119,7 +6008,7 @@ function generateAgentFile(data) {
6119
6008
  if (data.type && data.type !== "ai_human") {
6120
6009
  lines.push(` type: '${data.type}',`);
6121
6010
  }
6122
- if (data.maxSessionTurns !== void 0) {
6011
+ if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
6123
6012
  lines.push(` maxSessionTurns: ${data.maxSessionTurns},`);
6124
6013
  }
6125
6014
  lines.push(` sideA: ${formatSideConfig(data.sideA)},`);
@@ -6258,7 +6147,7 @@ function validateModelData(data) {
6258
6147
  if (!data.provider || typeof data.provider !== "string") {
6259
6148
  return "Model provider is required and must be a string";
6260
6149
  }
6261
- const validProviders = ["openai", "openrouter", "anthropic", "google"];
6150
+ const validProviders = ["openai", "openrouter", "anthropic", "google", "test"];
6262
6151
  if (!validProviders.includes(data.provider)) {
6263
6152
  return `Invalid provider '${data.provider}'. Must be one of: ${validProviders.join(", ")}`;
6264
6153
  }
@@ -6762,7 +6651,7 @@ function validateAgentData(data) {
6762
6651
  if (data.exposeAsTool && !data.toolDescription) {
6763
6652
  return "toolDescription is required when exposeAsTool is true";
6764
6653
  }
6765
- if (data.maxSessionTurns !== void 0) {
6654
+ if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
6766
6655
  if (typeof data.maxSessionTurns !== "number" || data.maxSessionTurns <= 0) {
6767
6656
  return "maxSessionTurns must be a positive number";
6768
6657
  }
@@ -7195,11 +7084,10 @@ function agentbuilder(options = {}) {
7195
7084
  // WASM image processing deps - must be excluded to avoid pre-bundle cache issues
7196
7085
  "@cf-wasm/photon",
7197
7086
  "@cf-wasm/photon/workerd",
7087
+ "@standardagents/sip",
7088
+ // sip's jsquash dependencies (WASM-based decoders)
7198
7089
  "@jsquash/avif",
7199
- "@jsquash/jpeg",
7200
- "@jsquash/png",
7201
- "@jsquash/webp",
7202
- "@standardagents/sip"
7090
+ "@jsquash/webp"
7203
7091
  ];
7204
7092
  const depsToInclude = [
7205
7093
  "zod",
@@ -7234,11 +7122,10 @@ function agentbuilder(options = {}) {
7234
7122
  // WASM image processing deps
7235
7123
  "@cf-wasm/photon",
7236
7124
  "@cf-wasm/photon/workerd",
7125
+ "@standardagents/sip",
7126
+ // sip's jsquash dependencies (WASM-based decoders)
7237
7127
  "@jsquash/avif",
7238
- "@jsquash/jpeg",
7239
- "@jsquash/png",
7240
- "@jsquash/webp",
7241
- "@standardagents/sip"
7128
+ "@jsquash/webp"
7242
7129
  ];
7243
7130
  const depsToInclude = [
7244
7131
  "zod",
@@ -9229,8 +9116,18 @@ var migration17 = {
9229
9116
  }
9230
9117
  };
9231
9118
 
9119
+ // src/durable-objects/migrations/018_add_image_dimensions.ts
9120
+ var migration18 = {
9121
+ version: 18,
9122
+ async up(sql) {
9123
+ await sql.exec(`ALTER TABLE files ADD COLUMN width INTEGER`);
9124
+ await sql.exec(`ALTER TABLE files ADD COLUMN height INTEGER`);
9125
+ await sql.exec(`UPDATE _metadata SET value = '18' WHERE key = 'schema_version'`);
9126
+ }
9127
+ };
9128
+
9232
9129
  // src/durable-objects/migrations/index.ts
9233
- var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16, migration17];
9130
+ var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16, migration17, migration18];
9234
9131
  var LATEST_SCHEMA_VERSION = migrations.length;
9235
9132
 
9236
9133
  // src/durable-objects/DurableThread.ts
@@ -9631,9 +9528,9 @@ var DurableThread = class extends DurableObject {
9631
9528
  * Each migration is run in order, starting from the current version + 1.
9632
9529
  */
9633
9530
  async runMigrations(fromVersion) {
9634
- for (const migration19 of migrations) {
9635
- if (migration19.version > fromVersion) {
9636
- await migration19.up(this.ctx.storage.sql);
9531
+ for (const migration20 of migrations) {
9532
+ if (migration20.version > fromVersion) {
9533
+ await migration20.up(this.ctx.storage.sql);
9637
9534
  }
9638
9535
  }
9639
9536
  }
@@ -10219,6 +10116,8 @@ var DurableThread = class extends DurableObject {
10219
10116
  id: threadMetadata.agent_name,
10220
10117
  title: agentDef.title || threadMetadata.agent_name,
10221
10118
  type: agentDef.type,
10119
+ description: agentDef.description,
10120
+ icon: agentDef.icon,
10222
10121
  side_a_label: agentDef.sideA?.label,
10223
10122
  side_b_label: agentDef.sideB?.label
10224
10123
  };
@@ -10718,7 +10617,7 @@ var DurableThread = class extends DurableObject {
10718
10617
  id: message.id,
10719
10618
  role: message.role,
10720
10619
  content: message.content,
10721
- attachments: message.attachments,
10620
+ attachments: message.attachments ? JSON.parse(message.attachments) : null,
10722
10621
  created_at: message.created_at
10723
10622
  });
10724
10623
  const nextSide = role === "assistant" ? "b" : "a";
@@ -11177,7 +11076,7 @@ var DurableThread = class extends DurableObject {
11177
11076
  };
11178
11077
 
11179
11078
  // src/durable-objects/agentbuilder-migrations/0001_initial.ts
11180
- var migration18 = {
11079
+ var migration19 = {
11181
11080
  version: 1,
11182
11081
  async up(sql) {
11183
11082
  sql.exec(`
@@ -11276,7 +11175,7 @@ var migration18 = {
11276
11175
  };
11277
11176
 
11278
11177
  // src/durable-objects/agentbuilder-migrations/index.ts
11279
- var migrations2 = [migration18];
11178
+ var migrations2 = [migration19];
11280
11179
  var LATEST_SCHEMA_VERSION2 = 1;
11281
11180
 
11282
11181
  // src/durable-objects/DurableAgentBuilder.ts
@@ -11366,9 +11265,9 @@ var DurableAgentBuilder = class extends DurableObject {
11366
11265
  }
11367
11266
  }
11368
11267
  async runMigrations(fromVersion) {
11369
- for (const migration19 of migrations2) {
11370
- if (migration19.version > fromVersion) {
11371
- await migration19.up(this.ctx.storage.sql);
11268
+ for (const migration20 of migrations2) {
11269
+ if (migration20.version > fromVersion) {
11270
+ await migration20.up(this.ctx.storage.sql);
11372
11271
  }
11373
11272
  }
11374
11273
  }
@@ -12180,7 +12079,7 @@ function defineAgent(options) {
12180
12079
  if (options.sideB?.maxTurns !== void 0 && options.sideB.maxTurns <= 0) {
12181
12080
  throw new Error("sideB.maxTurns must be a positive number");
12182
12081
  }
12183
- if (options.maxSessionTurns !== void 0 && options.maxSessionTurns <= 0) {
12082
+ if (options.maxSessionTurns !== void 0 && options.maxSessionTurns !== null && options.maxSessionTurns <= 0) {
12184
12083
  throw new Error("maxSessionTurns must be a positive number");
12185
12084
  }
12186
12085
  if (!["ai_human", "dual_ai"].includes(type)) {