@standardagents/builder 0.22.0 → 0.23.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.
Files changed (35) hide show
  1. package/dist/built-in-routes.js +175 -47
  2. package/dist/built-in-routes.js.map +1 -1
  3. package/dist/client/{ApiKeysView-N0JkbRqs.js → ApiKeysView-1m7uIS8S.js} +1 -1
  4. package/dist/client/{CenteredContentView-DTm87Sif.js → CenteredContentView-DJzHRMGj.js} +1 -1
  5. package/dist/client/{CompositionView-DnSaz1Nk.js → CompositionView-nzqzVKAg.js} +1 -1
  6. package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-DgfpzkTb.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-YX8WE_iB.js} +1 -1
  7. package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-DaO8fv5n.js → CopyButton.vue_vue_type_script_setup_true_lang-BpJt6BT0.js} +1 -1
  8. package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-CXfKtM8R.js → DataTable.vue_vue_type_script_setup_true_lang-Dg3HMMJ0.js} +1 -1
  9. package/dist/client/{JsonViewer-dnp9s6ji.js → JsonViewer-BdNA5OCG.js} +1 -1
  10. package/dist/client/{LoginView-C4vODzeq.js → LoginView-BlF_2TtB.js} +1 -1
  11. package/dist/client/{MarketplaceView-D4QuJAyk.js → MarketplaceView-DrlOb57k.js} +1 -1
  12. package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-DbzeQ2-L.js → Modal.vue_vue_type_script_setup_true_lang-hkOmEwrb.js} +1 -1
  13. package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-CNIgneiU.js → ModelModal.vue_vue_type_script_setup_true_lang-p3esoV-i.js} +1 -1
  14. package/dist/client/{ModelsView-CYQm6yLC.js → ModelsView-CHBanMSH.js} +1 -1
  15. package/dist/client/{PromptEditView-BAJoqY8N.js → PromptEditView-b5B43l4Q.js} +1 -1
  16. package/dist/client/{PromptModal-CFd4gHai.js → PromptModal-BF5bdmNQ.js} +1 -1
  17. package/dist/client/{PromptsView-DDapP7U-.js → PromptsView-6TfMOScI.js} +1 -1
  18. package/dist/client/{ProvidersView-D2g5wSI1.js → ProvidersView-CA5Yx2Fn.js} +1 -1
  19. package/dist/client/{ThreadInspectorPane.vue_vue_type_script_setup_true_lang-Cyvuox_G.js → ThreadInspectorPane.vue_vue_type_script_setup_true_lang-ejyFhmNy.js} +15 -15
  20. package/dist/client/{ThreadsView-Dc3lr6Au.js → ThreadsView-yJpVmf42.js} +1 -1
  21. package/dist/client/{ToolsView-C-marn6m.js → ToolsView-DE1TDnlU.js} +1 -1
  22. package/dist/client/{UsersView-D4j8izbK.js → UsersView-BXDHjJLB.js} +1 -1
  23. package/dist/client/{VariablesView-d3lOE_O2.js → VariablesView-Bz-CbaEv.js} +1 -1
  24. package/dist/client/assets/index-V68N0r_5.css +1 -0
  25. package/dist/client/{index-DR9DbKrm.js → index-TIntu1KJ.js} +2 -2
  26. package/dist/client/index.html +2 -2
  27. package/dist/index.js +106 -6
  28. package/dist/index.js.map +1 -1
  29. package/dist/plugin.js +8 -0
  30. package/dist/plugin.js.map +1 -1
  31. package/dist/runtime.d.ts +29 -0
  32. package/dist/runtime.js +98 -6
  33. package/dist/runtime.js.map +1 -1
  34. package/package.json +5 -5
  35. package/dist/client/assets/index-_JaOWezk.css +0 -1
