@amaster.ai/employee-runtime-connector 0.1.1-beta.255 → 0.1.1-beta.256

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.
@@ -5508,6 +5508,32 @@ var amasterRuntimeConnectorLogIngestSchema = external_exports.object({
5508
5508
  message: external_exports.string().max(16e3),
5509
5509
  payload: external_exports.record(external_exports.unknown()).default({})
5510
5510
  });
5511
+ var AMASTER_RUNTIME_CONNECTOR_LOG_BATCH_MAX_ENTRIES = 32;
5512
+ var AMASTER_RUNTIME_CONNECTOR_LOG_BATCH_MAX_BYTES = 128 * 1024;
5513
+ var amasterRuntimeConnectorLogIngestBatchSchema = external_exports.object({
5514
+ entries: external_exports.array(amasterRuntimeConnectorLogIngestSchema).min(1).max(AMASTER_RUNTIME_CONNECTOR_LOG_BATCH_MAX_ENTRIES)
5515
+ }).superRefine((value, ctx) => {
5516
+ const commandIds = new Set(value.entries.flatMap((entry) => entry.commandId ? [entry.commandId] : []));
5517
+ if (commandIds.size > 1) {
5518
+ ctx.addIssue({
5519
+ code: external_exports.ZodIssueCode.custom,
5520
+ path: ["entries"],
5521
+ message: "Runtime connector log batch entries must share one commandId"
5522
+ });
5523
+ }
5524
+ const serializedBytes = new TextEncoder().encode(JSON.stringify(value)).byteLength;
5525
+ if (serializedBytes > AMASTER_RUNTIME_CONNECTOR_LOG_BATCH_MAX_BYTES) {
5526
+ ctx.addIssue({
5527
+ code: external_exports.ZodIssueCode.too_big,
5528
+ type: "array",
5529
+ maximum: AMASTER_RUNTIME_CONNECTOR_LOG_BATCH_MAX_BYTES,
5530
+ inclusive: true,
5531
+ exact: false,
5532
+ path: ["entries"],
5533
+ message: "Runtime connector log batch exceeds 128 KiB"
5534
+ });
5535
+ }
5536
+ });
5511
5537
  var amasterRuntimeConnectorCostIngestSchema = external_exports.object({
5512
5538
  commandId: external_exports.string().uuid(),
5513
5539
  idempotencyKey: external_exports.string().trim().regex(/^runtime-command-cost:[0-9a-f-]{36}$/i).optional(),
@@ -33516,7 +33542,7 @@ function assertRequiredTaskAttachmentMaterialized(input, materialized) {
33516
33542
  }
33517
33543
 
33518
33544
  // src/amaster-runtime-daemon.mjs
33519
- var CONNECTOR_VERSION = "0.1.1-beta.255";
33545
+ var CONNECTOR_VERSION = "0.1.1-beta.256";
33520
33546
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
33521
33547
  var daemonRequire = createRequire2(import.meta.url);
33522
33548
  var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
@@ -35645,6 +35671,25 @@ function redactProtectedText(value, protectedValues = []) {
35645
35671
  }
35646
35672
  return text3;
35647
35673
  }
35674
+ var RUNTIME_LOG_BATCH_MAX_ENTRIES = 32;
35675
+ var RUNTIME_LOG_BATCH_MAX_BYTES = 128 * 1024;
35676
+ var RUNTIME_LOG_BATCH_FLUSH_MS = 250;
35677
+ function runtimeLogBatchEntries(command, entries) {
35678
+ return entries.map((entry) => ({
35679
+ commandId: command.commandId,
35680
+ runId: commandRunId(command) ?? void 0,
35681
+ stream: entry.stream,
35682
+ level: entry.level,
35683
+ message: truncateText(entry.message),
35684
+ payload: entry.payload ?? {}
35685
+ }));
35686
+ }
35687
+ function runtimeLogBatchEntryBytes(command, entry) {
35688
+ return Buffer.byteLength(JSON.stringify(runtimeLogBatchEntries(command, [entry])[0]));
35689
+ }
35690
+ function runtimeLogBatchBytes(command, entries) {
35691
+ return Buffer.byteLength(JSON.stringify({ entries: runtimeLogBatchEntries(command, entries) }));
35692
+ }
35648
35693
  function createLiveOutputLogger(config, command, executorKind, protectedValues = [], onMcpToolResults = null, options = {}) {
35649
35694
  const buffers = { stdout: "", stderr: "" };
35650
35695
  const displayCounts = { stdout: 0, stderr: 0, system: 0 };
@@ -35667,6 +35712,16 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
35667
35712
  let liveLogDeliveryFailed = false;
35668
35713
  let failedLiveLogDeliveryCount = 0;
35669
35714
  let skippedLiveLogDeliveryCount = 0;
35715
+ let logEntriesAttempted = 0;
35716
+ let logEntriesAccepted = 0;
35717
+ let logEntriesInvalidDropped = 0;
35718
+ let logEntriesAmbiguousDropped = 0;
35719
+ let logBatchRequestsAttempted = 0;
35720
+ let logBatchRequestsAccepted = 0;
35721
+ let firstLogDeliveryFailureCategory = null;
35722
+ let pendingBatch = [];
35723
+ let pendingBatchBytes = runtimeLogBatchBytes(command, []);
35724
+ let pendingBatchTimer = null;
35670
35725
  const piToolArgumentTracker = executorKind === "pi" ? createPiToolArgumentAmplificationTracker(options.piToolArgumentGuard) : null;
35671
35726
  const fullTranscriptEnabled = executorKind === "pi" && readString(asRecord(asRecord(command).payload).transcriptDetail) === AMASTER_RUNTIME_TRANSCRIPT_DETAIL_FULL;
35672
35727
  const maxEntriesPerStream = parsePositiveInteger(
@@ -35723,34 +35778,66 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
35723
35778
  }
35724
35779
  nonProgressEventCount += 1;
35725
35780
  };
35726
- const deliverLiveLog = async (entry, options2 = {}) => {
35781
+ const deliverLiveLogBatch = async (entries, options2 = {}) => {
35782
+ if (entries.length === 0) return;
35727
35783
  const terminalSummary = options2.terminalSummary === true;
35728
- if (liveLogDeliveryFailed && !terminalSummary) {
35729
- skippedLiveLogDeliveryCount += 1;
35784
+ const bisectRecovery = options2.bisectRecovery === true;
35785
+ if (liveLogDeliveryFailed && !terminalSummary && !bisectRecovery) {
35786
+ skippedLiveLogDeliveryCount += entries.length;
35730
35787
  return;
35731
35788
  }
35732
- let deliveryFailed = false;
35733
- await ingestLog(
35734
- config,
35735
- command,
35736
- entry.stream,
35737
- entry.level,
35738
- truncateText(entry.message),
35739
- entry.payload ?? {},
35740
- {
35741
- timeoutMs: 1e3,
35742
- onError: (message) => {
35743
- deliveryFailed = true;
35744
- process.stderr.write(terminalSummary ? `${message}; terminal live-log summary was not delivered
35789
+ let deliveryError = null;
35790
+ if (!bisectRecovery) logEntriesAttempted += entries.length;
35791
+ logBatchRequestsAttempted += 1;
35792
+ const response = await ingestLogBatch(config, command, entries, {
35793
+ timeoutMs: 1e3,
35794
+ onError: (_message, error) => {
35795
+ deliveryError = error;
35796
+ }
35797
+ });
35798
+ if (response) {
35799
+ logEntriesAccepted += readNumber(response.acceptedCount, entries.length);
35800
+ logBatchRequestsAccepted += 1;
35801
+ return;
35802
+ }
35803
+ if (Number(deliveryError?.httpStatus) === 400) {
35804
+ firstLogDeliveryFailureCategory ??= "invalid";
35805
+ if (entries.length === 1) {
35806
+ logEntriesInvalidDropped += 1;
35807
+ failedLiveLogDeliveryCount += 1;
35808
+ return;
35809
+ }
35810
+ const midpoint = Math.floor(entries.length / 2);
35811
+ const recoveryOptions = { ...options2, bisectRecovery: true };
35812
+ await deliverLiveLogBatch(entries.slice(0, midpoint), recoveryOptions);
35813
+ await deliverLiveLogBatch(entries.slice(midpoint), recoveryOptions);
35814
+ return;
35815
+ }
35816
+ firstLogDeliveryFailureCategory ??= "ambiguous";
35817
+ logEntriesAmbiguousDropped += entries.length;
35818
+ if (!terminalSummary) liveLogDeliveryFailed = true;
35819
+ const message = `AMaster daemon could not determine whether ${entries.length} runtime log entr${entries.length === 1 ? "y was" : "ies were"} accepted`;
35820
+ process.stderr.write(terminalSummary ? `${message}; terminal live-log summary was not delivered
35745
35821
  ` : `${message}; suppressing remaining live logs for this executor turn
35746
35822
  `);
35747
- }
35748
- }
35749
- );
35750
- if (deliveryFailed) {
35751
- liveLogDeliveryFailed = true;
35752
- failedLiveLogDeliveryCount += 1;
35823
+ failedLiveLogDeliveryCount += 1;
35824
+ };
35825
+ const flushPendingBatch = () => {
35826
+ if (pendingBatchTimer) {
35827
+ clearTimeout(pendingBatchTimer);
35828
+ pendingBatchTimer = null;
35753
35829
  }
35830
+ if (pendingBatch.length === 0) return;
35831
+ const entries = pendingBatch;
35832
+ pendingBatch = [];
35833
+ pendingBatchBytes = runtimeLogBatchBytes(command, []);
35834
+ queue = queue.then(() => deliverLiveLogBatch(entries)).catch(() => {
35835
+ });
35836
+ };
35837
+ const schedulePendingBatch = () => {
35838
+ if (pendingBatchTimer) return;
35839
+ pendingBatchTimer = setTimeout(() => flushPendingBatch(), RUNTIME_LOG_BATCH_FLUSH_MS);
35840
+ pendingBatchTimer.unref?.();
35754
35841
  };
35755
35842
  const enqueue = (entry) => {
35756
35843
  const stream = entry.stream === "stderr" || entry.stream === "system" ? entry.stream : "stdout";
@@ -35759,8 +35846,19 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
35759
35846
  return;
35760
35847
  }
35761
35848
  displayCounts[stream] = (displayCounts[stream] ?? 0) + 1;
35762
- queue = queue.then(() => deliverLiveLog(entry)).catch(() => {
35763
- });
35849
+ const entryBytes = runtimeLogBatchEntryBytes(command, entry);
35850
+ let candidateBatchBytes = pendingBatchBytes + (pendingBatch.length > 0 ? 1 : 0) + entryBytes;
35851
+ if (pendingBatch.length > 0 && (pendingBatch.length >= RUNTIME_LOG_BATCH_MAX_ENTRIES || candidateBatchBytes > RUNTIME_LOG_BATCH_MAX_BYTES)) {
35852
+ flushPendingBatch();
35853
+ candidateBatchBytes = pendingBatchBytes + entryBytes;
35854
+ }
35855
+ pendingBatch.push(entry);
35856
+ pendingBatchBytes = candidateBatchBytes;
35857
+ if (pendingBatch.length >= RUNTIME_LOG_BATCH_MAX_ENTRIES || pendingBatchBytes >= RUNTIME_LOG_BATCH_MAX_BYTES) {
35858
+ flushPendingBatch();
35859
+ } else {
35860
+ schedulePendingBatch();
35861
+ }
35764
35862
  };
35765
35863
  const shouldSuppressDuplicatePiAgentMessage = (entry) => {
35766
35864
  if (executorKind !== "pi") return false;
@@ -35890,22 +35988,25 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
35890
35988
  }
35891
35989
  await observationQueue;
35892
35990
  if (observationError) throw observationError;
35991
+ flushPendingBatch();
35893
35992
  await queue;
35894
35993
  const suppressedSummaries = Object.entries(suppressedCounts).filter(([, count2]) => count2 > 0).map(([stream, count2]) => ({ stream, count: count2 }));
35895
- if (suppressedSummaries.length > 0) {
35994
+ if (suppressedSummaries.length > 0 || liveLogDeliveryFailed) {
35896
35995
  const suppressedCount = suppressedSummaries.reduce((total, summary) => total + summary.count, 0);
35897
- await deliverLiveLog({
35996
+ await deliverLiveLogBatch([{
35898
35997
  stream: "system",
35899
- level: "info",
35900
- message: `Runtime output summarized: ${suppressedCount} event(s) suppressed after ${maxEntriesPerStream} live log entries per stream`,
35998
+ level: liveLogDeliveryFailed ? "warn" : "info",
35999
+ message: liveLogDeliveryFailed ? `Runtime output delivery was incomplete: ${logEntriesAmbiguousDropped} entr${logEntriesAmbiguousDropped === 1 ? "y" : "ies"} had an ambiguous server outcome` : `Runtime output summarized: ${suppressedCount} event(s) suppressed after ${maxEntriesPerStream} live log entries per stream`,
35901
36000
  payload: {
35902
36001
  presentationKind: "output_summary",
35903
36002
  executorKind,
35904
36003
  suppressedCount,
35905
36004
  suppressedByStream: suppressedSummaries,
35906
- maxEntriesPerStream
36005
+ maxEntriesPerStream,
36006
+ deliveryIncomplete: liveLogDeliveryFailed,
36007
+ ambiguousDropped: logEntriesAmbiguousDropped
35907
36008
  }
35908
- }, { terminalSummary: true });
36009
+ }], { terminalSummary: true });
35909
36010
  }
35910
36011
  },
35911
36012
  hasStream(stream) {
@@ -35930,10 +36031,17 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
35930
36031
  const normalizedFloodLimitBytes = readNumber(floodLimitBytes, 0);
35931
36032
  return {
35932
36033
  liveLogDelivery: {
35933
- status: liveLogDeliveryFailed ? "partial" : "complete",
36034
+ status: liveLogDeliveryFailed || logEntriesInvalidDropped > 0 ? "partial" : "complete",
35934
36035
  failed: failedLiveLogDeliveryCount,
35935
36036
  skipped: skippedLiveLogDeliveryCount
35936
36037
  },
36038
+ logEntriesAttempted,
36039
+ logEntriesAccepted,
36040
+ logEntriesInvalidDropped,
36041
+ logEntriesAmbiguousDropped,
36042
+ logBatchRequestsAttempted,
36043
+ logBatchRequestsAccepted,
36044
+ ...firstLogDeliveryFailureCategory ? { firstLogDeliveryFailureCategory } : {},
35937
36045
  rawBytesByStream,
35938
36046
  rawOutputBytes,
35939
36047
  retainedBytesByStream,
@@ -36573,6 +36681,15 @@ async function ingestLog(config, command, stream, level, message, payload = {},
36573
36681
  payload
36574
36682
  }, options);
36575
36683
  }
36684
+ async function ingestLogBatch(config, command, entries, options = {}) {
36685
+ const connectorId = requireConnectorId(config);
36686
+ return await bestEffortPostJson(
36687
+ config,
36688
+ `/api/amaster/runtime-connectors/${connectorId}/ingest/logs/batch`,
36689
+ { entries: runtimeLogBatchEntries(command, entries) },
36690
+ options
36691
+ );
36692
+ }
36576
36693
  function parsedUsageCostCents(usage) {
36577
36694
  const costUsd = readNumber(asRecord(usage).costUsd, 0);
36578
36695
  if (!Number.isFinite(costUsd) || costUsd <= 0) return 0;
@@ -7,7 +7,7 @@ import { homedir, hostname } from "node:os";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { BUILD_SUPPORTED_CAPABILITIES } from "./amaster-runtime-daemon/capability-registry.mjs";
9
9
 
10
- const CONNECTOR_VERSION = "0.1.1-beta.255";
10
+ const CONNECTOR_VERSION = "0.1.1-beta.256";
11
11
 
12
12
  const CONFIG_KEY_MAP = new Map([
13
13
  ["server_url", "AMASTER_EMPLOYEE_SERVER_URL"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/employee-runtime-connector",
3
- "version": "0.1.1-beta.255",
3
+ "version": "0.1.1-beta.256",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",