@@ -5755,7 +5755,7 @@ ${attachmentPaths}`;
5755
5755
  const attachmentId = crypto.randomUUID();
5756
5756
  const timestamp = Date.now();
5757
5757
  const ext = attachment.mimeType === "image/png" ? "png" : attachment.mimeType === "image/jpeg" ? "jpg" : attachment.mimeType === "image/gif" ? "gif" : attachment.mimeType === "image/webp" ? "webp" : attachment.name.split(".").pop() || "bin";
5758
- const path9 = `/attachments/${timestamp}-${attachmentId}.${ext}`;
5758
+ const path9 = `/attachments/${timestamp}-${attachmentId.slice(0, 8)}.${ext}`;
5759
5759
  const binaryString = atob(attachment.data);
5760
5760
  const dataBuffer = new Uint8Array(binaryString.length);
5761
5761
  for (let i = 0; i < binaryString.length; i++) {
@@ -5989,9 +5989,10 @@ var init_context = __esm({
5989
5989
  // src/agents/FlowEngine.ts
5990
5990
  var FlowEngine_exports = {};
5991
5991
  __export(FlowEngine_exports, {
5992
- FlowEngine: () => FlowEngine
5992
+ FlowEngine: () => FlowEngine,
5993
+ HookBlockedExecutionError: () => HookBlockedExecutionError
5993
5994
  });
5994
- var IMMEDIATE_BOOTSTRAP_TOOL_NAME, FlowEngine;
5995
+ var IMMEDIATE_BOOTSTRAP_TOOL_NAME, HookBlockedExecutionError, FlowEngine;
5995
5996
  var init_FlowEngine = __esm({
5996
5997
  "src/agents/FlowEngine.ts"() {
5997
5998
  init_types();
@@ -6002,6 +6003,12 @@ var init_FlowEngine = __esm({
6002
6003
  init_sessionTools();
6003
6004
  init_ThreadStateImpl();
6004
6005
  IMMEDIATE_BOOTSTRAP_TOOL_NAME = "bootstrap_immediate_subagent";
6006
+ HookBlockedExecutionError = class extends Error {
6007
+ constructor(message) {
6008
+ super(message);
6009
+ this.name = "HookBlockedExecutionError";
6010
+ }
6011
+ };
6005
6012
  FlowEngine = class _FlowEngine {
6006
6013
  static IMMEDIATE_SCOPED_ENV_CONTEXT_KEY = "__immediate_scoped_env_by_call_id";
6007
6014
  /**
@@ -6549,7 +6556,26 @@ This usually points to something I can't fix from here \u2014 for example the wo
6549
6556
  state.messageHistory = await this.loadMessageHistory(state);
6550
6557
  const context = await this.assembleContext(state);
6551
6558
  state.allowedTools = context.tools;
6552
- context.messages = await this.runPrefilterLLMHistoryHook(state, context.messages);
6559
+ try {
6560
+ context.messages = await this.runPrefilterLLMHistoryHook(state, context.messages);
6561
+ } catch (error) {
6562
+ if (error instanceof HookBlockedExecutionError) {
6563
+ const threadState = ThreadStateImpl.fromFlowState(state);
6564
+ await threadState.injectMessage({ role: "assistant", content: error.message });
6565
+ state.stopped = true;
6566
+ state.stoppedBy = state.currentSide;
6567
+ state.stopReason = error.message;
6568
+ state.stopReasonCode = "hook_blocked";
6569
+ state.emitTelemetry?.({
6570
+ type: "stopped",
6571
+ reason: state.stopReason,
6572
+ side: state.currentSide,
6573
+ timestamp: Date.now()
6574
+ });
6575
+ return;
6576
+ }
6577
+ throw error;
6578
+ }
6553
6579
  const pendingMessageId = await this.createPendingMessage(state);
6554
6580
  state.pendingMessageId = pendingMessageId;
6555
6581
  let responseStatus = "completed";
@@ -8705,6 +8731,9 @@ ${lines.join("\n\n")}`
8705
8731
  try {
8706
8732
  result = await executor(threadState, result);
8707
8733
  } catch (error) {
8734
+ if (error && typeof error === "object" && error.block === true) {
8735
+ throw new HookBlockedExecutionError(error instanceof Error ? error.message : String(error));
8736
+ }
8708
8737
  console.error("[Hooks] \u2717 Error running prefilter_llm_history hook:", error);
8709
8738
  }
8710
8739
  }
@@ -9313,7 +9342,7 @@ ${lines.join("\n\n")}`
9313
9342
  const base64Data = match2[2];
9314
9343
  const ext = mimeType.split("/")[1] || "png";
9315
9344
  const attachmentId = crypto.randomUUID();
9316
- const path9 = `/attachments/${Date.now()}-${attachmentId}.${ext}`;
9345
+ const path9 = `/attachments/${Date.now()}-${attachmentId.slice(0, 8)}.${ext}`;
9317
9346
  try {
9318
9347
  await state.thread.instance.writeFile(path9, base64Data, mimeType);
9319
9348
  if (image.id) {
@@ -9383,7 +9412,7 @@ ${lines.join("\n\n")}`
9383
9412
  const base64Data = imageUrl.slice(base64Index + base64Marker.length);
9384
9413
  const ext = mimeType.split("/")[1] || "png";
9385
9414
  const attachmentId = crypto.randomUUID();
9386
- const path9 = `/attachments/${Date.now()}-${attachmentId}.${ext}`;
9415
+ const path9 = `/attachments/${Date.now()}-${attachmentId.slice(0, 8)}.${ext}`;
9387
9416
  try {
9388
9417
  await state.thread.instance.writeFile(path9, base64Data, mimeType);
9389
9418
  const attachmentRef = {
@@ -69048,7 +69077,54 @@ var continue_post_default = defineController2(async ({ req, params, env: env2 })
69048
69077
  }
69049
69078
  });
69050
69079
 
69080
+ // src/agents/cost-summary.ts
69081
+ function emptyCostSummary() {
69082
+ return { totalCost: 0, requestCount: 0, messageCount: 0, byModel: {} };
69083
+ }
69084
+ function mergeByModel(summaries) {
69085
+ const merged = {};
69086
+ for (const summary of summaries) {
69087
+ for (const [modelName, acc] of Object.entries(summary.byModel)) {
69088
+ const entry = merged[modelName] ?? { totalCost: 0, count: 0 };
69089
+ entry.totalCost += acc.totalCost;
69090
+ entry.count += acc.count;
69091
+ merged[modelName] = entry;
69092
+ }
69093
+ }
69094
+ return merged;
69095
+ }
69096
+ function sumSummaries(summaries) {
69097
+ let totalCost = 0;
69098
+ let requestCount = 0;
69099
+ let messageCount = 0;
69100
+ for (const summary of summaries) {
69101
+ totalCost += summary.totalCost;
69102
+ requestCount += summary.requestCount;
69103
+ messageCount += summary.messageCount;
69104
+ }
69105
+ return { totalCost, requestCount, messageCount };
69106
+ }
69107
+ function buildModelBreakdown(byModel) {
69108
+ return Object.entries(byModel).map(([modelName, acc]) => ({
69109
+ modelName,
69110
+ totalCost: acc.totalCost,
69111
+ requestCount: acc.count,
69112
+ avgCostPerRequest: acc.count > 0 ? acc.totalCost / acc.count : 0
69113
+ })).sort((a, b) => b.totalCost - a.totalCost);
69114
+ }
69115
+ function threadNameFromTags(tags) {
69116
+ for (const tag of tags ?? []) {
69117
+ if (typeof tag === "string" && tag.startsWith("name:")) {
69118
+ const value = tag.slice("name:".length).trim();
69119
+ if (value) return value;
69120
+ }
69121
+ }
69122
+ return null;
69123
+ }
69124
+
69051
69125
  // src/api/threads/[id]/cost.get.ts
69126
+ var MAX_DESCENDANTS = 200;
69127
+ var SUMMARY_BATCH = 10;
69052
69128
  var cost_get_default = defineController2(async ({ req, params, env: env2 }) => {
69053
69129
  const threadId = params.id;
69054
69130
  if (!threadId) {
@@ -69064,52 +69140,70 @@ var cost_get_default = defineController2(async ({ req, params, env: env2 }) => {
69064
69140
  { status: 404 }
69065
69141
  );
69066
69142
  }
69067
- const durableId = env2.AGENT_BUILDER_THREAD.idFromName(threadId);
69068
- const stub = env2.AGENT_BUILDER_THREAD.get(durableId);
69069
- const logsResult = await stub.getLogs(1e4, 0, "ASC");
69070
- const logs = logsResult.logs || [];
69071
- let totalCost = 0;
69072
- const modelCosts = {};
69073
- const uniqueMessages = /* @__PURE__ */ new Set();
69074
- for (const log of logs) {
69075
- const cost = log.cost_total;
69076
- if (cost !== null && cost !== void 0 && !isNaN(cost)) {
69077
- totalCost += cost;
69078
- if (log.message_id) {
69079
- uniqueMessages.add(log.message_id);
69080
- }
69081
- const modelKey = log.model_name || log.model || "unknown";
69082
- if (!modelCosts[modelKey]) {
69083
- modelCosts[modelKey] = {
69084
- totalCost: 0,
69085
- count: 0
69086
- };
69087
- }
69088
- modelCosts[modelKey].totalCost += cost;
69089
- modelCosts[modelKey].count += 1;
69143
+ const descendants = (await agentBuilder.getDescendantThreads(threadId) ?? []).slice(
69144
+ 0,
69145
+ MAX_DESCENDANTS + 1
69146
+ );
69147
+ const truncated = descendants.length > MAX_DESCENDANTS;
69148
+ if (truncated) descendants.length = MAX_DESCENDANTS;
69149
+ const summarize = async (id) => {
69150
+ try {
69151
+ const durableId = env2.AGENT_BUILDER_THREAD.idFromName(id);
69152
+ const stub = env2.AGENT_BUILDER_THREAD.get(durableId);
69153
+ return await stub.getCostSummary() ?? emptyCostSummary();
69154
+ } catch {
69155
+ return emptyCostSummary();
69090
69156
  }
69157
+ };
69158
+ const ownSummary = await summarize(threadId);
69159
+ const descendantSummaries = [];
69160
+ for (let i = 0; i < descendants.length; i += SUMMARY_BATCH) {
69161
+ const batch = descendants.slice(i, i + SUMMARY_BATCH);
69162
+ descendantSummaries.push(
69163
+ ...await Promise.all(batch.map((child) => summarize(child.id)))
69164
+ );
69091
69165
  }
69092
- const messageCount = uniqueMessages.size;
69093
- const avgCostPerMessage = messageCount > 0 ? totalCost / messageCount : 0;
69166
+ const allSummaries = [ownSummary, ...descendantSummaries];
69167
+ const totals = sumSummaries(allSummaries);
69168
+ const byModel = mergeByModel(allSummaries);
69169
+ const modelBreakdown = buildModelBreakdown(byModel);
69094
69170
  const avgCostPerMessageByModel = {};
69095
- for (const [modelName, data] of Object.entries(modelCosts)) {
69096
- avgCostPerMessageByModel[modelName] = {
69097
- avgCost: data.count > 0 ? data.totalCost / data.count : 0,
69098
- messageCount: data.count
69171
+ for (const entry of modelBreakdown) {
69172
+ avgCostPerMessageByModel[entry.modelName] = {
69173
+ avgCost: entry.avgCostPerRequest,
69174
+ messageCount: entry.requestCount
69099
69175
  };
69100
69176
  }
69101
- const modelBreakdown = Object.entries(modelCosts).map(([modelName, data]) => ({
69102
- modelName,
69103
- totalCost: data.totalCost,
69104
- requestCount: data.count,
69105
- avgCostPerRequest: data.count > 0 ? data.totalCost / data.count : 0
69106
- }));
69177
+ const threads = [
69178
+ {
69179
+ threadId,
69180
+ agentName: thread.agent_name ?? null,
69181
+ threadName: threadNameFromTags(thread.tags),
69182
+ parent: null,
69183
+ isRoot: true,
69184
+ totalCost: ownSummary.totalCost,
69185
+ requestCount: ownSummary.requestCount
69186
+ },
69187
+ ...descendants.map((child, index) => ({
69188
+ threadId: child.id,
69189
+ agentName: child.agent_name ?? null,
69190
+ threadName: threadNameFromTags(child.tags),
69191
+ parent: child.parent,
69192
+ isRoot: false,
69193
+ totalCost: descendantSummaries[index]?.totalCost ?? 0,
69194
+ requestCount: descendantSummaries[index]?.requestCount ?? 0
69195
+ })).filter((row) => row.requestCount > 0)
69196
+ ];
69107
69197
  return Response.json({
69108
- totalCost,
69109
- messageCount,
69110
- avgCostPerMessage,
69198
+ totalCost: totals.totalCost,
69199
+ ownCost: ownSummary.totalCost,
69200
+ requestCount: totals.requestCount,
69201
+ messageCount: totals.messageCount,
69202
+ avgCostPerMessage: totals.messageCount > 0 ? totals.totalCost / totals.messageCount : 0,
69111
69203
  modelBreakdown,
69112
- avgCostPerMessageByModel
69204
+ avgCostPerMessageByModel,
69205
+ threads,
69206
+ truncated
69113
69207
  });
69114
69208
  } catch (error) {
69115
69209
  console.error(`Error calculating cost for thread ${threadId}:`, error);
@@ -69575,7 +69669,7 @@ var messages_post_default = defineController2(async ({ req, params, env: env2 })
69575
69669
  }
69576
69670
  }
69577
69671
  const ext = mimeType === "image/png" ? "png" : mimeType === "image/jpeg" ? "jpg" : attachment.name.split(".").pop() || "bin";
69578
- const path9 = `/attachments/${timestamp}-${attachmentId}.${ext}`;
69672
+ const path9 = `/attachments/${timestamp}-${attachmentId.slice(0, 8)}.${ext}`;
69579
69673
  const base64Size = fileData.length;
69580
69674
  const binarySize = Math.ceil(base64Size * 3 / 4);
69581
69675
  console.log(`[writeFile] Storing ${attachment.name}: ${(binarySize / 1024 / 1024).toFixed(2)}MB binary (${(base64Size / 1024 / 1024).toFixed(2)}MB base64) to ${path9}`);
@@ -70189,7 +70283,13 @@ var approve_get_default = defineController2(async ({ req, env: env2, params }) =
70189
70283
  const code = params.code;
70190
70284
  if (!code) return page("Missing code", "This device link is malformed.", false);
70191
70285
  const authResult = await requireAuth(req, env2);
70192
- if (authResult instanceof Response) return authResult;
70286
+ if (authResult instanceof Response) {
70287
+ const url = new URL(req.url);
70288
+ const returnTo = encodeURIComponent(url.pathname);
70289
+ const hosted = Boolean(env2.STANDARD_AGENTS_HOSTED && String(env2.STANDARD_AGENTS_HOSTED) !== "0" && String(env2.STANDARD_AGENTS_HOSTED).toLowerCase() !== "false");
70290
+ const target = hosted ? `/api/auth/sa/start?return_to=${returnTo}` : `/login?return_to=${returnTo}`;
70291
+ return new Response(null, { status: 302, headers: { Location: `${url.origin}${target}` } });
70292
+ }
70193
70293
  if (authResult.authType === "api_key") {
70194
70294
  return page("Sign in required", "Device logins must be approved from a signed-in browser session.", false);
70195
70295
  }
@@ -70604,6 +70704,20 @@ async function handleChunkedUploadComplete(stub, filePath, req) {
70604
70704
 
70605
70705
  // src/api/threads/[id]/logs/[logId].get.ts
70606
70706
  var logId_get_default = defineController2(async ({ req, params, env: env2 }) => {
70707
+ if (isPlatformHosted(env2)) {
70708
+ const authResult = await requirePermission(req, env2, "logs");
70709
+ if (authResult instanceof Response) {
70710
+ return authResult;
70711
+ }
70712
+ } else {
70713
+ const authContext = await authenticate(req, env2);
70714
+ if (authContext && !hasPermission(authContext.user, "logs")) {
70715
+ return Response.json(
70716
+ { error: "Forbidden: 'logs' access required" },
70717
+ { status: 403 }
70718
+ );
70719
+ }
70720
+ }
70607
70721
  const threadId = params.id;
70608
70722
  const logId = params.logId;
70609
70723
  if (!threadId) {
@@ -71019,6 +71133,20 @@ function createInspectProviderConfig(providerName, factory, env2) {
71019
71133
  };
71020
71134
  }
71021
71135
  var provider_get_default = defineController2(async ({ req, params, env: env2 }) => {
71136
+ if (isPlatformHosted(env2)) {
71137
+ const authResult = await requirePermission(req, env2, "logs");
71138
+ if (authResult instanceof Response) {
71139
+ return authResult;
71140
+ }
71141
+ } else {
71142
+ const authContext = await authenticate(req, env2);
71143
+ if (authContext && !hasPermission(authContext.user, "logs")) {
71144
+ return Response.json(
71145
+ { error: "Forbidden: 'logs' access required" },
71146
+ { status: 403 }
71147
+ );
71148
+ }
71149
+ }
71022
71150
  const threadId = params.id;
71023
71151
  const logId = params.logId;
71024
71152
  const providerName = params.provider;